diff --git a/resources/3rdparty/exprtk/exprtk.hpp b/resources/3rdparty/exprtk/exprtk.hpp
index 7581c4c8f..04f37d9a1 100755
--- a/resources/3rdparty/exprtk/exprtk.hpp
+++ b/resources/3rdparty/exprtk/exprtk.hpp
@@ -2,7 +2,7 @@
  ******************************************************************
  *           C++ Mathematical Expression Toolkit Library          *
  *                                                                *
- * Author: Arash Partow (1999-2015)                               *
+ * Author: Arash Partow (1999-2016)                               *
  * URL: http://www.partow.net/programming/exprtk/index.html       *
  *                                                                *
  * Copyright notice:                                              *
@@ -27,7 +27,7 @@
  * (12) (x ilike 's*ri?g') and [y < (3 z^7 + w)]                  *
  *                                                                *
  ******************************************************************
-*/
+ */
 
 
 #ifndef INCLUDE_EXPRTK_HPP
@@ -37,8 +37,10 @@
 #include <algorithm>
 #include <cctype>
 #include <cmath>
+#include <complex>
 #include <cstdio>
 #include <cstdlib>
+#include <cstring>
 #include <deque>
 #include <exception>
 #include <functional>
@@ -53,29986 +55,34930 @@
 #include <utility>
 #include <vector>
 
+// If this is set, this puts in place our modifications to ExprTk. That is: case sensitive and underscore is a valid character.
+#define MODIFICATION
 
 namespace exprtk
 {
-   #if exprtk_enable_debugging
-     #define exprtk_debug(params) printf params
-   #else
-     #define exprtk_debug(params) (void)0
-   #endif
-
-   namespace details
-   {
-      inline bool is_whitespace(const char c)
-      {
-         return (' '  == c) || ('\n' == c) ||
-                ('\r' == c) || ('\t' == c) ||
-                ('\b' == c) || ('\v' == c) ||
-                ('\f' == c) ;
-      }
-
-      inline bool is_operator_char(const char c)
-      {
-         return ('+' == c) || ('-' == c) ||
-                ('*' == c) || ('/' == c) ||
-                ('^' == c) || ('<' == c) ||
-                ('>' == c) || ('=' == c) ||
-                (',' == c) || ('!' == c) ||
-                ('(' == c) || (')' == c) ||
-                ('[' == c) || (']' == c) ||
-                ('{' == c) || ('}' == c) ||
-                ('%' == c) || (':' == c) ||
-                ('?' == c) || ('&' == c) ||
-                ('|' == c) || (';' == c) ;
-      }
-
-      inline bool is_letter(const char c)
-      {
-         return (('a' <= c) && (c <= 'z')) ||
-                (('A' <= c) && (c <= 'Z')) ;
-      }
-
-      inline bool is_digit(const char c)
-      {
-         return ('0' <= c) && (c <= '9');
-      }
-
-      inline bool is_letter_or_digit(const char c)
-      {
-         return is_letter(c) || is_digit(c);
-      }
-
-      inline bool is_left_bracket(const char c)
-      {
-         return ('(' == c) || ('[' == c) || ('{' == c);
-      }
-
-      inline bool is_right_bracket(const char c)
-      {
-         return (')' == c) || (']' == c) || ('}' == c);
-      }
-
-      inline bool is_bracket(const char c)
-      {
-         return is_left_bracket(c) || is_right_bracket(c);
-      }
-
-      inline bool is_sign(const char c)
-      {
-         return ('+' == c) || ('-' == c);
-      }
-
-      inline bool is_invalid(const char c)
-      {
-         return !is_whitespace   (c) &&
-                !is_operator_char(c) &&
-                !is_letter       (c) &&
-                !is_digit        (c) &&
-                ('.'  != c)          &&
-                ('_'  != c)          &&
-                ('$'  != c)          &&
-                ('~'  != c)          &&
-                ('\'' != c);
-      }
-
-      inline bool imatch(const char c1, const char c2)
-      {
-         return std::tolower(c1) == std::tolower(c2);
-      }
-
-      inline bool imatch(const std::string& s1, const std::string& s2)
-      {
-         if (s1.size() == s2.size())
-         {
-            for (std::size_t i = 0; i < s1.size(); ++i)
-            {
-               if (std::tolower(s1[i]) != std::tolower(s2[i]))
-               {
-                  return false;
-               }
-            }
-
-            return true;
-         }
-
-         return false;
-      }
-
-      inline bool is_valid_sf_symbol(const std::string& symbol)
-      {
-         // Special function: $f12 or $F34
-         return (4 == symbol.size())  &&
-                ('$' == symbol[0])    &&
-                imatch('f',symbol[1]) &&
-                is_digit(symbol[2])   &&
-                is_digit(symbol[3]);
-      }
-
-      inline std::string to_str(int i)
-      {
-         if (0 == i)
-            return std::string("0");
-
-         std::string result;
-         bool negative = (i < 0);
-
-         if (negative) i *= -1;
-
-         while (i)
-         {
-            char digit = '0' + char(i % 10);
-            result = (digit + result);
-            i /= 10;
-         }
-
-         if (negative)
-            result = "-" + result;
-
-         return result;
-      }
-
-      inline bool is_hex_digit(const std::string::value_type digit)
-      {
-         return (('0' <= digit) && (digit <= '9')) ||
-                (('A' <= digit) && (digit <= 'F')) ||
-                (('a' <= digit) && (digit <= 'f')) ;
-      }
-
-      inline unsigned char hex_to_bin(unsigned char h)
-      {
-         if (('0' <= h) && (h <= '9'))
-            return (h - '0');
-         else
-            return (std::toupper(h) - 'A');
-      }
-
-      template <typename Iterator>
-      inline void 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)))
-            )
-         {
-            result = hex_to_bin(*(itr + 2)) << 4 | hex_to_bin(*(itr + 3));
-            itr += 3;
-         }
-         else
-            result = '\0';
-      }
-
-      inline void cleanup_escapes(std::string& s)
-      {
-         std::string::iterator itr1 = s.begin();
-         std::string::iterator itr2 = s.begin();
-         std::string::iterator end  = s.end  ();
-         std::size_t removal_count  = 0;
-
-         while (end != itr1)
-         {
-            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;
-               }
-            }
-
-            if (itr1 != itr2)
-            {
-               (*itr2) = (*itr1);
-            }
-
-            ++itr1;
-            ++itr2;
-         }
-
-         s.resize(s.size() - removal_count);
-      }
-
-      class build_string
-      {
-      public:
-
-         build_string(const std::size_t& initial_size = 64)
-         {
-            data_.reserve(initial_size);
-         }
-
-         inline build_string& operator << (const std::string& s)
-         {
-            data_ += s;
-            return (*this);
-         }
-
-         inline build_string& operator << (const char* s)
-         {
-            data_ += std::string(s);
-            return (*this);
-         }
-
-         inline operator std::string () const
-         {
-            return data_;
-         }
-
-         inline std::string as_string() const
-         {
-            return data_;
-         }
-
-      private:
-
-         std::string data_;
-      };
-
-      struct ilesscompare
-      {
-         inline bool operator()(const std::string& s1, const std::string& s2) const
-         {
-            const std::size_t length = std::min(s1.size(),s2.size());
-
-            for (std::size_t i = 0; i < length;  ++i)
-            {
-               const char c1 = static_cast<char>(std::tolower(s1[i]));
-               const char c2 = static_cast<char>(std::tolower(s2[i]));
-
-               if (c1 > c2)
-                  return false;
-               else if (c1 < c2)
-                  return true;
-            }
-
-            return s1.size() < s2.size();
-         }
-      };
-
-      static const std::string reserved_words[] =
-                                  {
-                                    "break",  "case",  "continue",  "default",  "false",  "for",
-                                    "if", "else", "ilike",  "in", "like", "and",  "nand", "nor",
-                                    "not",  "null",  "or",   "repeat",  "shl",  "shr",   "swap",
-                                    "switch", "true",  "until", "var",  "while", "xnor",  "xor",
-                                    "&", "|"
-                                  };
-
-      static const std::size_t reserved_words_size = sizeof(reserved_words) / sizeof(std::string);
-
-      static const std::string reserved_symbols[] =
-                                  {
-                                    "abs",  "acos",  "acosh",  "and",  "asin",  "asinh", "atan",
-                                    "atanh", "atan2", "avg",  "break", "case", "ceil",  "clamp",
-                                    "continue",   "cos",   "cosh",   "cot",   "csc",  "default",
-                                    "deg2grad",  "deg2rad",   "equal",  "erf",   "erfc",  "exp",
-                                    "expm1",  "false",   "floor",  "for",   "frac",  "grad2deg",
-                                    "hypot", "iclamp", "if",  "else", "ilike", "in",  "inrange",
-                                    "like",  "log",  "log10", "log2",  "logn",  "log1p", "mand",
-                                    "max", "min",  "mod", "mor",  "mul", "ncdf",  "nand", "nor",
-                                    "not",   "not_equal",   "null",   "or",   "pow",  "rad2deg",
-                                    "repeat", "root",  "round", "roundn",  "sec", "sgn",  "shl",
-                                    "shr",  "sin",  "sinc",   "sinh",  "sqrt",  "sum",   "swap",
-                                    "switch", "tan",  "tanh", "true",  "trunc", "until",  "var",
-                                    "while", "xnor", "xor", "&", "|"
-                                  };
-
-      static const std::size_t reserved_symbols_size = sizeof(reserved_symbols) / sizeof(std::string);
-
-      inline bool is_reserved_word(const std::string& symbol)
-      {
-         for (std::size_t i = 0; i < reserved_words_size; ++i)
-         {
-            if (imatch(symbol,reserved_words[i]))
-            {
-               return true;
-            }
-         }
-
-         return false;
-      }
-
-      inline bool is_reserved_symbol(const std::string& symbol)
-      {
-         for (std::size_t i = 0; i < reserved_symbols_size; ++i)
-         {
-            if (imatch(symbol,reserved_symbols[i]))
-            {
-               return true;
+#ifdef exprtk_enable_debugging
+#define exprtk_debug(params) printf params
+#else
+#define exprtk_debug(params) (void)0
+#endif
+    
+    namespace details
+    {
+        typedef unsigned char uchar_t;
+        typedef char           char_t;
+        
+        inline bool is_whitespace(const char_t c)
+        {
+            return (' '  == c) || ('\n' == c) ||
+            ('\r' == c) || ('\t' == c) ||
+            ('\b' == c) || ('\v' == c) ||
+            ('\f' == c) ;
+        }
+        
+        inline bool is_operator_char(const char_t c)
+        {
+            return ('+' == c) || ('-' == c) ||
+            ('*' == c) || ('/' == c) ||
+            ('^' == c) || ('<' == c) ||
+            ('>' == c) || ('=' == c) ||
+            (',' == c) || ('!' == c) ||
+            ('(' == c) || (')' == c) ||
+            ('[' == c) || (']' == c) ||
+            ('{' == c) || ('}' == c) ||
+            ('%' == c) || (':' == c) ||
+            ('?' == c) || ('&' == c) ||
+            ('|' == c) || (';' == c) ;
+        }
+        
+        inline bool is_letter(const char_t c)
+        {
+            return (('a' <= c) && (c <= 'z')) ||
+            (('A' <= c) && (c <= 'Z')) ;
+        }
+        
+        inline bool is_digit(const char_t c)
+        {
+            return ('0' <= c) && (c <= '9');
+        }
+        
+        inline bool is_letter_or_digit(const char_t c)
+        {
+            return is_letter(c) || is_digit(c);
+        }
+        
+        inline bool is_left_bracket(const char_t c)
+        {
+            return ('(' == c) || ('[' == c) || ('{' == c);
+        }
+        
+        inline bool is_right_bracket(const char_t c)
+        {
+            return (')' == c) || (']' == c) || ('}' == c);
+        }
+        
+        inline bool is_bracket(const char_t c)
+        {
+            return is_left_bracket(c) || is_right_bracket(c);
+        }
+        
+        inline bool is_sign(const char_t c)
+        {
+            return ('+' == c) || ('-' == c);
+        }
+        
+        inline bool is_invalid(const char_t c)
+        {
+            return !is_whitespace   (c) &&
+            !is_operator_char(c) &&
+            !is_letter       (c) &&
+            !is_digit        (c) &&
+#ifndef MODIFICATION
+            ('.'  != c)          &&
+            ('_'  != c)          &&
+#endif
+            ('$'  != c)          &&
+            ('~'  != c)          &&
+            ('\'' != c);
+        }
+        
+        inline bool imatch(const char_t c1, const char_t c2)
+        {
+#ifdef MODIFICATION
+            return c1 == c2;
+#else
+            return std::tolower(c1) == std::tolower(c2);
+#endif
+        }
+        
+        inline bool imatch(const std::string& s1, const std::string& s2)
+        {
+            if (s1.size() == s2.size())
+            {
+                for (std::size_t i = 0; i < s1.size(); ++i)
+                {
+#ifdef MODIFICATION
+                    if (s1[i] != s2[i])
+#else
+                    if (std::tolower(s1[i]) != std::tolower(s2[i]))
+#endif
+                    {
+                        return false;
+                    }
+                }
+                
+                return true;
             }
-         }
-
-         return false;
-      }
-
-      struct cs_match
-      {
-         static inline bool cmp(const char c0, const char c1)
-         {
-            return (c0 == c1);
-         }
-      };
-
-      struct cis_match
-      {
-         static inline bool cmp(const char c0, const char c1)
-         {
-            return (std::tolower(c0) == std::tolower(c1));
-         }
-      };
-
-      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 typename std::iterator_traits<Iterator>::value_type& zero_or_more,
-                             const typename std::iterator_traits<Iterator>::value_type& zero_or_one)
-      {
-         if (0 == std::distance(data_begin,data_end))
-         {
+            
             return false;
-         }
-
-         Iterator d_itr = data_begin;
-         Iterator p_itr = pattern_begin;
-         Iterator c_itr = data_begin;
-         Iterator m_itr = data_begin;
-
-         while ((data_end != d_itr) && (zero_or_more != (*p_itr)))
-         {
-            if ((!Compare::cmp((*p_itr),(*d_itr))) && (zero_or_one != (*p_itr)))
-            {
-               return false;
-            }
-
-            ++p_itr;
-            ++d_itr;
-         }
-
-         while (data_end != d_itr)
-         {
-            if (zero_or_more == (*p_itr))
-            {
-               if (pattern_end == (++p_itr))
-               {
-                  return true;
-               }
-
-               m_itr = p_itr;
-               c_itr = d_itr;
-               ++c_itr;
+        }
+        
+        inline bool is_valid_sf_symbol(const std::string& symbol)
+        {
+            // Special function: $f12 or $F34
+            return (4 == symbol.size())  &&
+            ('$' == symbol[0])    &&
+            imatch('f',symbol[1]) &&
+            is_digit(symbol[2])   &&
+            is_digit(symbol[3]);
+        }
+        
+        inline const char& front(const std::string& s)
+        {
+            return s[0];
+        }
+        
+        inline const char& back(const std::string& s)
+        {
+            return s[s.size() - 1];
+        }
+        
+        inline std::string to_str(int i)
+        {
+            if (0 == i)
+                return std::string("0");
+            
+            std::string result;
+            
+            if (i < 0)
+            {
+                for ( ; i; i /= 10)
+                {
+                    result += '0' + char(-(i % 10));
+                }
+                
+                result += '-';
             }
-            else if ((Compare::cmp((*p_itr),(*d_itr))) || (zero_or_one == (*p_itr)))
+            else
             {
-               ++p_itr;
-               ++d_itr;
+                for ( ; i; i /= 10)
+                {
+                    result += '0' + char(i % 10);
+                }
             }
+            
+            std::reverse(result.begin(), result.end());
+            
+            return result;
+        }
+        
+        inline bool is_hex_digit(const std::string::value_type digit)
+        {
+            return (('0' <= digit) && (digit <= '9')) ||
+            (('A' <= digit) && (digit <= 'F')) ||
+            (('a' <= digit) && (digit <= 'f')) ;
+        }
+        
+        inline uchar_t hex_to_bin(uchar_t h)
+        {
+            if (('0' <= h) && (h <= '9'))
+                return (h - '0');
             else
+                return static_cast<unsigned char>(std::toupper(h) - 'A');
+        }
+        
+        template <typename Iterator>
+        inline void 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)))
+                )
             {
-               p_itr = m_itr;
-               d_itr = c_itr++;
+                result = hex_to_bin(*(itr + 2)) << 4 | hex_to_bin(*(itr + 3));
+                itr += 3;
             }
-         }
-
-         while ((p_itr != pattern_end) && (zero_or_more == (*p_itr))) { ++p_itr; }
-
-         return (p_itr == pattern_end);
-      }
-
-      inline bool wc_match(const std::string& wild_card,
-                           const std::string& str)
-      {
-         return match_impl<const char*,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*,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,
-                                 const std::string& str,
-                                 std::size_t&       diff_index,
-                                 char&              diff_value)
-      {
-         if (str.empty() || pattern.empty())
+            else
+                result = '\0';
+        }
+        
+        inline void cleanup_escapes(std::string& s)
+        {
+            typedef std::string::iterator str_itr_t;
+            
+            str_itr_t itr1 = s.begin();
+            str_itr_t itr2 = s.begin();
+            str_itr_t end  = s.end  ();
+            
+            std::size_t removal_count  = 0;
+            
+            while (end != itr1)
+            {
+                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;
+                    }
+                }
+                
+                if (itr1 != itr2)
+                {
+                    (*itr2) = (*itr1);
+                }
+                
+                ++itr1;
+                ++itr2;
+            }
+            
+            s.resize(s.size() - removal_count);
+        }
+        
+        class build_string
+        {
+        public:
+            
+            build_string(const std::size_t& initial_size = 64)
+            {
+                data_.reserve(initial_size);
+            }
+            
+            inline build_string& operator << (const std::string& s)
+            {
+                data_ += s;
+                return (*this);
+            }
+            
+            inline build_string& operator << (const char* s)
+            {
+                data_ += std::string(s);
+                return (*this);
+            }
+            
+            inline operator std::string () const
+            {
+                return data_;
+            }
+            
+            inline std::string as_string() const
+            {
+                return data_;
+            }
+            
+        private:
+            
+            std::string data_;
+        };
+        
+        struct ilesscompare
+        {
+            inline bool operator()(const std::string& s1, const std::string& s2) const
+            {
+                const std::size_t length = std::min(s1.size(),s2.size());
+                
+                for (std::size_t i = 0; i < length;  ++i)
+                {
+#ifdef MODIFICATION
+                    const char_t c1 = static_cast<char>(s1[i]);
+                    const char_t c2 = static_cast<char>(s2[i]);
+#else
+                    const char_t c1 = static_cast<char>(std::tolower(s1[i]));
+                    const char_t c2 = static_cast<char>(std::tolower(s2[i]));
+#endif
+                    
+                    if (c1 > c2)
+                        return false;
+                    else if (c1 < c2)
+                        return true;
+                }
+                
+                return s1.size() < s2.size();
+            }
+        };
+        
+        static const std::string reserved_words[] =
+        {
+            "break",  "case",  "continue",  "default",  "false",  "for",
+            "if", "else", "ilike",  "in", "like", "and",  "nand", "nor",
+            "not",  "null",  "or",   "repeat", "return",  "shl",  "shr",
+            "swap", "switch", "true",  "until", "var",  "while", "xnor",
+            "xor", "&", "|"
+        };
+        
+        static const std::size_t reserved_words_size = sizeof(reserved_words) / sizeof(std::string);
+        
+        static const std::string reserved_symbols[] =
+        {
+            "abs",  "acos",  "acosh",  "and",  "asin",  "asinh", "atan",
+            "atanh", "atan2", "avg",  "break", "case", "ceil",  "clamp",
+            "continue",   "cos",   "cosh",   "cot",   "csc",  "default",
+            "deg2grad",  "deg2rad",   "equal",  "erf",   "erfc",  "exp",
+            "expm1",  "false",   "floor",  "for",   "frac",  "grad2deg",
+            "hypot", "iclamp", "if",  "else", "ilike", "in",  "inrange",
+            "like",  "log",  "log10", "log2",  "logn",  "log1p", "mand",
+            "max", "min",  "mod", "mor",  "mul", "ncdf",  "nand", "nor",
+            "not",   "not_equal",   "null",   "or",   "pow",  "rad2deg",
+            "repeat", "return", "root", "round", "roundn", "sec", "sgn",
+            "shl", "shr", "sin", "sinc", "sinh", "sqrt",  "sum", "swap",
+            "switch", "tan",  "tanh", "true",  "trunc", "until",  "var",
+            "while", "xnor", "xor", "&", "|"
+        };
+        
+        static const std::size_t reserved_symbols_size = sizeof(reserved_symbols) / sizeof(std::string);
+        
+        static const std::string base_function_list[] =
+        {
+            "abs", "acos",  "acosh", "asin",  "asinh", "atan",  "atanh",
+            "atan2",  "avg",  "ceil",  "clamp",  "cos",  "cosh",  "cot",
+            "csc",  "equal",  "erf",  "erfc",  "exp",  "expm1", "floor",
+            "frac", "hypot", "iclamp",  "like", "log", "log10",  "log2",
+            "logn", "log1p", "mand", "max", "min", "mod", "mor",  "mul",
+            "ncdf",  "pow",  "root",  "round",  "roundn",  "sec", "sgn",
+            "sin", "sinc", "sinh", "sqrt", "sum", "swap", "tan", "tanh",
+            "trunc",  "not_equal",  "inrange",  "deg2grad",   "deg2rad",
+            "rad2deg", "grad2deg"
+        };
+        
+        static const std::size_t base_function_list_size = sizeof(base_function_list) / sizeof(std::string);
+        
+        static const std::string logic_ops_list[] =
+        {
+            "and", "nand", "nor", "not", "or",  "xnor", "xor", "&", "|"
+        };
+        
+        static const std::size_t logic_ops_list_size = sizeof(logic_ops_list) / sizeof(std::string);
+        
+        static const std::string cntrl_struct_list[] =
+        {
+            "if", "switch", "for", "while", "repeat"
+        };
+        
+        static const std::size_t cntrl_struct_list_size = sizeof(cntrl_struct_list) / sizeof(std::string);
+        
+        static const std::string arithmetic_ops_list[] =
+        {
+            "+", "-", "*", "/", "%", "^"
+        };
+        
+        static const std::size_t arithmetic_ops_list_size = sizeof(arithmetic_ops_list) / sizeof(std::string);
+        
+        static const std::string assignment_ops_list[] =
+        {
+            ":=", "+=", "-=",
+            "*=", "/=", "%="
+        };
+        
+        static const std::size_t assignment_ops_list_size = sizeof(assignment_ops_list) / sizeof(std::string);
+        
+        static const std::string inequality_ops_list[] =
+        {
+            "<",  "<=", "==",
+            "=",  "!=", "<>",
+            ">=",  ">"
+        };
+        
+        static const std::size_t inequality_ops_list_size = sizeof(inequality_ops_list) / sizeof(std::string);
+        
+        inline bool is_reserved_word(const std::string& symbol)
+        {
+            for (std::size_t i = 0; i < reserved_words_size; ++i)
+            {
+                if (imatch(symbol,reserved_words[i]))
+                {
+                    return true;
+                }
+            }
+            
             return false;
-         else if ('*' == pattern[0])
+        }
+        
+        inline bool is_reserved_symbol(const std::string& symbol)
+        {
+            for (std::size_t i = 0; i < reserved_symbols_size; ++i)
+            {
+                if (imatch(symbol,reserved_symbols[i]))
+                {
+                    return true;
+                }
+            }
+            
             return false;
-
-         typedef std::string::const_iterator itr_t;
-
-         itr_t p_itr = pattern.begin();
-         itr_t s_itr = str    .begin();
-
-         itr_t p_end = pattern.end();
-         itr_t s_end = str    .end();
-
-         while ((s_end != s_itr) && (p_end != p_itr))
-         {
-            if ('*' == (*p_itr))
+        }
+        
+        inline bool is_base_function(const std::string& function_name)
+        {
+            for (std::size_t i = 0; i < base_function_list_size; ++i)
+            {
+                if (imatch(function_name,base_function_list[i]))
+                {
+                    return true;
+                }
+            }
+            
+            return false;
+        }
+        
+        inline bool is_control_struct(const std::string& cntrl_strct)
+        {
+            for (std::size_t i = 0; i < cntrl_struct_list_size; ++i)
+            {
+                if (imatch(cntrl_strct,cntrl_struct_list[i]))
+                {
+                    return true;
+                }
+            }
+            
+            return false;
+        }
+        
+        inline bool is_logic_opr(const std::string& lgc_opr)
+        {
+            for (std::size_t i = 0; i < logic_ops_list_size; ++i)
+            {
+                if (imatch(lgc_opr,logic_ops_list[i]))
+                {
+                    return true;
+                }
+            }
+            
+            return false;
+        }
+        
+        struct cs_match
+        {
+            static inline bool cmp(const char_t c0, const char_t c1)
             {
-               const char target = std::toupper(*(p_itr - 1));
-
-               if ('*' == target)
-               {
-                  diff_index = std::distance(str.begin(),s_itr);
-                  diff_value = std::toupper(*p_itr);
-
-                  return false;
-               }
-               else
-                  ++p_itr;
-
-               while (s_itr != s_end)
-               {
-                  if (target != std::toupper(*s_itr))
-                     break;
-                  else
-                     ++s_itr;
-               }
-
-               continue;
+                return (c0 == c1);
             }
-            else if (
-                      ('?' != *p_itr) &&
-                      std::toupper(*p_itr) != std::toupper(*s_itr)
-                    )
+        };
+        
+        struct cis_match
+        {
+            static inline bool cmp(const char_t c0, const char_t c1)
             {
-               diff_index = std::distance(str.begin(),s_itr);
-               diff_value = std::toupper(*p_itr);
-
-               return false;
+#ifdef MODIFICATION
+                return (c0 == c1);
+#else
+                return (std::tolower(c0) == std::tolower(c1));
+#endif
             }
-
-            ++p_itr;
-            ++s_itr;
-         }
-
-         return (
-                  (s_end == s_itr) &&
-                  (
-                    (p_end ==  p_itr) ||
-                    ('*'   == *p_itr)
-                  )
-                );
-      }
-
-      static const double pow10[] = {
-                                       1.0,
-                                       1.0E+001, 1.0E+002, 1.0E+003, 1.0E+004,
-                                       1.0E+005, 1.0E+006, 1.0E+007, 1.0E+008,
-                                       1.0E+009, 1.0E+010, 1.0E+011, 1.0E+012,
-                                       1.0E+013, 1.0E+014, 1.0E+015, 1.0E+016
-                                    };
-
-     static const std::size_t pow10_size = sizeof(pow10) / sizeof(double);
-
-      namespace numeric
-      {
-         namespace constant
-         {
-            static const double e       =  2.718281828459045235360;
-            static const double pi      =  3.141592653589793238462;
-            static const double pi_2    =  1.570796326794896619231;
-            static const double pi_4    =  0.785398163397448309616;
-            static const double pi_180  =  0.017453292519943295769;
-            static const double _1_pi   =  0.318309886183790671538;
-            static const double _2_pi   =  0.636619772367581343076;
-            static const double _180_pi = 57.295779513082320876798;
-            static const double log2    =  0.693147180559945309417;
-            static const double sqrt2   =  1.414213562373095048801;
-         }
-
-         namespace details
-         {
-            struct unknown_type_tag {};
-            struct real_type_tag    {};
-            struct int_type_tag     {};
-
-            template <typename T>
-            struct number_type { typedef unknown_type_tag type; };
-
-            #define exprtk_register_real_type_tag(T)                          \
-            template<> struct number_type<T> { typedef real_type_tag type; }; \
-
-            #define exprtk_register_int_type_tag(T)                          \
-            template<> struct number_type<T> { typedef int_type_tag type; }; \
-
-            exprtk_register_real_type_tag(double     )
-            exprtk_register_real_type_tag(long double)
-            exprtk_register_real_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)
-
-            #undef exprtk_register_real_type_tag
-            #undef exprtk_register_int_type_tag
-
+        };
+        
+        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 typename std::iterator_traits<Iterator>::value_type& zero_or_more,
+                               const typename std::iterator_traits<Iterator>::value_type& zero_or_one)
+        {
+            if (0 == std::distance(data_begin,data_end))
+            {
+                return false;
+            }
+            
+            Iterator d_itr = data_begin;
+            Iterator p_itr = pattern_begin;
+            Iterator c_itr = data_begin;
+            Iterator m_itr = data_begin;
+            
+            while ((data_end != d_itr) && (zero_or_more != (*p_itr)))
+            {
+                if ((!Compare::cmp((*p_itr),(*d_itr))) && (zero_or_one != (*p_itr)))
+                {
+                    return false;
+                }
+                
+                ++p_itr;
+                ++d_itr;
+            }
+            
+            while (data_end != d_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++;
+                }
+            }
+            
+            while ((p_itr != pattern_end) && (zero_or_more == (*p_itr))) { ++p_itr; }
+            
+            return (p_itr == pattern_end);
+        }
+        
+        inline bool wc_match(const std::string& wild_card,
+                             const std::string& str)
+        {
+            return match_impl<const char*,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*,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,
+                                   const std::string& str,
+                                   std::size_t&       diff_index,
+                                   char&              diff_value)
+        {
+            if (str.empty())
+            {
+                return ("Z" == pattern);
+            }
+            else if ('*' == pattern[0])
+                return false;
+            
+            typedef std::string::const_iterator itr_t;
+            
+            itr_t p_itr = pattern.begin();
+            itr_t s_itr = str    .begin();
+            
+            itr_t p_end = pattern.end();
+            itr_t s_end = str    .end();
+            
+            while ((s_end != s_itr) && (p_end != p_itr))
+            {
+                if ('*' == (*p_itr))
+                {
+                    const char_t target = static_cast<char>(std::toupper(*(p_itr - 1)));
+                    
+                    if ('*' == target)
+                    {
+                        diff_index = std::distance(str.begin(),s_itr);
+                        diff_value = static_cast<char>(std::toupper(*p_itr));
+                        
+                        return false;
+                    }
+                    else
+                        ++p_itr;
+                    
+                    while (s_itr != s_end)
+                    {
+                        if (target != std::toupper(*s_itr))
+                            break;
+                        else
+                            ++s_itr;
+                    }
+                    
+                    continue;
+                }
+                else if (
+                         ('?' != *p_itr) &&
+                         std::toupper(*p_itr) != std::toupper(*s_itr)
+                         )
+                {
+                    diff_index = std::distance(str.begin(),s_itr);
+                    diff_value = static_cast<char>(std::toupper(*p_itr));
+                    
+                    return false;
+                }
+                
+                ++p_itr;
+                ++s_itr;
+            }
+            
+            return (
+                    (s_end == s_itr) &&
+                    (
+                     (p_end ==  p_itr) ||
+                     ('*'   == *p_itr)
+                     )
+                    );
+        }
+        
+        static const double pow10[] = {
+            1.0,
+            1.0E+001, 1.0E+002, 1.0E+003, 1.0E+004,
+            1.0E+005, 1.0E+006, 1.0E+007, 1.0E+008,
+            1.0E+009, 1.0E+010, 1.0E+011, 1.0E+012,
+            1.0E+013, 1.0E+014, 1.0E+015, 1.0E+016
+        };
+        
+        static const std::size_t pow10_size = sizeof(pow10) / sizeof(double);
+        
+        namespace numeric
+        {
+            namespace constant
+            {
+                static const double e       =  2.71828182845904523536028747135266249775724709369996;
+                static const double pi      =  3.14159265358979323846264338327950288419716939937510;
+                static const double pi_2    =  1.57079632679489661923132169163975144209858469968755;
+                static const double pi_4    =  0.78539816339744830961566084581987572104929234984378;
+                static const double pi_180  =  0.01745329251994329576923690768488612713442871888542;
+                static const double _1_pi   =  0.31830988618379067153776752674502872406891929148091;
+                static const double _2_pi   =  0.63661977236758134307553505349005744813783858296183;
+                static const double _180_pi = 57.29577951308232087679815481410517033240547246656443;
+                static const double log2    =  0.69314718055994530941723212145817656807550013436026;
+                static const double sqrt2   =  1.41421356237309504880168872420969807856967187537695;
+            }
+            
+            namespace details
+            {
+                struct unknown_type_tag {};
+                struct real_type_tag    {};
+                struct complex_type_tag {};
+                struct int_type_tag     {};
+                
+                template <typename T>
+                struct number_type { typedef unknown_type_tag type; };
+                
+#define exprtk_register_real_type_tag(T)                          \
+template<> struct number_type<T> { typedef real_type_tag type; }; \
+
+#define exprtk_register_complex_type_tag(T)     \
+template<> struct number_type<std::complex<T> > \
+{ typedef complex_type_tag type; };             \
+
+#define exprtk_register_int_type_tag(T)                          \
+template<> struct number_type<T> { typedef int_type_tag type; }; \
+
+                exprtk_register_real_type_tag(double     )
+                exprtk_register_real_type_tag(long double)
+                exprtk_register_real_type_tag(float      )
+                
+                exprtk_register_complex_type_tag(double     )
+                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)
+                
+#undef exprtk_register_real_type_tag
+#undef exprtk_register_int_type_tag
+                
+                template <typename T>
+                struct epsilon_type
+                {
+                    static inline T value()
+                    {
+                        const T epsilon = T(0.0000000001);
+                        return epsilon;
+                    }
+                };
+                
+                template <>
+                struct epsilon_type <float>
+                {
+                    static inline float value()
+                    {
+                        const float epsilon = float(0.000001f);
+                        return epsilon;
+                    }
+                };
+                
+                template <>
+                struct epsilon_type <long double>
+                {
+                    static inline long double value()
+                    {
+                        const long double epsilon = (long double)(0.000000000001);
+                        return epsilon;
+                    }
+                };
+                
+                template <typename T>
+                inline bool is_nan_impl(const T v, real_type_tag)
+                {
+                    return std::not_equal_to<T>()(v,v);
+                }
+                
+                template <typename T>
+                inline int to_int32_impl(const T v, real_type_tag)
+                {
+                    return static_cast<int>(v);
+                }
+                
+                template <typename T>
+                inline long long int to_int64_impl(const T v, real_type_tag)
+                {
+                    return static_cast<long long int>(v);
+                }
+                
+                template <typename T>
+                inline bool is_true_impl(const T v)
+                {
+                    return std::not_equal_to<T>()(T(0),v);
+                }
+                
+                template <typename T>
+                inline bool is_false_impl(const T v)
+                {
+                    return std::equal_to<T>()(T(0),v);
+                }
+                
+                template <typename T>
+                inline T abs_impl(const T v, real_type_tag)
+                {
+                    return ((v < T(0)) ? -v : v);
+                }
+                
+                template <typename T>
+                inline T min_impl(const T v0, const T v1, real_type_tag)
+                {
+                    return std::min<T>(v0,v1);
+                }
+                
+                template <typename T>
+                inline T max_impl(const T v0, const T v1, real_type_tag)
+                {
+                    return std::max<T>(v0,v1);
+                }
+                
+                template <typename T>
+                inline T equal_impl(const T v0, const T v1, real_type_tag)
+                {
+                    const T epsilon = epsilon_type<T>::value();
+                    return (abs_impl(v0 - v1,real_type_tag()) <= (std::max(T(1),std::max(abs_impl(v0,real_type_tag()),abs_impl(v1,real_type_tag()))) * epsilon)) ? T(1) : T(0);
+                }
+                
+                inline float equal_impl(const float v0, const float v1, real_type_tag)
+                {
+                    const float epsilon = epsilon_type<float>::value();
+                    return (abs_impl(v0 - v1,real_type_tag()) <= (std::max(1.0f,std::max(abs_impl(v0,real_type_tag()),abs_impl(v1,real_type_tag()))) * epsilon)) ? 1.0f : 0.0f;
+                }
+                
+                template <typename T>
+                inline T equal_impl(const T v0, const T v1, int_type_tag)
+                {
+                    return (v0 == v1) ? 1 : 0;
+                }
+                
+                template <typename T>
+                inline T expm1_impl(const T v, real_type_tag)
+                {
+                    // return std::expm1<T>(v);
+                    if (abs_impl(v,real_type_tag()) < T(0.00001))
+                        return v + (T(0.5) * v * v);
+                    else
+                        return std::exp(v) - T(1);
+                }
+                
+                template <typename T>
+                inline T expm1_impl(const T v, int_type_tag)
+                {
+                    return T(std::exp<double>(v)) - T(1);
+                }
+                
+                template <typename T>
+                inline T nequal_impl(const T v0, const T v1, real_type_tag)
+                {
+                    typedef real_type_tag rtg;
+                    const T epsilon = epsilon_type<T>::value();
+                    return (abs_impl(v0 - v1,rtg()) > (std::max(T(1),std::max(abs_impl(v0,rtg()),abs_impl(v1,rtg()))) * epsilon)) ? T(1) : T(0);
+                }
+                
+                inline float nequal_impl(const float v0, const float v1, real_type_tag)
+                {
+                    typedef real_type_tag rtg;
+                    const float epsilon = epsilon_type<float>::value();
+                    return (abs_impl(v0 - v1,rtg()) > (std::max(1.0f,std::max(abs_impl(v0,rtg()),abs_impl(v1,rtg()))) * epsilon)) ? 1.0f : 0.0f;
+                }
+                
+                template <typename T>
+                inline T nequal_impl(const T v0, const T v1, int_type_tag)
+                {
+                    return (v0 != v1) ? 1 : 0;
+                }
+                
+                template <typename T>
+                inline T modulus_impl(const T v0, const T v1, real_type_tag)
+                {
+                    return std::fmod(v0,v1);
+                }
+                
+                template <typename T>
+                inline T modulus_impl(const T v0, const T v1, int_type_tag)
+                {
+                    return v0 % v1;
+                }
+                
+                template <typename T>
+                inline T pow_impl(const T v0, const T v1, real_type_tag)
+                {
+                    return std::pow(v0,v1);
+                }
+                
+                template <typename T>
+                inline T pow_impl(const T v0, const T v1, int_type_tag)
+                {
+                    return std::pow(static_cast<double>(v0),static_cast<double>(v1));
+                }
+                
+                template <typename T>
+                inline T logn_impl(const T v0, const T v1, real_type_tag)
+                {
+                    return std::log(v0) / std::log(v1);
+                }
+                
+                template <typename T>
+                inline T logn_impl(const T v0, const T v1, int_type_tag)
+                {
+                    return static_cast<T>(logn_impl<double>(static_cast<double>(v0),static_cast<double>(v1),real_type_tag()));
+                }
+                
+                template <typename T>
+                inline T log1p_impl(const T v, real_type_tag)
+                {
+                    if (v > T(-1))
+                    {
+                        if (abs_impl(v,real_type_tag()) > T(0.0001))
+                        {
+                            return std::log(T(1) + v);
+                        }
+                        else
+                            return (T(-0.5) * v + T(1)) * v;
+                    }
+                    else
+                        return std::numeric_limits<T>::quiet_NaN();
+                }
+                
+                template <typename T>
+                inline T log1p_impl(const T v, int_type_tag)
+                {
+                    if (v > T(-1))
+                    {
+                        return std::log(T(1) + v);
+                    }
+                    else
+                        return std::numeric_limits<T>::quiet_NaN();
+                }
+                
+                template <typename T>
+                inline T root_impl(const T v0, const T v1, real_type_tag)
+                {
+                    return std::pow(v0,T(1) / v1);
+                }
+                
+                template <typename T>
+                inline T root_impl(const T v0, const T v1, int_type_tag)
+                {
+                    return root_impl<double>(static_cast<double>(v0),static_cast<double>(v1),real_type_tag());
+                }
+                
+                template <typename T>
+                inline T round_impl(const T v, real_type_tag)
+                {
+                    return ((v < T(0)) ? std::ceil(v - T(0.5)) : std::floor(v + T(0.5)));
+                }
+                
+                template <typename T>
+                inline T roundn_impl(const T v0, const T v1, real_type_tag)
+                {
+                    const int index = std::max<int>(0, std::min<int>(pow10_size - 1, (int)std::floor(v1)));
+                    const T p10 = T(pow10[index]);
+                    
+                    if (v0 < T(0))
+                        return T(std::ceil ((v0 * p10) - T(0.5)) / p10);
+                    else
+                        return T(std::floor((v0 * p10) + T(0.5)) / p10);
+                }
+                
+                template <typename T>
+                inline T roundn_impl(const T v0, const T, int_type_tag)
+                {
+                    return v0;
+                }
+                
+                template <typename T>
+                inline T hypot_impl(const T v0, const T v1, real_type_tag)
+                {
+                    return std::sqrt((v0 * v0) + (v1 * v1));
+                }
+                
+                template <typename T>
+                inline T hypot_impl(const T v0, const T v1, int_type_tag)
+                {
+                    return static_cast<T>(std::sqrt(static_cast<double>((v0 * v0) + (v1 * v1))));
+                }
+                
+                template <typename T>
+                inline T atan2_impl(const T v0, const T v1, real_type_tag)
+                {
+                    return std::atan2(v0,v1);
+                }
+                
+                template <typename T>
+                inline T atan2_impl(const T, const T, int_type_tag)
+                {
+                    return 0;
+                }
+                
+                template <typename T>
+                inline T shr_impl(const T v0, const T v1, real_type_tag)
+                {
+                    return v0 * (T(1) / std::pow(T(2),static_cast<T>(static_cast<int>(v1))));
+                }
+                
+                template <typename T>
+                inline T shr_impl(const T v0, const T v1, int_type_tag)
+                {
+                    return v0 >> v1;
+                }
+                
+                template <typename T>
+                inline T shl_impl(const T v0, const T v1, real_type_tag)
+                {
+                    return v0 * std::pow(T(2),static_cast<T>(static_cast<int>(v1)));
+                }
+                
+                template <typename T>
+                inline T shl_impl(const T v0, const T v1, int_type_tag)
+                {
+                    return v0 << v1;
+                }
+                
+                template <typename T>
+                inline T sgn_impl(const T v, real_type_tag)
+                {
+                    if (v > T(0)) return T(+1);
+                    else if (v < T(0)) return T(-1);
+                    else               return T( 0);
+                }
+                
+                template <typename T>
+                inline T sgn_impl(const T v, int_type_tag)
+                {
+                    if (v > T(0)) return T(+1);
+                    else if (v < T(0)) return T(-1);
+                    else               return T( 0);
+                }
+                
+                template <typename T>
+                inline T and_impl(const T v0, const T v1, real_type_tag)
+                {
+                    return (is_true_impl(v0) && is_true_impl(v1)) ? T(1) : T(0);
+                }
+                
+                template <typename T>
+                inline T and_impl(const T v0, const T v1, int_type_tag)
+                {
+                    return v0 && v1;
+                }
+                
+                template <typename T>
+                inline T nand_impl(const T v0, const T v1, real_type_tag)
+                {
+                    return (is_false_impl(v0) || is_false_impl(v1)) ? T(1) : T(0);
+                }
+                
+                template <typename T>
+                inline T nand_impl(const T v0, const T v1, int_type_tag)
+                {
+                    return !(v0 && v1);
+                }
+                
+                template <typename T>
+                inline T or_impl(const T v0, const T v1, real_type_tag)
+                {
+                    return (is_true_impl(v0) || is_true_impl(v1)) ? T(1) : T(0);
+                }
+                
+                template <typename T>
+                inline T or_impl(const T v0, const T v1, int_type_tag)
+                {
+                    return (v0 || v1);
+                }
+                
+                template <typename T>
+                inline T nor_impl(const T v0, const T v1, real_type_tag)
+                {
+                    return (is_false_impl(v0) && is_false_impl(v1)) ? T(1) : T(0);
+                }
+                
+                template <typename T>
+                inline T nor_impl(const T v0, const T v1, int_type_tag)
+                {
+                    return !(v0 || v1);
+                }
+                
+                template <typename T>
+                inline T xor_impl(const T v0, const T v1, real_type_tag)
+                {
+                    return (is_false_impl(v0) != is_false_impl(v1)) ? T(1) : T(0);
+                }
+                
+                template <typename T>
+                inline T xor_impl(const T v0, const T v1, int_type_tag)
+                {
+                    return v0 ^ v1;
+                }
+                
+                template <typename T>
+                inline T xnor_impl(const T v0, const T v1, real_type_tag)
+                {
+                    const bool v0_true = is_true_impl(v0);
+                    const bool v1_true = is_true_impl(v1);
+                    
+                    if ((v0_true &&  v1_true) || (!v0_true && !v1_true))
+                        return T(1);
+                    else
+                        return T(0);
+                }
+                
+                template <typename T>
+                inline T xnor_impl(const T v0, const T v1, int_type_tag)
+                {
+                    const bool v0_true = is_true_impl(v0);
+                    const bool v1_true = is_true_impl(v1);
+                    
+                    if ((v0_true &&  v1_true) || (!v0_true && !v1_true))
+                        return T(1);
+                    else
+                        return T(0);
+                }
+                
+#if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || !defined(_MSC_VER)
+#define exprtk_define_erf(TT,impl)           \
+inline TT erf_impl(TT v) { return impl(v); } \
+
+                exprtk_define_erf(      float,::erff)
+                exprtk_define_erf(     double,::erf )
+                exprtk_define_erf(long double,::erfl)
+#undef exprtk_define_erf
+#endif
+                
+                template <typename T>
+                inline T erf_impl(T v, real_type_tag)
+                {
+#if defined(_MSC_VER) && (_MSC_VER < 1900)
+                    // Credits: Abramowitz & Stegun Equations 7.1.25-28
+                    static const T c[] = {
+                        T( 1.26551223), T(1.00002368),
+                        T( 0.37409196), T(0.09678418),
+                        T(-0.18628806), T(0.27886807),
+                        T(-1.13520398), T(1.48851587),
+                        T(-0.82215223), T(0.17087277)
+                    };
+                    
+                    const T t = T(1) / (T(1) + T(0.5) * abs_impl(v,real_type_tag()));
+                    
+                    T result = T(1) - t * std::exp((-v * v) -
+                                                   c[0] + t * (c[1] + t *
+                                                               (c[2] + t * (c[3] + t *
+                                                                            (c[4] + t * (c[5] + t *
+                                                                                         (c[6] + t * (c[7] + t *
+                                                                                                      (c[8] + t * (c[9]))))))))));
+                    
+                    return (v >= T(0)) ? result : -result;
+#else
+                    return erf_impl(v);
+#endif
+                }
+                
+                template <typename T>
+                inline T erf_impl(T v, int_type_tag)
+                {
+                    return erf_impl(static_cast<double>(v),real_type_tag());
+                }
+                
+#if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || !defined(_MSC_VER)
+#define exprtk_define_erfc(TT,impl)           \
+inline TT erfc_impl(TT v) { return impl(v); } \
+
+                exprtk_define_erfc(      float,::erfcf)
+                exprtk_define_erfc(     double,::erfc )
+                exprtk_define_erfc(long double,::erfcl)
+#undef exprtk_define_erfc
+#endif
+                
+                template <typename T>
+                inline T erfc_impl(T v, real_type_tag)
+                {
+#if defined(_MSC_VER) && (_MSC_VER < 1900)
+                    return T(1) - erf_impl(v,real_type_tag());
+#else
+                    return erfc_impl(v);
+#endif
+                }
+                
+                template <typename T>
+                inline T erfc_impl(T v, int_type_tag)
+                {
+                    return erfc_impl(static_cast<double>(v),real_type_tag());
+                }
+                
+                template <typename T>
+                inline T ncdf_impl(T v, real_type_tag)
+                {
+                    T cnd = T(0.5) * (T(1) + erf_impl(
+                                                      abs_impl(v,real_type_tag()) /
+                                                      T(numeric::constant::sqrt2),real_type_tag()));
+                    return  (v < T(0)) ? (T(1) - cnd) : cnd;
+                }
+                
+                template <typename T>
+                inline T ncdf_impl(T v, int_type_tag)
+                {
+                    return ncdf_impl(static_cast<double>(v),real_type_tag());
+                }
+                
+                template <typename T>
+                inline T sinc_impl(T v, real_type_tag)
+                {
+                    if (std::abs(v) >= std::numeric_limits<T>::epsilon())
+                        return(std::sin(v) / v);
+                    else
+                        return T(1);
+                }
+                
+                template <typename T>
+                inline T sinc_impl(T v, int_type_tag)
+                {
+                    return sinc_impl(static_cast<double>(v),real_type_tag());
+                }
+                
+                template <typename T> inline T  acos_impl(const T v, real_type_tag) { return std::acos (v); }
+                template <typename T> inline T acosh_impl(const T v, real_type_tag) { return std::log(v + std::sqrt((v * v) - T(1))); }
+                template <typename T> inline T  asin_impl(const T v, real_type_tag) { return std::asin (v); }
+                template <typename T> inline T asinh_impl(const T v, real_type_tag) { return std::log(v + std::sqrt((v * v) + T(1))); }
+                template <typename T> inline T  atan_impl(const T v, real_type_tag) { return std::atan (v); }
+                template <typename T> inline T atanh_impl(const T v, real_type_tag) { return (std::log(T(1) + v) - std::log(T(1) - v)) / T(2); }
+                template <typename T> inline T  ceil_impl(const T v, real_type_tag) { return std::ceil (v); }
+                template <typename T> inline T   cos_impl(const T v, real_type_tag) { return std::cos  (v); }
+                template <typename T> inline T  cosh_impl(const T v, real_type_tag) { return std::cosh (v); }
+                template <typename T> inline T   exp_impl(const T v, real_type_tag) { return std::exp  (v); }
+                template <typename T> inline T floor_impl(const T v, real_type_tag) { return std::floor(v); }
+                template <typename T> inline T   log_impl(const T v, real_type_tag) { return std::log  (v); }
+                template <typename T> inline T log10_impl(const T v, real_type_tag) { return std::log10(v); }
+                template <typename T> inline T  log2_impl(const T v, real_type_tag) { return std::log(v)/T(numeric::constant::log2); }
+                template <typename T> inline T   neg_impl(const T v, real_type_tag) { return -v;            }
+                template <typename T> inline T   pos_impl(const T v, real_type_tag) { return +v;            }
+                template <typename T> inline T   sin_impl(const T v, real_type_tag) { return std::sin  (v); }
+                template <typename T> inline T  sinh_impl(const T v, real_type_tag) { return std::sinh (v); }
+                template <typename T> inline T  sqrt_impl(const T v, real_type_tag) { return std::sqrt (v); }
+                template <typename T> inline T   tan_impl(const T v, real_type_tag) { return std::tan  (v); }
+                template <typename T> inline T  tanh_impl(const T v, real_type_tag) { return std::tanh (v); }
+                template <typename T> inline T   cot_impl(const T v, real_type_tag) { return T(1) / std::tan(v); }
+                template <typename T> inline T   sec_impl(const T v, real_type_tag) { return T(1) / std::cos(v); }
+                template <typename T> inline T   csc_impl(const T v, real_type_tag) { return T(1) / std::sin(v); }
+                template <typename T> inline T   r2d_impl(const T v, real_type_tag) { return (v * T(numeric::constant::_180_pi)); }
+                template <typename T> inline T   d2r_impl(const T v, real_type_tag) { return (v * T(numeric::constant::pi_180));  }
+                template <typename T> inline T   d2g_impl(const T v, real_type_tag) { return (v * T(20.0/9.0)); }
+                template <typename T> inline T   g2d_impl(const T v, real_type_tag) { return (v * T(9.0/20.0)); }
+                template <typename T> inline T  notl_impl(const T v, real_type_tag) { return (std::not_equal_to<T>()(T(0),v) ? T(0) : T(1)); }
+                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   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); }
+                template <typename T> inline T   log_impl(const T v, int_type_tag) { return std::log  (v); }
+                template <typename T> inline T log10_impl(const T v, int_type_tag) { return std::log10(v); }
+                template <typename T> inline T  log2_impl(const T v, int_type_tag) { return std::log(v)/T(numeric::constant::log2); }
+                template <typename T> inline T   neg_impl(const T v, int_type_tag) { return -v;            }
+                template <typename T> inline T   pos_impl(const T v, int_type_tag) { return +v;            }
+                template <typename T> inline T  ceil_impl(const T v, int_type_tag) { return v;             }
+                template <typename T> inline T floor_impl(const T v, int_type_tag) { return v;             }
+                template <typename T> inline T round_impl(const T v, int_type_tag) { return v;             }
+                template <typename T> inline T  notl_impl(const T v, int_type_tag) { return !v;            }
+                template <typename T> inline T  sqrt_impl(const T v, int_type_tag) { return std::sqrt (v); }
+                template <typename T> inline T  frac_impl(const T  , int_type_tag) { return T(0);          }
+                template <typename T> inline T trunc_impl(const T v, int_type_tag) { return v;             }
+                template <typename T> inline T  acos_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
+                template <typename T> inline T acosh_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
+                template <typename T> inline T  asin_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
+                template <typename T> inline T asinh_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
+                template <typename T> inline T  atan_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
+                template <typename T> inline T atanh_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
+                template <typename T> inline T   cos_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
+                template <typename T> inline T  cosh_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
+                template <typename T> inline T   sin_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
+                template <typename T> inline T  sinh_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
+                template <typename T> inline T   tan_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
+                template <typename T> inline T  tanh_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
+                template <typename T> inline T   cot_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
+                template <typename T> inline T   sec_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
+                template <typename T> inline T   csc_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
+                
+                template <typename T>
+                inline bool is_integer_impl(const T& v, real_type_tag)
+                {
+                    return std::equal_to<T>()(T(0),std::fmod(v,T(1)));
+                }
+                
+                template <typename T>
+                inline bool is_integer_impl(const T&, int_type_tag)
+                {
+                    return true;
+                }
+            }
+            
+            template <typename Type>
+            struct numeric_info { enum { length = 0, size = 32, bound_length = 0, min_exp = 0, max_exp = 0 }; };
+            
+            template<> struct numeric_info<int>         { enum { length = 10, size = 16, bound_length = 9}; };
+            template<> struct numeric_info<float>       { enum { min_exp =  -38, max_exp =  +38}; };
+            template<> struct numeric_info<double>      { enum { min_exp = -308, max_exp = +308}; };
+            template<> struct numeric_info<long double> { enum { min_exp = -308, max_exp = +308}; };
+            
             template <typename T>
-            struct epsilon_type
+            inline int to_int32(const T v)
             {
-               static inline T value()
-               {
-                  const T epsilon = T(0.0000000001);
-                  return epsilon;
-               }
-            };
-
-            template <>
-            struct epsilon_type <float>
-            {
-               static inline float value()
-               {
-                  const float epsilon = float(0.000001f);
-                  return epsilon;
-               }
-            };
-
-            template <>
-            struct epsilon_type <long double>
-            {
-               static inline long double value()
-               {
-                  const long double epsilon = (long double)(0.000000000001);
-                  return epsilon;
-               }
-            };
-
+                typename details::number_type<T>::type num_type;
+                return to_int32_impl(v,num_type);
+            }
+            
             template <typename T>
-            inline bool is_nan_impl(const T v, real_type_tag)
+            inline long long int to_int64(const T v)
             {
-               return std::not_equal_to<T>()(v,v);
+                typename details::number_type<T>::type num_type;
+                return to_int64_impl(v,num_type);
             }
-
+            
             template <typename T>
-            inline int to_int32_impl(const T v, real_type_tag)
+            inline bool is_nan(const T v)
             {
-               return static_cast<int>(v);
+                typename details::number_type<T>::type num_type;
+                return is_nan_impl(v,num_type);
             }
-
+            
             template <typename T>
-            inline long long int to_int64_impl(const T v, real_type_tag)
+            inline T min(const T v0, const T v1)
             {
-               return static_cast<long long int>(v);
+                typename details::number_type<T>::type num_type;
+                return min_impl(v0,v1,num_type);
             }
-
+            
             template <typename T>
-            inline bool is_true_impl(const T v)
+            inline T max(const T v0, const T v1)
             {
-               return std::not_equal_to<T>()(T(0),v);
+                typename details::number_type<T>::type num_type;
+                return max_impl(v0,v1,num_type);
             }
-
+            
             template <typename T>
-            inline bool is_false_impl(const T v)
+            inline T equal(const T v0, const T v1)
             {
-               return std::equal_to<T>()(T(0),v);
+                typename details::number_type<T>::type num_type;
+                return equal_impl(v0,v1,num_type);
             }
-
+            
             template <typename T>
-            inline T abs_impl(const T v, real_type_tag)
+            inline T nequal(const T v0, const T v1)
             {
-               return ((v >= T(0)) ? v : -v);
+                typename details::number_type<T>::type num_type;
+                return nequal_impl(v0,v1,num_type);
             }
-
+            
             template <typename T>
-            inline T min_impl(const T v0, const T v1, real_type_tag)
+            inline T modulus(const T v0, const T v1)
             {
-               return std::min<T>(v0,v1);
+                typename details::number_type<T>::type num_type;
+                return modulus_impl(v0,v1,num_type);
             }
-
+            
             template <typename T>
-            inline T max_impl(const T v0, const T v1, real_type_tag)
+            inline T pow(const T v0, const T v1)
             {
-               return std::max<T>(v0,v1);
+                typename details::number_type<T>::type num_type;
+                return pow_impl(v0,v1,num_type);
             }
-
+            
             template <typename T>
-            inline T equal_impl(const T v0, const T v1, real_type_tag)
+            inline T logn(const T v0, const T v1)
             {
-               const T epsilon = epsilon_type<T>::value();
-               return (abs_impl(v0 - v1,real_type_tag()) <= (std::max(T(1),std::max(abs_impl(v0,real_type_tag()),abs_impl(v1,real_type_tag()))) * epsilon)) ? T(1) : T(0);
+                typename details::number_type<T>::type num_type;
+                return logn_impl(v0,v1,num_type);
             }
-
-            inline float equal_impl(const float v0, const float v1, real_type_tag)
+            
+            template <typename T>
+            inline T root(const T v0, const T v1)
             {
-               const float epsilon = epsilon_type<float>::value();
-               return (abs_impl(v0 - v1,real_type_tag()) <= (std::max(1.0f,std::max(abs_impl(v0,real_type_tag()),abs_impl(v1,real_type_tag()))) * epsilon)) ? 1.0f : 0.0f;
+                typename details::number_type<T>::type num_type;
+                return root_impl(v0,v1,num_type);
             }
-
+            
             template <typename T>
-            inline T equal_impl(const T v0, const T v1, int_type_tag)
+            inline T roundn(const T v0, const T v1)
             {
-               return (v0 == v1) ? 1 : 0;
+                typename details::number_type<T>::type num_type;
+                return roundn_impl(v0,v1,num_type);
             }
-
+            
             template <typename T>
-            inline T expm1_impl(const T v, real_type_tag)
+            inline T hypot(const T v0, const T v1)
             {
-               // return std::expm1<T>(v);
-               if (abs_impl(v,real_type_tag()) < T(0.00001))
-                  return v + (T(0.5) * v * v);
-               else
-                  return std::exp(v) - T(1);
+                typename details::number_type<T>::type num_type;
+                return hypot_impl(v0,v1,num_type);
             }
-
+            
             template <typename T>
-            inline T expm1_impl(const T v, int_type_tag)
+            inline T atan2(const T v0, const T v1)
             {
-               return T(std::exp<double>(v)) - T(1);
+                typename details::number_type<T>::type num_type;
+                return atan2_impl(v0,v1,num_type);
             }
-
+            
             template <typename T>
-            inline T nequal_impl(const T v0, const T v1, real_type_tag)
+            inline T shr(const T v0, const T v1)
             {
-               const T epsilon = epsilon_type<T>::value();
-               return (abs_impl(v0 - v1,real_type_tag()) > (std::max(T(1),std::max(abs_impl(v0,real_type_tag()),abs_impl(v1,real_type_tag()))) * epsilon)) ? T(1) : T(0);
+                typename details::number_type<T>::type num_type;
+                return shr_impl(v0,v1,num_type);
             }
-
-            inline float nequal_impl(const float v0, const float v1, real_type_tag)
+            
+            template <typename T>
+            inline T shl(const T v0, const T v1)
             {
-               const float epsilon = epsilon_type<float>::value();
-               return (abs_impl(v0 - v1,real_type_tag()) > (std::max(1.0f,std::max(abs_impl(v0,real_type_tag()),abs_impl(v1,real_type_tag()))) * epsilon)) ? 1.0f : 0.0f;
+                typename details::number_type<T>::type num_type;
+                return shl_impl(v0,v1,num_type);
             }
-
+            
             template <typename T>
-            inline T nequal_impl(const T v0, const T v1, int_type_tag)
+            inline T and_opr(const T v0, const T v1)
             {
-               return (v0 != v1) ? 1 : 0;
+                typename details::number_type<T>::type num_type;
+                return and_impl(v0,v1,num_type);
             }
-
+            
             template <typename T>
-            inline T modulus_impl(const T v0, const T v1, real_type_tag)
+            inline T nand_opr(const T v0, const T v1)
             {
-               return std::fmod(v0,v1);
+                typename details::number_type<T>::type num_type;
+                return nand_impl(v0,v1,num_type);
             }
-
+            
             template <typename T>
-            inline T modulus_impl(const T v0, const T v1, int_type_tag)
+            inline T or_opr(const T v0, const T v1)
             {
-               return v0 % v1;
+                typename details::number_type<T>::type num_type;
+                return or_impl(v0,v1,num_type);
             }
-
+            
             template <typename T>
-            inline T pow_impl(const T v0, const T v1, real_type_tag)
+            inline T nor_opr(const T v0, const T v1)
             {
-               return std::pow(v0,v1);
+                typename details::number_type<T>::type num_type;
+                return nor_impl(v0,v1,num_type);
             }
-
+            
             template <typename T>
-            inline T pow_impl(const T v0, const T v1, int_type_tag)
+            inline T xor_opr(const T v0, const T v1)
             {
-               return std::pow(static_cast<double>(v0),static_cast<double>(v1));
+                typename details::number_type<T>::type num_type;
+                return xor_impl(v0,v1,num_type);
             }
-
+            
             template <typename T>
-            inline T logn_impl(const T v0, const T v1, real_type_tag)
+            inline T xnor_opr(const T v0, const T v1)
             {
-               return std::log(v0) / std::log(v1);
+                typename details::number_type<T>::type num_type;
+                return xnor_impl(v0,v1,num_type);
             }
-
+            
             template <typename T>
-            inline T logn_impl(const T v0, const T v1, int_type_tag)
+            inline bool is_integer(const T v)
+            {
+                typename details::number_type<T>::type num_type;
+                return is_integer_impl(v,num_type);
+            }
+            
+            template <typename T, unsigned int N>
+            struct fast_exp
+            {
+                static inline T result(T v)
+                {
+                    unsigned int k = N;
+                    T l = T(1);
+                    
+                    while (k)
+                    {
+                        if (k & 1)
+                        {
+                            l *= v;
+                            --k;
+                        }
+                        
+                        v *= v;
+                        k >>= 1;
+                    }
+                    
+                    return l;
+                }
+            };
+            
+            template <typename T> struct fast_exp<T,10> { static inline T result(T v) { T v_5 = fast_exp<T,5>::result(v); return v_5 * v_5; } };
+            template <typename T> struct fast_exp<T, 9> { static inline T result(T v) { return fast_exp<T,8>::result(v) * v; } };
+            template <typename T> struct fast_exp<T, 8> { static inline T result(T v) { T v_4 = fast_exp<T,4>::result(v); return v_4 * v_4; } };
+            template <typename T> struct fast_exp<T, 7> { static inline T result(T v) { return fast_exp<T,6>::result(v) * v; } };
+            template <typename T> struct fast_exp<T, 6> { static inline T result(T v) { T v_3 = fast_exp<T,3>::result(v); return v_3 * v_3; } };
+            template <typename T> struct fast_exp<T, 5> { static inline T result(T v) { return fast_exp<T,4>::result(v) * v; } };
+            template <typename T> struct fast_exp<T, 4> { static inline T result(T v) { T v_2 = v * v; return v_2 * v_2; } };
+            template <typename T> struct fast_exp<T, 3> { static inline T result(T v) { return v * v * v; } };
+            template <typename T> struct fast_exp<T, 2> { static inline T result(T v) { return v * v;     } };
+            template <typename T> struct fast_exp<T, 1> { static inline T result(T v) { return v;         } };
+            template <typename T> struct fast_exp<T, 0> { static inline T result(T  ) { return T(1);      } };
+            
+#define exprtk_define_unary_function(FunctionName)   \
+template <typename T>                                \
+inline T FunctionName (const T v)                    \
+{                                                    \
+typename details::number_type<T>::type num_type;  \
+return  FunctionName##_impl(v,num_type);          \
+}                                                    \
+
+            exprtk_define_unary_function(abs  )
+            exprtk_define_unary_function(acos )
+            exprtk_define_unary_function(acosh)
+            exprtk_define_unary_function(asin )
+            exprtk_define_unary_function(asinh)
+            exprtk_define_unary_function(atan )
+            exprtk_define_unary_function(atanh)
+            exprtk_define_unary_function(ceil )
+            exprtk_define_unary_function(cos  )
+            exprtk_define_unary_function(cosh )
+            exprtk_define_unary_function(exp  )
+            exprtk_define_unary_function(expm1)
+            exprtk_define_unary_function(floor)
+            exprtk_define_unary_function(log  )
+            exprtk_define_unary_function(log10)
+            exprtk_define_unary_function(log2 )
+            exprtk_define_unary_function(log1p)
+            exprtk_define_unary_function(neg  )
+            exprtk_define_unary_function(pos  )
+            exprtk_define_unary_function(round)
+            exprtk_define_unary_function(sin  )
+            exprtk_define_unary_function(sinc )
+            exprtk_define_unary_function(sinh )
+            exprtk_define_unary_function(sqrt )
+            exprtk_define_unary_function(tan  )
+            exprtk_define_unary_function(tanh )
+            exprtk_define_unary_function(cot  )
+            exprtk_define_unary_function(sec  )
+            exprtk_define_unary_function(csc  )
+            exprtk_define_unary_function(r2d  )
+            exprtk_define_unary_function(d2r  )
+            exprtk_define_unary_function(d2g  )
+            exprtk_define_unary_function(g2d  )
+            exprtk_define_unary_function(notl )
+            exprtk_define_unary_function(sgn  )
+            exprtk_define_unary_function(erf  )
+            exprtk_define_unary_function(erfc )
+            exprtk_define_unary_function(ncdf )
+            exprtk_define_unary_function(frac )
+            exprtk_define_unary_function(trunc)
+#undef exprtk_define_unary_function
+        }
+        
+        template <typename T>
+        inline T compute_pow10(T d, const int exponent)
+        {
+            static const double fract10[] =
+            {
+                0.0,
+                1.0E+001, 1.0E+002, 1.0E+003, 1.0E+004, 1.0E+005, 1.0E+006, 1.0E+007, 1.0E+008, 1.0E+009, 1.0E+010,
+                1.0E+011, 1.0E+012, 1.0E+013, 1.0E+014, 1.0E+015, 1.0E+016, 1.0E+017, 1.0E+018, 1.0E+019, 1.0E+020,
+                1.0E+021, 1.0E+022, 1.0E+023, 1.0E+024, 1.0E+025, 1.0E+026, 1.0E+027, 1.0E+028, 1.0E+029, 1.0E+030,
+                1.0E+031, 1.0E+032, 1.0E+033, 1.0E+034, 1.0E+035, 1.0E+036, 1.0E+037, 1.0E+038, 1.0E+039, 1.0E+040,
+                1.0E+041, 1.0E+042, 1.0E+043, 1.0E+044, 1.0E+045, 1.0E+046, 1.0E+047, 1.0E+048, 1.0E+049, 1.0E+050,
+                1.0E+051, 1.0E+052, 1.0E+053, 1.0E+054, 1.0E+055, 1.0E+056, 1.0E+057, 1.0E+058, 1.0E+059, 1.0E+060,
+                1.0E+061, 1.0E+062, 1.0E+063, 1.0E+064, 1.0E+065, 1.0E+066, 1.0E+067, 1.0E+068, 1.0E+069, 1.0E+070,
+                1.0E+071, 1.0E+072, 1.0E+073, 1.0E+074, 1.0E+075, 1.0E+076, 1.0E+077, 1.0E+078, 1.0E+079, 1.0E+080,
+                1.0E+081, 1.0E+082, 1.0E+083, 1.0E+084, 1.0E+085, 1.0E+086, 1.0E+087, 1.0E+088, 1.0E+089, 1.0E+090,
+                1.0E+091, 1.0E+092, 1.0E+093, 1.0E+094, 1.0E+095, 1.0E+096, 1.0E+097, 1.0E+098, 1.0E+099, 1.0E+100,
+                1.0E+101, 1.0E+102, 1.0E+103, 1.0E+104, 1.0E+105, 1.0E+106, 1.0E+107, 1.0E+108, 1.0E+109, 1.0E+110,
+                1.0E+111, 1.0E+112, 1.0E+113, 1.0E+114, 1.0E+115, 1.0E+116, 1.0E+117, 1.0E+118, 1.0E+119, 1.0E+120,
+                1.0E+121, 1.0E+122, 1.0E+123, 1.0E+124, 1.0E+125, 1.0E+126, 1.0E+127, 1.0E+128, 1.0E+129, 1.0E+130,
+                1.0E+131, 1.0E+132, 1.0E+133, 1.0E+134, 1.0E+135, 1.0E+136, 1.0E+137, 1.0E+138, 1.0E+139, 1.0E+140,
+                1.0E+141, 1.0E+142, 1.0E+143, 1.0E+144, 1.0E+145, 1.0E+146, 1.0E+147, 1.0E+148, 1.0E+149, 1.0E+150,
+                1.0E+151, 1.0E+152, 1.0E+153, 1.0E+154, 1.0E+155, 1.0E+156, 1.0E+157, 1.0E+158, 1.0E+159, 1.0E+160,
+                1.0E+161, 1.0E+162, 1.0E+163, 1.0E+164, 1.0E+165, 1.0E+166, 1.0E+167, 1.0E+168, 1.0E+169, 1.0E+170,
+                1.0E+171, 1.0E+172, 1.0E+173, 1.0E+174, 1.0E+175, 1.0E+176, 1.0E+177, 1.0E+178, 1.0E+179, 1.0E+180,
+                1.0E+181, 1.0E+182, 1.0E+183, 1.0E+184, 1.0E+185, 1.0E+186, 1.0E+187, 1.0E+188, 1.0E+189, 1.0E+190,
+                1.0E+191, 1.0E+192, 1.0E+193, 1.0E+194, 1.0E+195, 1.0E+196, 1.0E+197, 1.0E+198, 1.0E+199, 1.0E+200,
+                1.0E+201, 1.0E+202, 1.0E+203, 1.0E+204, 1.0E+205, 1.0E+206, 1.0E+207, 1.0E+208, 1.0E+209, 1.0E+210,
+                1.0E+211, 1.0E+212, 1.0E+213, 1.0E+214, 1.0E+215, 1.0E+216, 1.0E+217, 1.0E+218, 1.0E+219, 1.0E+220,
+                1.0E+221, 1.0E+222, 1.0E+223, 1.0E+224, 1.0E+225, 1.0E+226, 1.0E+227, 1.0E+228, 1.0E+229, 1.0E+230,
+                1.0E+231, 1.0E+232, 1.0E+233, 1.0E+234, 1.0E+235, 1.0E+236, 1.0E+237, 1.0E+238, 1.0E+239, 1.0E+240,
+                1.0E+241, 1.0E+242, 1.0E+243, 1.0E+244, 1.0E+245, 1.0E+246, 1.0E+247, 1.0E+248, 1.0E+249, 1.0E+250,
+                1.0E+251, 1.0E+252, 1.0E+253, 1.0E+254, 1.0E+255, 1.0E+256, 1.0E+257, 1.0E+258, 1.0E+259, 1.0E+260,
+                1.0E+261, 1.0E+262, 1.0E+263, 1.0E+264, 1.0E+265, 1.0E+266, 1.0E+267, 1.0E+268, 1.0E+269, 1.0E+270,
+                1.0E+271, 1.0E+272, 1.0E+273, 1.0E+274, 1.0E+275, 1.0E+276, 1.0E+277, 1.0E+278, 1.0E+279, 1.0E+280,
+                1.0E+281, 1.0E+282, 1.0E+283, 1.0E+284, 1.0E+285, 1.0E+286, 1.0E+287, 1.0E+288, 1.0E+289, 1.0E+290,
+                1.0E+291, 1.0E+292, 1.0E+293, 1.0E+294, 1.0E+295, 1.0E+296, 1.0E+297, 1.0E+298, 1.0E+299, 1.0E+300,
+                1.0E+301, 1.0E+302, 1.0E+303, 1.0E+304, 1.0E+305, 1.0E+306, 1.0E+307, 1.0E+308
+            };
+            
+            static const int fract10_size = static_cast<int>(sizeof(fract10) / sizeof(double));
+            
+            const int e = std::abs(exponent);
+            
+            if (exponent >= std::numeric_limits<T>::min_exponent10)
+            {
+                if (e < fract10_size)
+                {
+                    if (exponent > 0)
+                        return T(d * fract10[e]);
+                    else
+                        return T(d / fract10[e]);
+                }
+                else
+                    return T(d * std::pow(10.0, 10.0 * exponent));
+            }
+            else
             {
-               return static_cast<T>(logn_impl<double>(static_cast<double>(v0),static_cast<double>(v1),real_type_tag()));
+                d /= T(fract10[           -std::numeric_limits<T>::min_exponent10]);
+                return T(d /    fract10[-exponent + std::numeric_limits<T>::min_exponent10]);
+            }
+        }
+        
+        template <typename Iterator, typename T>
+        inline bool string_to_type_converter_impl_ref(Iterator& itr, const Iterator end, T& result)
+        {
+            if (itr == end)
+                return false;
+            
+            bool negative = ('-' == (*itr));
+            
+            if (negative || ('+' == (*itr)))
+            {
+                if (end == ++itr)
+                    return false;
+            }
+            
+            while ((end != itr) && ('0' == (*itr))) ++itr;
+            
+            bool return_result = true;
+            unsigned int digit = 0;
+            const std::size_t length = std::distance(itr,end);
+            
+            if (length <= 4)
+            {
+                switch (length)
+                {
+#ifdef exprtk_use_lut
+                        
+#define exprtk_process_digit \
+if ((digit = details::digit_table[(int)*itr++]) < 10) result = result * 10 + (digit); else { return_result = false; break; }
+                        
+#else
+#define exprtk_process_digit \
+if ((digit = (*itr++ - '0')) < 10) result = result * 10 + (digit); else { return_result = false; break; }
+                        
+#endif
+                        
+                    case  4 : exprtk_process_digit
+                    case  3 : exprtk_process_digit
+                    case  2 : exprtk_process_digit
+                    case  1 : if ((digit = (*itr - '0'))>= 10) { digit = 0; return_result = false; }
+                        
+#undef exprtk_process_digit
+                }
             }
-
-            template <typename T>
-            inline T log1p_impl(const T v, real_type_tag)
-            {
-               if (v > T(-1))
-               {
-                  if (abs_impl(v,real_type_tag()) > T(0.0001))
-                  {
-                     return std::log(T(1) + v);
-                  }
-                  else
-                     return (T(-0.5) * v + T(1)) * v;
-               }
-               else
-                  return std::numeric_limits<T>::quiet_NaN();
+            else
+                return_result = false;
+            
+            if (length && return_result)
+            {
+                result = result * 10 + static_cast<T>(digit);
+                ++itr;
+            }
+            
+            result = negative ? -result : result;
+            return return_result;
+        }
+        
+        template <typename Iterator, typename T>
+        static inline bool parse_nan(Iterator& itr, const Iterator end, T& t)
+        {
+            typedef typename std::iterator_traits<Iterator>::value_type type;
+            
+            static const std::size_t nan_length = 3;
+            
+            if (std::distance(itr,end) != static_cast<int>(nan_length))
+                return false;
+            
+            if (static_cast<type>('n') == (*itr))
+            {
+                if (
+                    (static_cast<type>('a') != *(itr + 1)) ||
+                    (static_cast<type>('n') != *(itr + 2))
+                    )
+                {
+                    return false;
+                }
             }
-
-            template <typename T>
-            inline T log1p_impl(const T v, int_type_tag)
+            else if (
+                     (static_cast<type>('A') != *(itr + 1)) ||
+                     (static_cast<type>('N') != *(itr + 2))
+                     )
             {
-               if (v > T(-1))
-               {
-                  return std::log(T(1) + v);
-               }
-               else
-                  return std::numeric_limits<T>::quiet_NaN();
+                return false;
             }
-
-            template <typename T>
-            inline T root_impl(const T v0, const T v1, real_type_tag)
+            
+            t = std::numeric_limits<T>::quiet_NaN();
+            
+            return true;
+        }
+        
+        template <typename Iterator, typename T>
+        static inline bool parse_inf(Iterator& itr, const Iterator end, T& t, bool negative)
+        {
+            static const char_t inf_uc[] = "INFINITY";
+            static const char_t inf_lc[] = "infinity";
+            static const std::size_t inf_length = 8;
+            
+            const std::size_t length = std::distance(itr,end);
+            
+            if ((3 != length) && (inf_length != length))
+                return false;
+            
+            const char* inf_itr = ('i' == (*itr)) ? inf_lc : inf_uc;
+            
+            while (end != itr)
+            {
+                if (*inf_itr == static_cast<char>(*itr))
+                {
+                    ++itr;
+                    ++inf_itr;
+                    continue;
+                }
+                else
+                    return false;
+            }
+            
+            if (negative)
+                t = -std::numeric_limits<T>::infinity();
+            else
+                t =  std::numeric_limits<T>::infinity();
+            
+            return true;
+        }
+        
+        template <typename Iterator, typename T>
+        inline bool string_to_real(Iterator& itr_external, const Iterator end, T& t, numeric::details::real_type_tag)
+        {
+            if (end == itr_external) return false;
+            
+            Iterator itr = itr_external;
+            
+            T d = T(0);
+            
+            bool negative = ('-' == (*itr));
+            
+            if (negative || '+' == (*itr))
+            {
+                if (end == ++itr)
+                    return false;
+            }
+            
+            bool instate = false;
+            
+#define parse_digit_1(d)         \
+if ((digit = (*itr - '0')) < 10) \
+{ d = d * T(10) + digit; }    \
+else                             \
+{ break; }                    \
+if (end == ++itr) break;         \
+
+#define parse_digit_2(d)         \
+if ((digit = (*itr - '0')) < 10) \
+{ d = d * T(10) + digit; }    \
+else { break; }                  \
+++itr;                        \
+
+            if ('.' != (*itr))
+            {
+                const Iterator curr = itr;
+                while ((end != itr) && ('0' == (*itr))) ++itr;
+                unsigned int digit;
+                
+                while (end != itr)
+                {
+                    // Note: For 'physical' superscalar architectures it
+                    // is advised that the following loop be: 4xPD1 and 1xPD2
+#ifdef exprtk_enable_superscalar
+                    parse_digit_1(d)
+                    parse_digit_1(d)
+#endif
+                    parse_digit_1(d)
+                    parse_digit_1(d)
+                    parse_digit_2(d)
+                }
+                
+                if (curr != itr) instate = true;
+            }
+            
+            int exponent = 0;
+            
+            if (end != itr)
+            {
+                if ('.' == (*itr))
+                {
+                    const Iterator curr = ++itr;
+                    unsigned int digit;
+                    T tmp_d = T(0);
+                    
+                    while (end != itr)
+                    {
+#ifdef exprtk_enable_superscalar
+                        parse_digit_1(tmp_d)
+                        parse_digit_1(tmp_d)
+                        parse_digit_1(tmp_d)
+#endif
+                        parse_digit_1(tmp_d)
+                        parse_digit_1(tmp_d)
+                        parse_digit_2(tmp_d)
+                    }
+                    
+                    if (curr != itr)
+                    {
+                        instate = true;
+                        d += compute_pow10(tmp_d,static_cast<int>(-std::distance(curr,itr)));
+                    }
+                    
+#undef parse_digit_1
+#undef parse_digit_2
+                }
+                
+                if (end != itr)
+                {
+                    typename std::iterator_traits<Iterator>::value_type c = (*itr);
+                    
+                    if (('e' == c) || ('E' == c))
+                    {
+                        int exp = 0;
+                        
+                        if (!details::string_to_type_converter_impl_ref(++itr,end,exp))
+                        {
+                            if (end == itr)
+                                return false;
+                            else
+                                c = (*itr);
+                        }
+                        
+                        exponent += exp;
+                    }
+                    
+                    if (end != itr)
+                    {
+                        if (('f' == c) || ('F' == c) || ('l' == c) || ('L' == c))
+                            ++itr;
+                        else if ('#' == c)
+                        {
+                            if (end == ++itr)
+                                return false;
+                            else if (('I' <= (*itr)) && ((*itr) <= 'n'))
+                            {
+                                if (('i' == (*itr)) || ('I' == (*itr)))
+                                {
+                                    return parse_inf(itr,end,t,negative);
+                                }
+                                else if (('n' == (*itr)) || ('N' == (*itr)))
+                                {
+                                    return parse_nan(itr,end,t);
+                                }
+                                else
+                                    return false;
+                            }
+                            else
+                                return false;
+                        }
+                        else if (('I' <= (*itr)) && ((*itr) <= 'n'))
+                        {
+                            if (('i' == (*itr)) || ('I' == (*itr)))
+                            {
+                                return parse_inf(itr,end,t,negative);
+                            }
+                            else if (('n' == (*itr)) || ('N' == (*itr)))
+                            {
+                                return parse_nan(itr,end,t);
+                            }
+                            else
+                                return false;
+                        }
+                        else
+                            return false;
+                    }
+                }
+            }
+            
+            if ((end != itr) || (!instate))
+                return false;
+            else if (exponent)
+                d = compute_pow10(d,exponent);
+            
+            t = static_cast<T>((negative) ? -d : d);
+            return true;
+        }
+        
+        template <typename T>
+        inline bool string_to_real(const std::string& s, T& t)
+        {
+            const char* begin = s.data();
+            const char* end   = s.data() + s.size();
+            typename numeric::details::number_type<T>::type num_type;
+            return string_to_real(begin,end,t,num_type);
+        }
+        
+        template <typename T>
+        struct functor_t
+        {
+            /*
+             Note: The following definitions for Type, may require tweaking
+             based on the compiler and target architecture. The benchmark
+             should provide enough information to make the right choice.
+             */
+            //typedef T Type;
+            //typedef const T Type;
+            typedef const T& Type;
+            typedef       T& RefType;
+            typedef T (*qfunc_t)(Type t0, Type t1, Type t2, Type t3);
+            typedef T (*tfunc_t)(Type t0, Type t1, Type t2);
+            typedef T (*bfunc_t)(Type t0, Type t1);
+            typedef T (*ufunc_t)(Type t0);
+        };
+        
+    } // namespace details
+    
+    namespace lexer
+    {
+        struct token
+        {
+            enum token_type
+            {
+                e_none        =   0, e_error       =   1, e_err_symbol  =   2,
+                e_err_number  =   3, e_err_string  =   4, e_err_sfunc   =   5,
+                e_eof         =   6, e_number      =   7, e_symbol      =   8,
+                e_string      =   9, e_assign      =  10, e_addass      =  11,
+                e_subass      =  12, e_mulass      =  13, e_divass      =  14,
+                e_modass      =  15, e_shr         =  16, e_shl         =  17,
+                e_lte         =  18, e_ne          =  19, e_gte         =  20,
+                e_swap        =  21, e_lt          = '<', e_gt          = '>',
+                e_eq          = '=', e_rbracket    = ')', e_lbracket    = '(',
+                e_rsqrbracket = ']', e_lsqrbracket = '[', e_rcrlbracket = '}',
+                e_lcrlbracket = '{', e_comma       = ',', e_add         = '+',
+                e_sub         = '-', e_div         = '/', e_mul         = '*',
+                e_mod         = '%', e_pow         = '^', e_colon       = ':',
+                e_ternary     = '?'
+            };
+            
+            token()
+            : type(e_none),
+            value(""),
+            position(std::numeric_limits<std::size_t>::max())
+            {}
+            
+            void clear()
             {
-               return std::pow(v0,T(1) / v1);
+                type     = e_none;
+                value    = "";
+                position = std::numeric_limits<std::size_t>::max();
+            }
+            
+            template <typename Iterator>
+            inline token& set_operator(const token_type tt, const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0))
+            {
+                type = tt;
+                value.assign(begin,end);
+                if (base_begin)
+                    position = std::distance(base_begin,begin);
+                return *this;
+            }
+            
+            template <typename Iterator>
+            inline token& set_symbol(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0))
+            {
+                type = e_symbol;
+                value.assign(begin,end);
+                if (base_begin)
+                    position = std::distance(base_begin,begin);
+                return *this;
+            }
+            
+            template <typename Iterator>
+            inline token& set_numeric(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0))
+            {
+                type = e_number;
+                value.assign(begin,end);
+                if (base_begin)
+                    position = std::distance(base_begin,begin);
+                return *this;
+            }
+            
+            template <typename Iterator>
+            inline token& set_string(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0))
+            {
+                type = e_string;
+                value.assign(begin,end);
+                if (base_begin)
+                    position = std::distance(base_begin,begin);
+                return *this;
+            }
+            
+            inline token& set_string(const std::string& s, const std::size_t p)
+            {
+                type     = e_string;
+                value    = s;
+                position = p;
+                return *this;
+            }
+            
+            template <typename Iterator>
+            inline token& set_error(const token_type et, const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0))
+            {
+                if (
+                    (e_error      == et) ||
+                    (e_err_symbol == et) ||
+                    (e_err_number == et) ||
+                    (e_err_string == et) ||
+                    (e_err_sfunc  == et)
+                    )
+                {
+                    type = et;
+                }
+                else
+                    type = e_error;
+                
+                value.assign(begin,end);
+                
+                if (base_begin)
+                    position = std::distance(base_begin,begin);
+                
+                return *this;
+            }
+            
+            static inline std::string to_str(token_type t)
+            {
+                switch (t)
+                {
+                    case e_none        : return "NONE";
+                    case e_error       : return "ERROR";
+                    case e_err_symbol  : return "ERROR_SYMBOL";
+                    case e_err_number  : return "ERROR_NUMBER";
+                    case e_err_string  : return "ERROR_STRING";
+                    case e_eof         : return "EOF";
+                    case e_number      : return "NUMBER";
+                    case e_symbol      : return "SYMBOL";
+                    case e_string      : return "STRING";
+                    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_shr         : return ">>";
+                    case e_shl         : return "<<";
+                    case e_lte         : return "<=";
+                    case e_ne          : return "!=";
+                    case e_gte         : return ">=";
+                    case e_lt          : return "<";
+                    case e_gt          : return ">";
+                    case e_eq          : return "=";
+                    case e_rbracket    : return ")";
+                    case e_lbracket    : return "(";
+                    case e_rsqrbracket : return "]";
+                    case e_lsqrbracket : return "[";
+                    case e_rcrlbracket : return "}";
+                    case e_lcrlbracket : return "{";
+                    case e_comma       : return ",";
+                    case e_add         : return "+";
+                    case e_sub         : return "-";
+                    case e_div         : return "/";
+                    case e_mul         : return "*";
+                    case e_mod         : return "%";
+                    case e_pow         : return "^";
+                    case e_colon       : return ":";
+                    case e_ternary     : return "?";
+                    case e_swap        : return "<=>";
+                    default            : return "UNKNOWN";
+                }
+            }
+            
+            inline bool is_error() const
+            {
+                return (
+                        (e_error      == type) ||
+                        (e_err_symbol == type) ||
+                        (e_err_number == type) ||
+                        (e_err_string == type) ||
+                        (e_err_sfunc  == type)
+                        );
+            }
+            
+            token_type type;
+            std::string value;
+            std::size_t position;
+        };
+        
+        class generator
+        {
+        public:
+            
+            typedef token token_t;
+            typedef std::vector<token_t> token_list_t;
+            typedef std::vector<token_t>::iterator token_list_itr_t;
+            typedef details::char_t char_t;
+            
+            generator()
+            : base_itr_(0),
+            s_itr_   (0),
+            s_end_   (0)
+            {
+                clear();
+            }
+            
+            inline void clear()
+            {
+                base_itr_ = 0;
+                s_itr_    = 0;
+                s_end_    = 0;
+                token_list_.clear();
+                token_itr_ = token_list_.end();
+                store_token_itr_ = token_list_.end();
+            }
+            
+            inline bool process(const std::string& str)
+            {
+                base_itr_ = str.data();
+                s_itr_    = str.data();
+                s_end_    = str.data() + str.size();
+                
+                eof_token_.set_operator(token_t::e_eof,s_end_,s_end_,base_itr_);
+                token_list_.clear();
+                
+                while (!is_end(s_itr_))
+                {
+                    scan_token();
+                    
+                    if (token_list_.empty())
+                        return true;
+                    else if (token_list_.back().is_error())
+                        return false;
+                }
+                
+                return true;
             }
-
-            template <typename T>
-            inline T root_impl(const T v0, const T v1, int_type_tag)
+            
+            inline bool empty() const
             {
-               return root_impl<double>(static_cast<double>(v0),static_cast<double>(v1),real_type_tag());
+                return token_list_.empty();
             }
-
-            template <typename T>
-            inline T round_impl(const T v, real_type_tag)
+            
+            inline std::size_t size() const
             {
-               return ((v < T(0)) ? std::ceil(v - T(0.5)) : std::floor(v + T(0.5)));
+                return token_list_.size();
             }
-
-            template <typename T>
-            inline T roundn_impl(const T v0, const T v1, real_type_tag)
+            
+            inline void begin()
             {
-               const int index = std::max<int>(0, std::min<int>(pow10_size - 1, (int)std::floor(v1)));
-               const T p10 = T(pow10[index]);
-               if (v0 < T(0))
-                  return T(std::ceil ((v0 * p10) - T(0.5)) / p10);
-               else
-                  return T(std::floor((v0 * p10) + T(0.5)) / p10);
+                token_itr_ = token_list_.begin();
+                store_token_itr_ = token_list_.begin();
             }
-
-            template <typename T>
-            inline T roundn_impl(const T v0, const T, int_type_tag)
+            
+            inline void store()
             {
-               return v0;
+                store_token_itr_ = token_itr_;
             }
-
-            template <typename T>
-            inline T hypot_impl(const T v0, const T v1, real_type_tag)
+            
+            inline void restore()
             {
-               return std::sqrt((v0 * v0) + (v1 * v1));
+                token_itr_ = store_token_itr_;
             }
-
-            template <typename T>
-            inline T hypot_impl(const T v0, const T v1, int_type_tag)
+            
+            inline token_t& next_token()
             {
-               return static_cast<T>(std::sqrt(static_cast<double>((v0 * v0) + (v1 * v1))));
+                if (token_list_.end() != token_itr_)
+                {
+                    return *token_itr_++;
+                }
+                else
+                    return eof_token_;
             }
-
-            template <typename T>
-            inline T atan2_impl(const T v0, const T v1, real_type_tag)
+            
+            inline token_t& peek_next_token()
             {
-               return std::atan2(v0,v1);
+                if (token_list_.end() != token_itr_)
+                {
+                    return *token_itr_;
+                }
+                else
+                    return eof_token_;
             }
-
-            template <typename T>
-            inline T atan2_impl(const T, const T, int_type_tag)
+            
+            inline token_t& operator[](const std::size_t& index)
             {
-               return 0;
+                if (index < token_list_.size())
+                    return token_list_[index];
+                else
+                    return eof_token_;
             }
-
-            template <typename T>
-            inline T shr_impl(const T v0, const T v1, real_type_tag)
+            
+            inline token_t operator[](const std::size_t& index) const
             {
-               return v0 * (T(1) / std::pow(T(2),static_cast<T>(static_cast<int>(v1))));
+                if (index < token_list_.size())
+                    return token_list_[index];
+                else
+                    return eof_token_;
             }
-
-            template <typename T>
-            inline T shr_impl(const T v0, const T v1, int_type_tag)
+            
+            inline bool finished() const
             {
-               return v0 >> v1;
+                return (token_list_.end() == token_itr_);
             }
-
-            template <typename T>
-            inline T shl_impl(const T v0, const T v1, real_type_tag)
+            
+            inline void insert_front(token_t::token_type tk_type)
             {
-               return v0 * std::pow(T(2),static_cast<T>(static_cast<int>(v1)));
+                if (
+                    !token_list_.empty() &&
+                    (token_list_.end() != token_itr_)
+                    )
+                {
+                    token_t t = *token_itr_;
+                    
+                    t.type     = tk_type;
+                    token_itr_ = token_list_.insert(token_itr_,t);
+                }
+            }
+            
+            inline std::string substr(const std::size_t& begin, const std::size_t& end)
+            {
+                const char* begin_itr = ((base_itr_ + begin) < s_end_) ? (base_itr_ + begin) : s_end_;
+                const char* end_itr   = ((base_itr_ +   end) < s_end_) ? (base_itr_ +   end) : s_end_;
+                
+                return std::string(begin_itr,end_itr);
+            }
+            
+            inline std::string remaining() const
+            {
+                if (finished())
+                    return "";
+                else if (token_list_.begin() != token_itr_)
+                    return std::string(base_itr_ + (token_itr_ - 1)->position,s_end_);
+                else
+                    return std::string(base_itr_ + token_itr_->position,s_end_);
+            }
+            
+        private:
+            
+            inline bool is_end(const char* itr)
+            {
+                return (s_end_ == itr);
+            }
+            
+            inline void skip_whitespace()
+            {
+                while (!is_end(s_itr_) && details::is_whitespace(*s_itr_))
+                {
+                    ++s_itr_;
+                }
+            }
+            
+            inline void skip_comments()
+            {
+#ifndef exprtk_disable_comments
+                // The following comment styles are supported:
+                // 1. // .... \n
+                // 2. #  .... \n
+                // 3. /* .... */
+                struct test
+                {
+                    static inline bool comment_start(const char_t c0, const char_t c1, int& mode, int& incr)
+                    {
+                        mode = 0;
+                        if ('#' == c0)    { mode = 1; incr = 1; }
+                        else if ('/' == c0)
+                        {
+                            if ('/' == c1) { mode = 1; incr = 2; }
+                            else if ('*' == c1) { mode = 2; incr = 2; }
+                        }
+                        return (0 != mode);
+                    }
+                    
+                    static inline bool comment_end(const char_t c0, const char_t c1, const int mode)
+                    {
+                        return (
+                                ((1 == mode) && ('\n' == c0)) ||
+                                ((2 == mode) && ( '*' == c0) && ('/' == c1))
+                                );
+                    }
+                };
+                
+                int mode      = 0;
+                int increment = 0;
+                
+                if (is_end(s_itr_) || is_end((s_itr_ + 1)))
+                    return;
+                else if (!test::comment_start(*s_itr_,*(s_itr_ + 1),mode,increment))
+                    return;
+                
+                s_itr_ += increment;
+                
+                while (!is_end(s_itr_) && !test::comment_end(*s_itr_,*(s_itr_ + 1),mode))
+                {
+                    ++s_itr_;
+                }
+                
+                if (!is_end(s_itr_))
+                {
+                    s_itr_ += mode;
+                    skip_whitespace();
+                    skip_comments();
+                }
+#endif
             }
-
-            template <typename T>
-            inline T shl_impl(const T v0, const T v1, int_type_tag)
-            {
-               return v0 << v1;
+            
+            inline void scan_token()
+            {
+                skip_whitespace();
+                
+                skip_comments();
+                
+                if (is_end(s_itr_))
+                {
+                    return;
+                }
+                else if (details::is_operator_char(*s_itr_))
+                {
+                    scan_operator();
+                    return;
+                }
+                else if (details::is_letter(*s_itr_))
+                {
+                    scan_symbol();
+                    return;
+                }
+                else if (details::is_digit((*s_itr_)) || ('.' == (*s_itr_)))
+                {
+                    scan_number();
+                    return;
+                }
+                else if ('$' == (*s_itr_))
+                {
+                    scan_special_function();
+                    return;
+                }
+#ifndef exprtk_disable_string_capabilities
+                else if ('\'' == (*s_itr_))
+                {
+                    scan_string();
+                    return;
+                }
+#endif
+                else if ('~' == (*s_itr_))
+                {
+                    token_t t;
+                    t.set_symbol(s_itr_,s_itr_ + 1,base_itr_);
+                    token_list_.push_back(t);
+                    ++s_itr_;
+                    return;
+                }
+                else
+                {
+                    token_t t;
+                    t.set_error(token::e_error,s_itr_,s_itr_ + 2,base_itr_);
+                    token_list_.push_back(t);
+                    ++s_itr_;
+                }
+            }
+            
+            inline void scan_operator()
+            {
+                token_t t;
+                
+                const char_t c0 = s_itr_[0];
+                
+                if (!is_end(s_itr_ + 1))
+                {
+                    const char_t c1 = s_itr_[1];
+                    
+                    if (!is_end(s_itr_ + 2))
+                    {
+                        const char_t c2 = s_itr_[2];
+                        
+                        if ((c0 == '<') && (c1 == '=') && (c2 == '>'))
+                        {
+                            t.set_operator(token_t::e_swap,s_itr_,s_itr_ + 3,base_itr_);
+                            token_list_.push_back(t);
+                            s_itr_ += 3;
+                            return;
+                        }
+                    }
+                    
+                    token_t::token_type ttype = token_t::e_none;
+                    
+                    if ((c0 == '<') && (c1 == '=')) ttype = token_t::e_lte;
+                    else if ((c0 == '>') && (c1 == '=')) ttype = token_t::e_gte;
+                    else if ((c0 == '<') && (c1 == '>')) ttype = token_t::e_ne;
+                    else if ((c0 == '!') && (c1 == '=')) ttype = token_t::e_ne;
+                    else if ((c0 == '=') && (c1 == '=')) ttype = token_t::e_eq;
+                    else if ((c0 == ':') && (c1 == '=')) ttype = token_t::e_assign;
+                    else if ((c0 == '<') && (c1 == '<')) ttype = token_t::e_shl;
+                    else if ((c0 == '>') && (c1 == '>')) ttype = token_t::e_shr;
+                    else if ((c0 == '+') && (c1 == '=')) ttype = token_t::e_addass;
+                    else if ((c0 == '-') && (c1 == '=')) ttype = token_t::e_subass;
+                    else if ((c0 == '*') && (c1 == '=')) ttype = token_t::e_mulass;
+                    else if ((c0 == '/') && (c1 == '=')) ttype = token_t::e_divass;
+                    else if ((c0 == '%') && (c1 == '=')) ttype = token_t::e_modass;
+                    
+                    if (token_t::e_none != ttype)
+                    {
+                        t.set_operator(ttype,s_itr_,s_itr_ + 2,base_itr_);
+                        token_list_.push_back(t);
+                        s_itr_ += 2;
+                        return;
+                    }
+                }
+                
+                if ('<' == c0)
+                    t.set_operator(token_t::e_lt ,s_itr_,s_itr_ + 1,base_itr_);
+                else if ('>' == c0)
+                    t.set_operator(token_t::e_gt ,s_itr_,s_itr_ + 1,base_itr_);
+                else if (';' == c0)
+                    t.set_operator(token_t::e_eof,s_itr_,s_itr_ + 1,base_itr_);
+                else if ('&' == c0)
+                    t.set_symbol(s_itr_,s_itr_ + 1,base_itr_);
+                else if ('|' == c0)
+                    t.set_symbol(s_itr_,s_itr_ + 1,base_itr_);
+                else
+                    t.set_operator(token_t::token_type(c0),s_itr_,s_itr_ + 1,base_itr_);
+                
+                token_list_.push_back(t);
+                ++s_itr_;
+            }
+            
+            inline void scan_symbol()
+            {
+                const char* initial_itr = s_itr_;
+                
+                while (!is_end(s_itr_))
+                {
+                    if (!details::is_letter_or_digit(*s_itr_) && ('_' != (*s_itr_)))
+                    {
+                        if ('.' != (*s_itr_))
+                            break;
+                        /*
+                         Permit symbols that contain a 'dot'
+                         Allowed   : abc.xyz, a123.xyz, abc.123, abc_.xyz a123_.xyz abc._123
+                         Disallowed: .abc, abc.<white-space>, abc.<eof>, abc.<operator +,-,*,/...>
+                         */
+                        if (
+                            (s_itr_ != initial_itr)                  &&
+                            !is_end(s_itr_ + 1)                      &&
+                            details::is_letter_or_digit(*s_itr_ + 1) &&
+                            ('_' != (*s_itr_ + 1))
+                            )
+                            break;
+                    }
+                    
+                    ++s_itr_;
+                }
+                
+                token_t t;
+                t.set_symbol(initial_itr,s_itr_,base_itr_);
+                token_list_.push_back(t);
+            }
+            
+            inline void scan_number()
+            {
+                /*
+                 Attempt to match a valid numeric value in one of the following formats:
+                 01. 123456
+                 02. 123.456
+                 03. 123.456e3
+                 04. 123.456E3
+                 05. 123.456e+3
+                 06. 123.456E+3
+                 07. 123.456e-3
+                 08. 123.456E-3
+                 09. .1234
+                 10. .1234e3
+                 11. .1234E+3
+                 12. .1234e+3
+                 13. .1234E-3
+                 14. .1234e-3
+                 */
+                const char* 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_))
+                {
+                    if ('.' == (*s_itr_))
+                    {
+                        if (dot_found)
+                        {
+                            t.set_error(token::e_err_number,initial_itr,s_itr_,base_itr_);
+                            token_list_.push_back(t);
+                            return;
+                        }
+                        
+                        dot_found = true;
+                        ++s_itr_;
+                        
+                        continue;
+                    }
+                    else if (details::imatch('e',(*s_itr_)))
+                    {
+                        const char& c = *(s_itr_ + 1);
+                        
+                        if (is_end(s_itr_ + 1))
+                        {
+                            t.set_error(token::e_err_number,initial_itr,s_itr_,base_itr_);
+                            token_list_.push_back(t);
+                            
+                            return;
+                        }
+                        else if (
+                                 ('+' != c) &&
+                                 ('-' != c) &&
+                                 !details::is_digit(c)
+                                 )
+                        {
+                            t.set_error(token::e_err_number,initial_itr,s_itr_,base_itr_);
+                            token_list_.push_back(t);
+                            
+                            return;
+                        }
+                        
+                        e_found = true;
+                        ++s_itr_;
+                        
+                        continue;
+                    }
+                    else if (e_found && details::is_sign(*s_itr_) && !post_e_digit_found)
+                    {
+                        if (post_e_sign_found)
+                        {
+                            t.set_error(token::e_err_number,initial_itr,s_itr_,base_itr_);
+                            token_list_.push_back(t);
+                            
+                            return;
+                        }
+                        
+                        post_e_sign_found = true;
+                        ++s_itr_;
+                        
+                        continue;
+                    }
+                    else if (e_found && details::is_digit(*s_itr_))
+                    {
+                        post_e_digit_found = true;
+                        ++s_itr_;
+                        
+                        continue;
+                    }
+                    else if (('.' != (*s_itr_)) && !details::is_digit(*s_itr_))
+                        break;
+                    else
+                        ++s_itr_;
+                }
+                
+                t.set_numeric(initial_itr,s_itr_,base_itr_);
+                token_list_.push_back(t);
+                
+                return;
+            }
+            
+            inline void scan_special_function()
+            {
+                const char* initial_itr = s_itr_;
+                token_t t;
+                
+                // $fdd(x,x,x) = at least 11 chars
+                if (std::distance(s_itr_,s_end_) < 11)
+                {
+                    t.set_error(token::e_err_sfunc,initial_itr,s_itr_,base_itr_);
+                    token_list_.push_back(t);
+                    
+                    return;
+                }
+                
+                if (
+                    !(('$' == *s_itr_)                       &&
+                      (details::imatch  ('f',*(s_itr_ + 1))) &&
+                      (details::is_digit(*(s_itr_ + 2)))     &&
+                      (details::is_digit(*(s_itr_ + 3))))
+                    )
+                {
+                    t.set_error(token::e_err_sfunc,initial_itr,s_itr_,base_itr_);
+                    token_list_.push_back(t);
+                    
+                    return;
+                }
+                
+                s_itr_ += 4; // $fdd = 4chars
+                
+                t.set_symbol(initial_itr,s_itr_,base_itr_);
+                token_list_.push_back(t);
+                
+                return;
+            }
+            
+#ifndef exprtk_disable_string_capabilities
+            inline void scan_string()
+            {
+                const char* 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;
+                }
+                
+                ++s_itr_;
+                
+                bool escaped_found = false;
+                bool escaped = false;
+                
+                while (!is_end(s_itr_))
+                {
+                    if (!escaped && ('\\' == *s_itr_))
+                    {
+                        escaped_found = true;
+                        escaped = true;
+                        ++s_itr_;
+                        
+                        continue;
+                    }
+                    else if (!escaped)
+                    {
+                        if ('\'' == *s_itr_)
+                            break;
+                    }
+                    else if (escaped)
+                    {
+                        if (!is_end(s_itr_) && ('0' == *(s_itr_)))
+                        {
+                            /*
+                             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' == *(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)) ;
+                            
+                            if (!within_range || !x_seperator || !both_digits)
+                            {
+                                t.set_error(token::e_err_string,initial_itr,s_itr_,base_itr_);
+                                token_list_.push_back(t);
+                                
+                                return;
+                            }
+                            else
+                                s_itr_ += 3;
+                        }
+                        
+                        escaped = false;
+                    }
+                    
+                    ++s_itr_;
+                }
+                
+                if (is_end(s_itr_))
+                {
+                    t.set_error(token::e_err_string,initial_itr,s_itr_,base_itr_);
+                    token_list_.push_back(t);
+                    
+                    return;
+                }
+                
+                if (!escaped_found)
+                    t.set_string(initial_itr,s_itr_,base_itr_);
+                else
+                {
+                    std::string parsed_string(initial_itr,s_itr_);
+                    details::cleanup_escapes(parsed_string);
+                    t.set_string(parsed_string, std::distance(base_itr_,initial_itr));
+                }
+                
+                token_list_.push_back(t);
+                ++s_itr_;
+                
+                return;
             }
-
-            template <typename T>
-            inline T sgn_impl(const T v, real_type_tag)
-            {
-                    if (v > T(0)) return T(+1);
-               else if (v < T(0)) return T(-1);
-               else               return T( 0);
+#endif
+            
+        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* base_itr_;
+            const char* s_itr_;
+            const char* s_end_;
+            
+            friend class token_scanner;
+            friend class token_modifier;
+            friend class token_inserter;
+            friend class token_joiner;
+        };
+        
+        class helper_interface
+        {
+        public:
+            
+            virtual void init()                     {              }
+            virtual void reset()                    {              }
+            virtual bool result()                   { return true; }
+            virtual std::size_t process(generator&) { return 0;    }
+            virtual ~helper_interface()             {              }
+        };
+        
+        class token_scanner : public helper_interface
+        {
+        public:
+            
+            virtual ~token_scanner()
+            {}
+            
+            explicit token_scanner(const std::size_t& stride)
+            : stride_(stride)
+            {
+                if (stride > 4)
+                {
+                    throw std::invalid_argument("token_scanner() - Invalid stride value");
+                }
+            }
+            
+            inline std::size_t process(generator& g)
+            {
+                if (g.token_list_.size() >= stride_)
+                {
+                    for (std::size_t i = 0; i < (g.token_list_.size() - stride_ + 1); ++i)
+                    {
+                        token t;
+                        
+                        switch (stride_)
+                        {
+                            case 1 :
+                            {
+                                const token& t0 = g.token_list_[i];
+                                
+                                if (!operator()(t0))
+                                {
+                                    return i;
+                                }
+                            }
+                                break;
+                                
+                            case 2 :
+                            {
+                                const token& t0 = g.token_list_[i    ];
+                                const token& t1 = g.token_list_[i + 1];
+                                
+                                if (!operator()(t0,t1))
+                                {
+                                    return i;
+                                }
+                            }
+                                break;
+                                
+                            case 3 :
+                            {
+                                const token& t0 = g.token_list_[i    ];
+                                const token& t1 = g.token_list_[i + 1];
+                                const token& t2 = g.token_list_[i + 2];
+                                
+                                if (!operator()(t0,t1,t2))
+                                {
+                                    return i;
+                                }
+                            }
+                                break;
+                                
+                            case 4 :
+                            {
+                                const token& t0 = g.token_list_[i    ];
+                                const token& t1 = g.token_list_[i + 1];
+                                const token& t2 = g.token_list_[i + 2];
+                                const token& t3 = g.token_list_[i + 3];
+                                
+                                if (!operator()(t0,t1,t2,t3))
+                                {
+                                    return i;
+                                }
+                            }
+                                break;
+                        }
+                    }
+                }
+                
+                return (g.token_list_.size() - stride_ + 1);
             }
-
-            template <typename T>
-            inline T sgn_impl(const T v, int_type_tag)
+            
+            virtual bool operator()(const token&)
             {
-                    if (v > T(0)) return T(+1);
-               else if (v < T(0)) return T(-1);
-               else               return T( 0);
+                return false;
             }
-
-            template <typename T>
-            inline T and_impl(const T v0, const T v1, real_type_tag)
+            
+            virtual bool operator()(const token&, const token&)
             {
-               return (is_true_impl(v0) && is_true_impl(v1)) ? T(1) : T(0);
+                return false;
             }
-
-            template <typename T>
-            inline T and_impl(const T v0, const T v1, int_type_tag)
+            
+            virtual bool operator()(const token&, const token&, const token&)
             {
-               return v0 && v1;
+                return false;
             }
-
-            template <typename T>
-            inline T nand_impl(const T v0, const T v1, real_type_tag)
+            
+            virtual bool operator()(const token&, const token&, const token&, const token&)
             {
-               return (is_false_impl(v0) || is_false_impl(v1)) ? T(1) : T(0);
+                return false;
             }
-
-            template <typename T>
-            inline T nand_impl(const T v0, const T v1, int_type_tag)
+            
+        private:
+            
+            std::size_t stride_;
+        };
+        
+        class token_modifier : public helper_interface
+        {
+        public:
+            
+            inline std::size_t process(generator& g)
+            {
+                std::size_t changes = 0;
+                
+                for (std::size_t i = 0; i < g.token_list_.size(); ++i)
+                {
+                    if (modify(g.token_list_[i])) changes++;
+                }
+                
+                return changes;
+            }
+            
+            virtual bool modify(token& t) = 0;
+        };
+        
+        class token_inserter : public helper_interface
+        {
+        public:
+            
+            explicit token_inserter(const std::size_t& stride)
+            : stride_(stride)
+            {
+                if (stride > 5)
+                {
+                    throw std::invalid_argument("token_inserter() - Invalid stride value");
+                }
+            }
+            
+            inline std::size_t process(generator& g)
+            {
+                if (g.token_list_.empty())
+                    return 0;
+                else if (g.token_list_.size() < stride_)
+                    return 0;
+                
+                std::size_t changes = 0;
+                
+                for (std::size_t i = 0; i < (g.token_list_.size() - stride_ + 1); ++i)
+                {
+                    int insert_index = -1;
+                    token t;
+                    
+                    switch (stride_)
+                    {
+                        case 1 : insert_index = insert(g.token_list_[i],t);
+                            break;
+                            
+                        case 2 : insert_index = insert(g.token_list_[i],g.token_list_[i + 1],t);
+                            break;
+                            
+                        case 3 : insert_index = insert(g.token_list_[i],g.token_list_[i + 1],g.token_list_[i + 2],t);
+                            break;
+                            
+                        case 4 : insert_index = insert(g.token_list_[i],g.token_list_[i + 1],g.token_list_[i + 2],g.token_list_[i + 3],t);
+                            break;
+                            
+                        case 5 : insert_index = insert(g.token_list_[i],g.token_list_[i + 1],g.token_list_[i + 2],g.token_list_[i + 3],g.token_list_[i + 4],t);
+                            break;
+                    }
+                    
+                    if ((insert_index >= 0) && (insert_index <= (static_cast<int>(stride_) + 1)))
+                    {
+                        g.token_list_.insert(g.token_list_.begin() + (i + insert_index),t);
+                        changes++;
+                    }
+                }
+                
+                return changes;
+            }
+            
+#define token_inserter_empty_body \
+{                                 \
+return -1;                     \
+}                                 \
+
+            inline virtual int insert(const token&, token&)
+            token_inserter_empty_body
+            
+            inline virtual int insert(const token&, const token&, token&)
+            token_inserter_empty_body
+            
+            inline virtual int insert(const token&, const token&, const token&, token&)
+            token_inserter_empty_body
+            
+            inline virtual int insert(const token&, const token&, const token&, const token&, token&)
+            token_inserter_empty_body
+            
+            inline virtual int insert(const token&, const token&, const token&, const token&, const token&, token&)
+            token_inserter_empty_body
+            
+#undef token_inserter_empty_body
+            
+        private:
+            
+            std::size_t stride_;
+        };
+        
+        class token_joiner : public helper_interface
+        {
+        public:
+            
+            token_joiner(const std::size_t& stride)
+            : stride_(stride)
+            {}
+            
+            inline std::size_t process(generator& g)
+            {
+                if (g.token_list_.empty())
+                    return 0;
+                
+                switch (stride_)
+                {
+                    case 2  : return process_stride_2(g);
+                    case 3  : return process_stride_3(g);
+                    default : return 0;
+                }
+            }
+            
+            virtual bool join(const token&, const token&, token&) { return false; }
+            virtual bool join(const token&, const token&, const token&, token&) { return false; }
+            
+        private:
+            
+            inline std::size_t process_stride_2(generator& g)
+            {
+                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)
+                {
+                    token t;
+                    
+                    while (join(g[i],g[i + 1],t))
+                    {
+                        g.token_list_[i] = t;
+                        
+                        g.token_list_.erase(g.token_list_.begin() + (i + 1));
+                        
+                        ++changes;
+                    }
+                }
+                
+                return changes;
+            }
+            
+            inline std::size_t process_stride_3(generator& g)
+            {
+                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)
+                {
+                    token t;
+                    
+                    while (join(g[i],g[i + 1],g[i + 2],t))
+                    {
+                        g.token_list_[i] = t;
+                        
+                        g.token_list_.erase(g.token_list_.begin() + (i + 1),
+                                            g.token_list_.begin() + (i + 3));
+                        ++changes;
+                    }
+                }
+                
+                return changes;
+            }
+            
+            std::size_t stride_;
+        };
+        
+        namespace helper
+        {
+            
+            inline void dump(lexer::generator& generator)
+            {
+                for (std::size_t i = 0; i < generator.size(); ++i)
+                {
+                    lexer::token t = generator[i];
+                    printf("Token[%02d] @ %03d  %6s  -->  '%s'\n",
+                           static_cast<int>(i),
+                           static_cast<int>(t.position),
+                           t.to_str(t.type).c_str(),
+                           t.value.c_str());
+                }
+            }
+            
+            class commutative_inserter : public lexer::token_inserter
+            {
+            public:
+                
+                using lexer::token_inserter::insert;
+                
+                commutative_inserter()
+                : lexer::token_inserter(2)
+                {}
+                
+                inline void ignore_symbol(const std::string& symbol)
+                {
+                    ignore_set_.insert(symbol);
+                }
+                
+                inline int insert(const lexer::token& t0, const lexer::token& t1, lexer::token& new_token)
+                {
+                    bool match         = false;
+                    new_token.type     = lexer::token::e_mul;
+                    new_token.value    = "*";
+                    new_token.position = t1.position;
+                    
+                    if (t0.type == lexer::token::e_symbol)
+                    {
+                        if (ignore_set_.end() != ignore_set_.find(t0.value))
+                        {
+                            return -1;
+                        }
+                        else if (!t0.value.empty() && ('$' == t0.value[0]))
+                        {
+                            return -1;
+                        }
+                    }
+                    
+                    if (t1.type == lexer::token::e_symbol)
+                    {
+                        if (ignore_set_.end() != ignore_set_.find(t1.value))
+                        {
+                            return -1;
+                        }
+                    }
+                    if ((t0.type == lexer::token::e_number     ) && (t1.type == lexer::token::e_symbol     )) match = true;
+                    else if ((t0.type == lexer::token::e_number     ) && (t1.type == lexer::token::e_lbracket   )) match = true;
+                    else if ((t0.type == lexer::token::e_number     ) && (t1.type == lexer::token::e_lcrlbracket)) match = true;
+                    else if ((t0.type == lexer::token::e_number     ) && (t1.type == lexer::token::e_lsqrbracket)) match = true;
+                    else if ((t0.type == lexer::token::e_symbol     ) && (t1.type == lexer::token::e_number     )) match = true;
+                    else if ((t0.type == lexer::token::e_rbracket   ) && (t1.type == lexer::token::e_number     )) match = true;
+                    else if ((t0.type == lexer::token::e_rcrlbracket) && (t1.type == lexer::token::e_number     )) match = true;
+                    else if ((t0.type == lexer::token::e_rsqrbracket) && (t1.type == lexer::token::e_number     )) match = true;
+                    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;
+                    
+                    return (match) ? 1 : -1;
+                }
+                
+            private:
+                
+                std::set<std::string,details::ilesscompare> ignore_set_;
+            };
+            
+            class operator_joiner : public token_joiner
+            {
+            public:
+                
+                operator_joiner(const std::size_t& stride)
+                : token_joiner(stride)
+                {}
+                
+                inline bool join(const lexer::token& t0, const lexer::token& t1, lexer::token& t)
+                {
+                    // ': =' --> ':='
+                    if ((t0.type == lexer::token::e_colon) && (t1.type == lexer::token::e_eq))
+                    {
+                        t.type     = lexer::token::e_assign;
+                        t.value    = ":=";
+                        t.position = t0.position;
+                        
+                        return true;
+                    }
+                    // '+ =' --> '+='
+                    else if ((t0.type == lexer::token::e_add) && (t1.type == lexer::token::e_eq))
+                    {
+                        t.type     = lexer::token::e_addass;
+                        t.value    = "+=";
+                        t.position = t0.position;
+                        
+                        return true;
+                    }
+                    // '- =' --> '-='
+                    else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_eq))
+                    {
+                        t.type     = lexer::token::e_subass;
+                        t.value    = "-=";
+                        t.position = t0.position;
+                        
+                        return true;
+                    }
+                    // '* =' --> '*='
+                    else if ((t0.type == lexer::token::e_mul) && (t1.type == lexer::token::e_eq))
+                    {
+                        t.type     = lexer::token::e_mulass;
+                        t.value    = "*=";
+                        t.position = t0.position;
+                        
+                        return true;
+                    }
+                    // '/ =' --> '/='
+                    else if ((t0.type == lexer::token::e_div) && (t1.type == lexer::token::e_eq))
+                    {
+                        t.type     = lexer::token::e_divass;
+                        t.value    = "/=";
+                        t.position = t0.position;
+                        
+                        return true;
+                    }
+                    // '% =' --> '%='
+                    else if ((t0.type == lexer::token::e_mod) && (t1.type == lexer::token::e_eq))
+                    {
+                        t.type     = lexer::token::e_modass;
+                        t.value    = "%=";
+                        t.position = t0.position;
+                        
+                        return true;
+                    }
+                    // '> =' --> '>='
+                    else if ((t0.type == lexer::token::e_gt) && (t1.type == lexer::token::e_eq))
+                    {
+                        t.type     = lexer::token::e_gte;
+                        t.value    = ">=";
+                        t.position = t0.position;
+                        
+                        return true;
+                    }
+                    // '< =' --> '<='
+                    else if ((t0.type == lexer::token::e_lt) && (t1.type == lexer::token::e_eq))
+                    {
+                        t.type     = lexer::token::e_lte;
+                        t.value    = "<=";
+                        t.position = t0.position;
+                        
+                        return true;
+                    }
+                    // '= =' --> '=='
+                    else if ((t0.type == lexer::token::e_eq) && (t1.type == lexer::token::e_eq))
+                    {
+                        t.type     = lexer::token::e_eq;
+                        t.value    = "==";
+                        t.position = t0.position;
+                        
+                        return true;
+                    }
+                    // '! =' --> '!='
+                    else if ((static_cast<char>(t0.type) == '!') && (t1.type == lexer::token::e_eq))
+                    {
+                        t.type     = lexer::token::e_ne;
+                        t.value    = "!=";
+                        t.position = t0.position;
+                        
+                        return true;
+                    }
+                    // '< >' --> '<>'
+                    else if ((t0.type == lexer::token::e_lt) && (t1.type == lexer::token::e_gt))
+                    {
+                        t.type     = lexer::token::e_ne;
+                        t.value    = "<>";
+                        t.position = t0.position;
+                        
+                        return true;
+                    }
+                    // '<= >' --> '<=>'
+                    else if ((t0.type == lexer::token::e_lte) && (t1.type == lexer::token::e_gt))
+                    {
+                        t.type     = lexer::token::e_swap;
+                        t.value    = "<=>";
+                        t.position = t0.position;
+                        
+                        return true;
+                    }
+                    // '+ -' --> '-'
+                    else if ((t0.type == lexer::token::e_add) && (t1.type == lexer::token::e_sub))
+                    {
+                        t.type     = lexer::token::e_sub;
+                        t.value    = "-";
+                        t.position = t0.position;
+                        
+                        return true;
+                    }
+                    // '- +' --> '-'
+                    else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_add))
+                    {
+                        t.type     = lexer::token::e_sub;
+                        t.value    = "-";
+                        t.position = t0.position;
+                        
+                        return true;
+                    }
+                    // '- -' --> '-'
+                    else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_sub))
+                    {
+                        /*
+                         Note: May need to reconsider this when wanting to implement
+                         pre/postfix decrement operator
+                         */
+                        t.type     = lexer::token::e_add;
+                        t.value    = "+";
+                        t.position = t0.position;
+                        
+                        return true;
+                    }
+                    else
+                        return false;
+                }
+                
+                inline bool join(const lexer::token& t0, const lexer::token& t1, const lexer::token& t2, lexer::token& t)
+                {
+                    // '[ * ]' --> '[*]'
+                    if (
+                        (t0.type == lexer::token::e_lsqrbracket) &&
+                        (t1.type == lexer::token::e_mul        ) &&
+                        (t2.type == lexer::token::e_rsqrbracket)
+                        )
+                    {
+                        t.type     = lexer::token::e_symbol;
+                        t.value    = "[*]";
+                        t.position = t0.position;
+                        
+                        return true;
+                    }
+                    else
+                        return false;
+                }
+            };
+            
+            class bracket_checker : public lexer::token_scanner
+            {
+            public:
+                
+                using lexer::token_scanner::operator();
+                
+                bracket_checker()
+                : token_scanner(1),
+                state_(true)
+                {}
+                
+                bool result()
+                {
+                    if (!stack_.empty())
+                    {
+                        lexer::token t;
+                        t.value      = stack_.top().first;
+                        t.position   = stack_.top().second;
+                        error_token_ = t;
+                        state_       = false;
+                        
+                        return false;
+                    }
+                    else
+                        return state_;
+                }
+                
+                lexer::token error_token()
+                {
+                    return error_token_;
+                }
+                
+                void reset()
+                {
+                    // Why? because msvc doesn't support swap properly.
+                    stack_ = std::stack<std::pair<char,std::size_t> >();
+                    state_ = true;
+                    error_token_.clear();
+                }
+                
+                bool operator()(const lexer::token& t)
+                {
+                    if (
+                        !t.value.empty()                       &&
+                        (lexer::token::e_string != t.type)     &&
+                        (lexer::token::e_symbol != t.type)     &&
+                        exprtk::details::is_bracket(t.value[0])
+                        )
+                    {
+                        details::char_t c = t.value[0];
+                        
+                        if (t.type == lexer::token::e_lbracket)    stack_.push(std::make_pair(')',t.position));
+                        else if (t.type == lexer::token::e_lcrlbracket) stack_.push(std::make_pair('}',t.position));
+                        else if (t.type == lexer::token::e_lsqrbracket) stack_.push(std::make_pair(']',t.position));
+                        else if (exprtk::details::is_right_bracket(c))
+                        {
+                            if (stack_.empty())
+                            {
+                                state_       = false;
+                                error_token_ = t;
+                                
+                                return false;
+                            }
+                            else if (c != stack_.top().first)
+                            {
+                                state_       = false;
+                                error_token_ = t;
+                                
+                                return false;
+                            }
+                            else
+                                stack_.pop();
+                        }
+                    }
+                    
+                    return true;
+                }
+                
+            private:
+                
+                bool state_;
+                std::stack<std::pair<char,std::size_t> > stack_;
+                lexer::token error_token_;
+            };
+            
+            class numeric_checker : public lexer::token_scanner
+            {
+            public:
+                
+                using lexer::token_scanner::operator();
+                
+                numeric_checker()
+                : token_scanner (1),
+                current_index_(0)
+                {}
+                
+                bool result()
+                {
+                    return error_list_.empty();
+                }
+                
+                void reset()
+                {
+                    error_list_.clear();
+                    current_index_ = 0;
+                }
+                
+                bool operator()(const lexer::token& t)
+                {
+                    if (token::e_number == t.type)
+                    {
+                        double v;
+                        
+                        if (!exprtk::details::string_to_real(t.value,v))
+                        {
+                            error_list_.push_back(current_index_);
+                        }
+                    }
+                    
+                    ++current_index_;
+                    
+                    return true;
+                }
+                
+                std::size_t error_count() const
+                {
+                    return error_list_.size();
+                }
+                
+                std::size_t error_index(const std::size_t& i)
+                {
+                    if (i < error_list_.size())
+                        return error_list_[i];
+                    else
+                        return std::numeric_limits<std::size_t>::max();
+                }
+                
+                void clear_errors()
+                {
+                    error_list_.clear();
+                }
+                
+            private:
+                
+                std::size_t current_index_;
+                std::vector<std::size_t> error_list_;
+            };
+            
+            class symbol_replacer : public lexer::token_modifier
+            {
+            private:
+                
+                typedef std::map<std::string,std::pair<std::string,token::token_type>,details::ilesscompare> replace_map_t;
+                
+            public:
+                
+                bool remove(const std::string& target_symbol)
+                {
+                    replace_map_t::iterator itr = replace_map_.find(target_symbol);
+                    
+                    if (replace_map_.end() == itr)
+                        return false;
+                    
+                    replace_map_.erase(itr);
+                    
+                    return true;
+                }
+                
+                bool add_replace(const std::string& target_symbol,
+                                 const std::string& replace_symbol,
+                                 const lexer::token::token_type token_type = lexer::token::e_symbol)
+                {
+                    replace_map_t::iterator itr = replace_map_.find(target_symbol);
+                    
+                    if (replace_map_.end() != itr)
+                    {
+                        return false;
+                    }
+                    
+                    replace_map_[target_symbol] = std::make_pair(replace_symbol,token_type);
+                    
+                    return true;
+                }
+                
+                void clear()
+                {
+                    replace_map_.clear();
+                }
+                
+            private:
+                
+                bool modify(lexer::token& t)
+                {
+                    if (lexer::token::e_symbol == t.type)
+                    {
+                        if (replace_map_.empty())
+                            return false;
+                        
+                        replace_map_t::iterator itr = replace_map_.find(t.value);
+                        
+                        if (replace_map_.end() != itr)
+                        {
+                            t.value = itr->second.first;
+                            t.type  = itr->second.second;
+                            
+                            return true;
+                        }
+                    }
+                    
+                    return false;
+                }
+                
+                replace_map_t replace_map_;
+            };
+            
+            class sequence_validator : public lexer::token_scanner
+            {
+            private:
+                
+                typedef std::pair<lexer::token::token_type,lexer::token::token_type> token_pair_t;
+                typedef std::set<token_pair_t> set_t;
+                
+            public:
+                
+                using lexer::token_scanner::operator();
+                
+                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_string ,lexer::token::e_ternary);
+                    add_invalid_set1(lexer::token::e_assign );
+                    add_invalid_set1(lexer::token::e_shr    );
+                    add_invalid_set1(lexer::token::e_shl    );
+                    add_invalid_set1(lexer::token::e_lte    );
+                    add_invalid_set1(lexer::token::e_ne     );
+                    add_invalid_set1(lexer::token::e_gte    );
+                    add_invalid_set1(lexer::token::e_lt     );
+                    add_invalid_set1(lexer::token::e_gt     );
+                    add_invalid_set1(lexer::token::e_eq     );
+                    add_invalid_set1(lexer::token::e_comma  );
+                    add_invalid_set1(lexer::token::e_add    );
+                    add_invalid_set1(lexer::token::e_sub    );
+                    add_invalid_set1(lexer::token::e_div    );
+                    add_invalid_set1(lexer::token::e_mul    );
+                    add_invalid_set1(lexer::token::e_mod    );
+                    add_invalid_set1(lexer::token::e_pow    );
+                    add_invalid_set1(lexer::token::e_colon  );
+                    add_invalid_set1(lexer::token::e_ternary);
+                }
+                
+                bool result()
+                {
+                    return error_list_.empty();
+                }
+                
+                bool operator()(const lexer::token& t0, const lexer::token& t1)
+                {
+                    set_t::value_type p = std::make_pair(t0.type,t1.type);
+                    
+                    if (invalid_bracket_check(t0.type,t1.type))
+                    {
+                        error_list_.push_back(std::make_pair(t0,t1));
+                    }
+                    else if (invalid_comb_.find(p) != invalid_comb_.end())
+                    {
+                        error_list_.push_back(std::make_pair(t0,t1));
+                    }
+                    
+                    return true;
+                }
+                
+                std::size_t error_count()
+                {
+                    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(lexer::token::token_type base, lexer::token::token_type t)
+                {
+                    invalid_comb_.insert(std::make_pair(base,t));
+                }
+                
+                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 );
+                }
+                
+                bool invalid_bracket_check(lexer::token::token_type base, lexer::token::token_type t)
+                {
+                    if (details::is_right_bracket(static_cast<char>(base)))
+                    {
+                        switch (t)
+                        {
+                            case lexer::token::e_assign : return (']' != base);
+                            case lexer::token::e_string : return true;
+                            default                     : return false;
+                        }
+                    }
+                    else if (details::is_left_bracket(static_cast<char>(base)))
+                    {
+                        if (details::is_right_bracket(static_cast<char>(t)))
+                            return false;
+                        else if (details::is_left_bracket(static_cast<char>(t)))
+                            return false;
+                        else
+                        {
+                            switch (t)
+                            {
+                                case lexer::token::e_number  : return false;
+                                case lexer::token::e_symbol  : return false;
+                                case lexer::token::e_string  : return false;
+                                case lexer::token::e_add     : return false;
+                                case lexer::token::e_sub     : return false;
+                                case lexer::token::e_colon   : return false;
+                                case lexer::token::e_ternary : return false;
+                                default                      : return true;
+                            }
+                        }
+                    }
+                    else if (details::is_right_bracket(static_cast<char>(t)))
+                    {
+                        switch (base)
+                        {
+                            case lexer::token::e_number  : return false;
+                            case lexer::token::e_symbol  : return false;
+                            case lexer::token::e_string  : return false;
+                            case lexer::token::e_eof     : return false;
+                            case lexer::token::e_colon   : return false;
+                            case lexer::token::e_ternary : return false;
+                            default                      : return true;
+                        }
+                    }
+                    else if (details::is_left_bracket(static_cast<char>(t)))
+                    {
+                        switch (base)
+                        {
+                            case lexer::token::e_rbracket    : return true;
+                            case lexer::token::e_rsqrbracket : return true;
+                            case lexer::token::e_rcrlbracket : return true;
+                            default                          : return false;
+                        }
+                    }
+                    
+                    return false;
+                }
+                
+                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)
+                {
+                    if (token_scanner_list.end() != std::find(token_scanner_list.begin(),
+                                                              token_scanner_list.end(),
+                                                              scanner))
+                    {
+                        return false;
+                    }
+                    
+                    token_scanner_list.push_back(scanner);
+                    
+                    return true;
+                }
+                
+                inline bool register_modifier(lexer::token_modifier* modifier)
+                {
+                    if (token_modifier_list.end() != std::find(token_modifier_list.begin(),
+                                                               token_modifier_list.end(),
+                                                               modifier))
+                    {
+                        return false;
+                    }
+                    
+                    token_modifier_list.push_back(modifier);
+                    
+                    return true;
+                }
+                
+                inline bool register_joiner(lexer::token_joiner* joiner)
+                {
+                    if (token_joiner_list.end() != std::find(token_joiner_list.begin(),
+                                                             token_joiner_list.end(),
+                                                             joiner))
+                    {
+                        return false;
+                    }
+                    
+                    token_joiner_list.push_back(joiner);
+                    
+                    return true;
+                }
+                
+                inline bool register_inserter(lexer::token_inserter* inserter)
+                {
+                    if (token_inserter_list.end() != std::find(token_inserter_list.begin(),
+                                                               token_inserter_list.end(),
+                                                               inserter))
+                    {
+                        return false;
+                    }
+                    
+                    token_inserter_list.push_back(inserter);
+                    
+                    return true;
+                }
+                
+                inline bool run_modifiers(lexer::generator& g)
+                {
+                    error_token_modifier = reinterpret_cast<lexer::token_modifier*>(0);
+                    
+                    for (std::size_t i = 0; i < token_modifier_list.size(); ++i)
+                    {
+                        lexer::token_modifier& modifier = (*token_modifier_list[i]);
+                        
+                        modifier.reset();
+                        modifier.process(g);
+                        
+                        if (!modifier.result())
+                        {
+                            error_token_modifier = token_modifier_list[i];
+                            
+                            return false;
+                        }
+                    }
+                    
+                    return true;
+                }
+                
+                inline bool run_joiners(lexer::generator& g)
+                {
+                    error_token_joiner = reinterpret_cast<lexer::token_joiner*>(0);
+                    
+                    for (std::size_t i = 0; i < token_joiner_list.size(); ++i)
+                    {
+                        lexer::token_joiner& joiner = (*token_joiner_list[i]);
+                        
+                        joiner.reset();
+                        joiner.process(g);
+                        
+                        if (!joiner.result())
+                        {
+                            error_token_joiner = token_joiner_list[i];
+                            
+                            return false;
+                        }
+                    }
+                    
+                    return true;
+                }
+                
+                inline bool run_inserters(lexer::generator& g)
+                {
+                    error_token_inserter = reinterpret_cast<lexer::token_inserter*>(0);
+                    
+                    for (std::size_t i = 0; i < token_inserter_list.size(); ++i)
+                    {
+                        lexer::token_inserter& inserter = (*token_inserter_list[i]);
+                        
+                        inserter.reset();
+                        inserter.process(g);
+                        
+                        if (!inserter.result())
+                        {
+                            error_token_inserter = token_inserter_list[i];
+                            
+                            return false;
+                        }
+                    }
+                    
+                    return true;
+                }
+                
+                inline bool run_scanners(lexer::generator& g)
+                {
+                    error_token_scanner = reinterpret_cast<lexer::token_scanner*>(0);
+                    
+                    for (std::size_t i = 0; i < token_scanner_list.size(); ++i)
+                    {
+                        lexer::token_scanner& scanner = (*token_scanner_list[i]);
+                        
+                        scanner.reset();
+                        scanner.process(g);
+                        
+                        if (!scanner.result())
+                        {
+                            error_token_scanner = token_scanner_list[i];
+                            
+                            return false;
+                        }
+                    }
+                    
+                    return true;
+                }
+                
+                std::vector<lexer::token_scanner*>  token_scanner_list;
+                std::vector<lexer::token_modifier*> token_modifier_list;
+                std::vector<lexer::token_joiner*>   token_joiner_list;
+                std::vector<lexer::token_inserter*> token_inserter_list;
+                
+                lexer::token_scanner*  error_token_scanner;
+                lexer::token_modifier* error_token_modifier;
+                lexer::token_joiner*   error_token_joiner;
+                lexer::token_inserter* error_token_inserter;
+            };
+        }
+        
+        class parser_helper
+        {
+        public:
+            
+            typedef token         token_t;
+            typedef generator generator_t;
+            
+            inline bool init(const std::string& str)
             {
-               return !(v0 && v1);
+                if (!lexer_.process(str))
+                {
+                    return false;
+                }
+                
+                lexer_.begin();
+                
+                next_token();
+                
+                return true;
             }
-
-            template <typename T>
-            inline T or_impl(const T v0, const T v1, real_type_tag)
+            
+            inline generator_t& lexer()
             {
-               return (is_true_impl(v0) || is_true_impl(v1)) ? T(1) : T(0);
+                return lexer_;
             }
-
-            template <typename T>
-            inline T or_impl(const T v0, const T v1, int_type_tag)
+            
+            inline const generator_t& lexer() const
             {
-               return (v0 || v1);
+                return lexer_;
             }
-
-            template <typename T>
-            inline T nor_impl(const T v0, const T v1, real_type_tag)
+            
+            inline void store_token()
             {
-               return (is_false_impl(v0) && is_false_impl(v1)) ? T(1) : T(0);
+                lexer_.store();
+                store_current_token_ = current_token_;
             }
-
-            template <typename T>
-            inline T nor_impl(const T v0, const T v1, int_type_tag)
+            
+            inline void restore_token()
             {
-               return !(v0 || v1);
+                lexer_.restore();
+                current_token_ = store_current_token_;
             }
-
-            template <typename T>
-            inline T xor_impl(const T v0, const T v1, real_type_tag)
+            
+            inline void next_token()
             {
-               return (is_false_impl(v0) != is_false_impl(v1)) ? T(1) : T(0);
+                current_token_ = lexer_.next_token();
             }
-
-            template <typename T>
-            inline T xor_impl(const T v0, const T v1, int_type_tag)
+            
+            inline const token_t& current_token() const
             {
-               return v0 ^ v1;
+                return current_token_;
             }
-
-            template <typename T>
-            inline T xnor_impl(const T v0, const T v1, real_type_tag)
+            
+            enum token_advance_mode
             {
-               const bool v0_true = is_true_impl(v0);
-               const bool v1_true = is_true_impl(v1);
-               if ((v0_true &&  v1_true) || (!v0_true && !v1_true))
-                  return T(1);
-               else
-                  return T(0);
-            }
-
-            template <typename T>
-            inline T xnor_impl(const T v0, const T v1, int_type_tag)
+                e_hold    = 0,
+                e_advance = 1
+            };
+            
+            inline void advance_token(const token_advance_mode mode)
+            {
+                if (e_advance == mode)
+                {
+                    next_token();
+                }
+            }
+            
+            inline bool token_is(const token_t::token_type& ttype, const token_advance_mode mode = e_advance)
+            {
+                if (current_token().type != ttype)
+                {
+                    return false;
+                }
+                
+                advance_token(mode);
+                
+                return true;
+            }
+            
+            inline bool token_is(const token_t::token_type& ttype,
+                                 const std::string& value,
+                                 const token_advance_mode mode = e_advance)
+            {
+                if (
+                    (current_token().type != ttype) ||
+                    !exprtk::details::imatch(value,current_token().value)
+                    )
+                {
+                    return false;
+                }
+                
+                advance_token(mode);
+                
+                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);
+            }
+            
+            inline bool peek_token_is(const std::string& s)
+            {
+                return (exprtk::details::imatch(lexer_.peek_next_token().value,s));
+            }
+            
+        private:
+            
+            generator_t lexer_;
+            token_t     current_token_;
+            token_t     store_current_token_;
+        };
+    }
+    
+    template <typename T>
+    class vector_view
+    {
+    public:
+        
+        typedef T* data_ptr_t;
+        
+        vector_view(data_ptr_t data, const std::size_t& size)
+        : size_(size),
+        data_(data),
+        data_ref_(0)
+        {}
+        
+        vector_view(const vector_view<T>& vv)
+        : size_(vv.size_),
+        data_(vv.data_),
+        data_ref_(0)
+        {}
+        
+        inline void rebase(data_ptr_t data)
+        {
+            data_ = data;
+            
+            if (!data_ref_.empty())
+            {
+                for (std::size_t i = 0; i < data_ref_.size(); ++i)
+                {
+                    (*data_ref_[i]) = data;
+                }
+            }
+        }
+        
+        inline data_ptr_t data() const
+        {
+            return data_;
+        }
+        
+        inline std::size_t size() const
+        {
+            return size_;
+        }
+        
+        inline const T& operator[](const std::size_t index) const
+        {
+            return data_[index];
+        }
+        
+        inline T& operator[](const std::size_t index)
+        {
+            return data_[index];
+        }
+        
+        void set_ref(data_ptr_t* data_ref)
+        {
+            data_ref_.push_back(data_ref);
+        }
+        
+    private:
+        
+        std::size_t size_;
+        data_ptr_t  data_;
+        std::vector<data_ptr_t*> data_ref_;
+    };
+    
+    template <typename T>
+    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);
+    }
+    
+    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);
+    }
+    
+    template <typename T> class results_context;
+    
+    template <typename T>
+    struct type_store
+    {
+        enum store_type
+        {
+            e_unknown,
+            e_scalar,
+            e_vector,
+            e_string
+        };
+        
+        type_store()
+        : size(0),
+        data(0),
+        type(e_unknown)
+        {}
+        
+        std::size_t size;
+        void*       data;
+        store_type  type;
+        
+        class parameter_list
+        {
+        public:
+            
+            parameter_list(std::vector<type_store>& pl)
+            : parameter_list_(pl)
+            {}
+            
+            inline bool empty() const
             {
-               const bool v0_true = is_true_impl(v0);
-               const bool v1_true = is_true_impl(v1);
-               if ((v0_true &&  v1_true) || (!v0_true && !v1_true))
-                  return T(1);
-               else
-                  return T(0);
+                return parameter_list_.empty();
             }
-
-            template <typename T>
-            inline T erf_impl(T v, real_type_tag)
-            {
-               #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
-               // Credits: Abramowitz & Stegun Equations 7.1.25-28
-               const T t = T(1) / (T(1) + T(0.5) * abs_impl(v,real_type_tag()));
-               static const T c[] = {
-                                      T( 1.26551223), T(1.00002368),
-                                      T( 0.37409196), T(0.09678418),
-                                      T(-0.18628806), T(0.27886807),
-                                      T(-1.13520398), T(1.48851587),
-                                      T(-0.82215223), T(0.17087277)
-                                    };
-               T result = T(1) - t * std::exp((-v * v) -
-                                      c[0] + t * (c[1] + t *
-                                     (c[2] + t * (c[3] + t *
-                                     (c[4] + t * (c[5] + t *
-                                     (c[6] + t * (c[7] + t *
-                                     (c[8] + t * (c[9]))))))))));
-               return (v >= T(0)) ? result : -result;
-               #else
-               return ::erf(v);
-               #endif
+            
+            inline std::size_t size() const
+            {
+                return parameter_list_.size();
             }
-
-            template <typename T>
-            inline T erf_impl(T v, int_type_tag)
+            
+            inline type_store& operator[](const std::size_t& index)
             {
-               return erf_impl(static_cast<double>(v),real_type_tag());
+                return parameter_list_[index];
             }
-
-            template <typename T>
-            inline T erfc_impl(T v, real_type_tag)
+            
+            inline const type_store& operator[](const std::size_t& index) const
             {
-               #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
-               return T(1) - erf_impl(v,real_type_tag());
-               #else
-               return ::erfc(v);
-               #endif
+                return parameter_list_[index];
             }
-
-            template <typename T>
-            inline T erfc_impl(T v, int_type_tag)
+            
+            inline type_store& front()
             {
-               return erfc_impl(static_cast<double>(v),real_type_tag());
+                return parameter_list_[0];
             }
-
-            template <typename T>
-            inline T ncdf_impl(T v, real_type_tag)
+            
+            inline const type_store& front() const
             {
-               T cnd = T(0.5) * (T(1) + erf_impl(
-                                           abs_impl(v,real_type_tag()) /
-                                           T(numeric::constant::sqrt2),real_type_tag()));
-               return  (v < T(0)) ? (T(1) - cnd) : cnd;
+                return parameter_list_[0];
             }
-
-            template <typename T>
-            inline T ncdf_impl(T v, int_type_tag)
+            
+            inline type_store& back()
             {
-               return ncdf_impl(static_cast<double>(v),real_type_tag());
+                return parameter_list_.back();
             }
-
-            template <typename T>
-            inline T sinc_impl(T v, real_type_tag)
+            
+            inline const type_store& back() const
             {
-               if (std::abs(v) >= std::numeric_limits<T>::epsilon())
-                   return(std::sin(v) / v);
-               else
-                  return T(1);
+                return parameter_list_.back();
             }
-
-            template <typename T>
-            inline T sinc_impl(T v, int_type_tag)
+            
+        private:
+            
+            std::vector<type_store>& parameter_list_;
+            
+            friend class results_context<T>;
+        };
+        
+        template <typename ViewType>
+        struct type_view
+        {
+            typedef type_store<T> type_store_t;
+            typedef ViewType      value_t;
+            
+            type_view(type_store_t& ts)
+            : ts_(ts),
+            data_(reinterpret_cast<value_t*>(ts_.data))
+            {}
+            
+            inline std::size_t size() const
             {
-               return sinc_impl(static_cast<double>(v),real_type_tag());
+                return ts_.size;
             }
-
-            template <typename T> inline T  acos_impl(const T v, real_type_tag) { return std::acos (v); }
-            template <typename T> inline T acosh_impl(const T v, real_type_tag) { return std::log(v + std::sqrt((v * v) - T(1))); }
-            template <typename T> inline T  asin_impl(const T v, real_type_tag) { return std::asin (v); }
-            template <typename T> inline T asinh_impl(const T v, real_type_tag) { return std::log(v + std::sqrt((v * v) + T(1))); }
-            template <typename T> inline T  atan_impl(const T v, real_type_tag) { return std::atan (v); }
-            template <typename T> inline T atanh_impl(const T v, real_type_tag) { return (std::log(T(1) + v) - log(T(1) - v)) / T(2); }
-            template <typename T> inline T  ceil_impl(const T v, real_type_tag) { return std::ceil (v); }
-            template <typename T> inline T   cos_impl(const T v, real_type_tag) { return std::cos  (v); }
-            template <typename T> inline T  cosh_impl(const T v, real_type_tag) { return std::cosh (v); }
-            template <typename T> inline T   exp_impl(const T v, real_type_tag) { return std::exp  (v); }
-            template <typename T> inline T floor_impl(const T v, real_type_tag) { return std::floor(v); }
-            template <typename T> inline T   log_impl(const T v, real_type_tag) { return std::log  (v); }
-            template <typename T> inline T log10_impl(const T v, real_type_tag) { return std::log10(v); }
-            template <typename T> inline T  log2_impl(const T v, real_type_tag) { return std::log(v)/T(numeric::constant::log2); }
-            template <typename T> inline T   neg_impl(const T v, real_type_tag) { return -v;            }
-            template <typename T> inline T   pos_impl(const T v, real_type_tag) { return +v;            }
-            template <typename T> inline T   sin_impl(const T v, real_type_tag) { return std::sin  (v); }
-            template <typename T> inline T  sinh_impl(const T v, real_type_tag) { return std::sinh (v); }
-            template <typename T> inline T  sqrt_impl(const T v, real_type_tag) { return std::sqrt (v); }
-            template <typename T> inline T   tan_impl(const T v, real_type_tag) { return std::tan  (v); }
-            template <typename T> inline T  tanh_impl(const T v, real_type_tag) { return std::tanh (v); }
-            template <typename T> inline T   cot_impl(const T v, real_type_tag) { return T(1) / std::tan(v); }
-            template <typename T> inline T   sec_impl(const T v, real_type_tag) { return T(1) / std::cos(v); }
-            template <typename T> inline T   csc_impl(const T v, real_type_tag) { return T(1) / std::sin(v); }
-            template <typename T> inline T   r2d_impl(const T v, real_type_tag) { return (v * T(numeric::constant::_180_pi)); }
-            template <typename T> inline T   d2r_impl(const T v, real_type_tag) { return (v * T(numeric::constant::pi_180));  }
-            template <typename T> inline T   d2g_impl(const T v, real_type_tag) { return (v * T(20.0/9.0)); }
-            template <typename T> inline T   g2d_impl(const T v, real_type_tag) { return (v * T(9.0/20.0)); }
-            template <typename T> inline T  notl_impl(const T v, real_type_tag) { return (std::not_equal_to<T>()(T(0),v) ? T(0) : T(1)); }
-            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   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); }
-            template <typename T> inline T   log_impl(const T v, int_type_tag) { return std::log  (v); }
-            template <typename T> inline T log10_impl(const T v, int_type_tag) { return std::log10(v); }
-            template <typename T> inline T  log2_impl(const T v, int_type_tag) { return std::log(v)/T(numeric::constant::log2); }
-            template <typename T> inline T   neg_impl(const T v, int_type_tag) { return -v;            }
-            template <typename T> inline T   pos_impl(const T v, int_type_tag) { return +v;            }
-            template <typename T> inline T  ceil_impl(const T v, int_type_tag) { return v;             }
-            template <typename T> inline T floor_impl(const T v, int_type_tag) { return v;             }
-            template <typename T> inline T round_impl(const T v, int_type_tag) { return v;             }
-            template <typename T> inline T  notl_impl(const T v, int_type_tag) { return !v;            }
-            template <typename T> inline T  sqrt_impl(const T v, int_type_tag) { return std::sqrt (v); }
-            template <typename T> inline T  frac_impl(const T  , int_type_tag) { return T(0);          }
-            template <typename T> inline T trunc_impl(const T v, int_type_tag) { return v;             }
-            template <typename T> inline T  acos_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
-            template <typename T> inline T acosh_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
-            template <typename T> inline T  asin_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
-            template <typename T> inline T asinh_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
-            template <typename T> inline T  atan_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
-            template <typename T> inline T atanh_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
-            template <typename T> inline T   cos_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
-            template <typename T> inline T  cosh_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
-            template <typename T> inline T   sin_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
-            template <typename T> inline T  sinh_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
-            template <typename T> inline T   tan_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
-            template <typename T> inline T  tanh_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
-            template <typename T> inline T   cot_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
-            template <typename T> inline T   sec_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
-            template <typename T> inline T   csc_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
-
-            template <typename T>
-            inline bool is_integer_impl(const T& v, real_type_tag)
+            
+            inline value_t& operator[](const std::size_t& i)
             {
-               return std::equal_to<T>()(T(0),std::fmod(v,T(1)));
+                return data_[i];
             }
-
-            template <typename T>
-            inline bool is_integer_impl(const T&, int_type_tag)
+            
+            inline const value_t& operator[](const std::size_t& i) const
             {
-               return true;
+                return data_[i];
             }
-         }
-
-         template <typename Type>
-         struct numeric_info { enum { length = 0, size = 32, bound_length = 0, min_exp = 0, max_exp = 0 }; };
-
-         template<> struct numeric_info<int>         { enum { length = 10, size = 16, bound_length =  9}; };
-         template<> struct numeric_info<float>       { enum { min_exp =  -38, max_exp =  +38}; };
-         template<> struct numeric_info<double>      { enum { min_exp = -308, max_exp = +308}; };
-         template<> struct numeric_info<long double> { enum { min_exp = -308, max_exp = +308}; };
-
-         template <typename T>
-         inline int to_int32(const T v)
-         {
-            typename details::number_type<T>::type num_type;
-            return to_int32_impl(v,num_type);
-         }
-
-         template <typename T>
-         inline long long int to_int64(const T v)
-         {
-            typename details::number_type<T>::type num_type;
-            return to_int64_impl(v,num_type);
-         }
-
-         template <typename T>
-         inline bool is_nan(const T v)
-         {
-            typename details::number_type<T>::type num_type;
-            return is_nan_impl(v,num_type);
-         }
-
-         template <typename T>
-         inline T min(const T v0, const T v1)
-         {
-            typename details::number_type<T>::type num_type;
-            return min_impl(v0,v1,num_type);
-         }
-
-         template <typename T>
-         inline T max(const T v0, const T v1)
-         {
-            typename details::number_type<T>::type num_type;
-            return max_impl(v0,v1,num_type);
-         }
-
-         template <typename T>
-         inline T equal(const T v0, const T v1)
-         {
-            typename details::number_type<T>::type num_type;
-            return equal_impl(v0,v1,num_type);
-         }
-
-         template <typename T>
-         inline T nequal(const T v0, const T v1)
-         {
-            typename details::number_type<T>::type num_type;
-            return nequal_impl(v0,v1,num_type);
-         }
-
-         template <typename T>
-         inline T modulus(const T v0, const T v1)
-         {
-            typename details::number_type<T>::type num_type;
-            return modulus_impl(v0,v1,num_type);
-         }
-
-         template <typename T>
-         inline T pow(const T v0, const T v1)
-         {
-            typename details::number_type<T>::type num_type;
-            return pow_impl(v0,v1,num_type);
-         }
-
-         template <typename T>
-         inline T logn(const T v0, const T v1)
-         {
-            typename details::number_type<T>::type num_type;
-            return logn_impl(v0,v1,num_type);
-         }
-
-         template <typename T>
-         inline T root(const T v0, const T v1)
-         {
-            typename details::number_type<T>::type num_type;
-            return root_impl(v0,v1,num_type);
-         }
-
-         template <typename T>
-         inline T roundn(const T v0, const T v1)
-         {
-            typename details::number_type<T>::type num_type;
-            return roundn_impl(v0,v1,num_type);
-         }
-
-         template <typename T>
-         inline T hypot(const T v0, const T v1)
-         {
-            typename details::number_type<T>::type num_type;
-            return hypot_impl(v0,v1,num_type);
-         }
-
-         template <typename T>
-         inline T atan2(const T v0, const T v1)
-         {
-            typename details::number_type<T>::type num_type;
-            return atan2_impl(v0,v1,num_type);
-         }
-
-         template <typename T>
-         inline T shr(const T v0, const T v1)
-         {
-            typename details::number_type<T>::type num_type;
-            return shr_impl(v0,v1,num_type);
-         }
-
-         template <typename T>
-         inline T shl(const T v0, const T v1)
-         {
-            typename details::number_type<T>::type num_type;
-            return shl_impl(v0,v1,num_type);
-         }
-
-         template <typename T>
-         inline T and_opr(const T v0, const T v1)
-         {
-            typename details::number_type<T>::type num_type;
-            return and_impl(v0,v1,num_type);
-         }
-
-         template <typename T>
-         inline T nand_opr(const T v0, const T v1)
-         {
-            typename details::number_type<T>::type num_type;
-            return nand_impl(v0,v1,num_type);
-         }
-
-         template <typename T>
-         inline T or_opr(const T v0, const T v1)
-         {
-            typename details::number_type<T>::type num_type;
-            return or_impl(v0,v1,num_type);
-         }
-
-         template <typename T>
-         inline T nor_opr(const T v0, const T v1)
-         {
-            typename details::number_type<T>::type num_type;
-            return nor_impl(v0,v1,num_type);
-         }
-
-         template <typename T>
-         inline T xor_opr(const T v0, const T v1)
-         {
-            typename details::number_type<T>::type num_type;
-            return xor_impl(v0,v1,num_type);
-         }
-
-         template <typename T>
-         inline T xnor_opr(const T v0, const T v1)
-         {
-            typename details::number_type<T>::type num_type;
-            return xnor_impl(v0,v1,num_type);
-         }
-
-         template <typename T>
-         inline bool is_integer(const T v)
-         {
-            typename details::number_type<T>::type num_type;
-            return is_integer_impl(v,num_type);
-         }
-
-         template <typename T, unsigned int N>
-         struct fast_exp
-         {
-            static inline T result(T v)
+            
+            inline const value_t* begin() const { return data_; }
+            inline       value_t* begin()       { return data_; }
+            
+            inline const value_t* end() const
             {
-               unsigned int k = N;
-               T l = T(1);
-
-               while (k)
-               {
-                  if (k & 1)
-                  {
-                     l *= v;
-                     --k;
-                  }
-
-                  v *= v;
-                  k >>= 1;
-               }
-
-               return l;
+                return static_cast<value_t*>(data_ + ts_.size);
             }
-         };
-
-         template <typename T> struct fast_exp<T,10> { static inline T result(T v) { T v_5 = fast_exp<T,5>::result(v); return v_5 * v_5; } };
-         template <typename T> struct fast_exp<T, 9> { static inline T result(T v) { return fast_exp<T,8>::result(v) * v; } };
-         template <typename T> struct fast_exp<T, 8> { static inline T result(T v) { T v_4 = fast_exp<T,4>::result(v); return v_4 * v_4; } };
-         template <typename T> struct fast_exp<T, 7> { static inline T result(T v) { return fast_exp<T,6>::result(v) * v; } };
-         template <typename T> struct fast_exp<T, 6> { static inline T result(T v) { T v_3 = fast_exp<T,3>::result(v); return v_3 * v_3; } };
-         template <typename T> struct fast_exp<T, 5> { static inline T result(T v) { return fast_exp<T,4>::result(v) * v; } };
-         template <typename T> struct fast_exp<T, 4> { static inline T result(T v) { T v_2 = v * v; return v_2 * v_2; } };
-         template <typename T> struct fast_exp<T, 3> { static inline T result(T v) { return v * v * v; } };
-         template <typename T> struct fast_exp<T, 2> { static inline T result(T v) { return v * v;     } };
-         template <typename T> struct fast_exp<T, 1> { static inline T result(T v) { return v;         } };
-         template <typename T> struct fast_exp<T, 0> { static inline T result(T  ) { return T(1);      } };
-
-         #define exprtk_define_unary_function(FunctionName)   \
-         template <typename T>                                \
-         inline T FunctionName (const T v)                    \
-         {                                                    \
-            typename details::number_type<T>::type num_type;  \
-            return  FunctionName##_impl(v,num_type);          \
-         }                                                    \
-
-         exprtk_define_unary_function(abs  )
-         exprtk_define_unary_function(acos )
-         exprtk_define_unary_function(acosh)
-         exprtk_define_unary_function(asin )
-         exprtk_define_unary_function(asinh)
-         exprtk_define_unary_function(atan )
-         exprtk_define_unary_function(atanh)
-         exprtk_define_unary_function(ceil )
-         exprtk_define_unary_function(cos  )
-         exprtk_define_unary_function(cosh )
-         exprtk_define_unary_function(exp  )
-         exprtk_define_unary_function(expm1)
-         exprtk_define_unary_function(floor)
-         exprtk_define_unary_function(log  )
-         exprtk_define_unary_function(log10)
-         exprtk_define_unary_function(log2 )
-         exprtk_define_unary_function(log1p)
-         exprtk_define_unary_function(neg  )
-         exprtk_define_unary_function(pos  )
-         exprtk_define_unary_function(round)
-         exprtk_define_unary_function(sin  )
-         exprtk_define_unary_function(sinc )
-         exprtk_define_unary_function(sinh )
-         exprtk_define_unary_function(sqrt )
-         exprtk_define_unary_function(tan  )
-         exprtk_define_unary_function(tanh )
-         exprtk_define_unary_function(cot  )
-         exprtk_define_unary_function(sec  )
-         exprtk_define_unary_function(csc  )
-         exprtk_define_unary_function(r2d  )
-         exprtk_define_unary_function(d2r  )
-         exprtk_define_unary_function(d2g  )
-         exprtk_define_unary_function(g2d  )
-         exprtk_define_unary_function(notl )
-         exprtk_define_unary_function(sgn  )
-         exprtk_define_unary_function(erf  )
-         exprtk_define_unary_function(erfc )
-         exprtk_define_unary_function(ncdf )
-         exprtk_define_unary_function(frac )
-         exprtk_define_unary_function(trunc)
-         #undef exprtk_define_unary_function
-      }
-
-      template <typename T>
-      inline T compute_pow10(T d, const int exponent)
-      {
-         static const double fract10[] =
-         {
-            0.0,
-            1.0E+001, 1.0E+002, 1.0E+003, 1.0E+004, 1.0E+005, 1.0E+006, 1.0E+007, 1.0E+008, 1.0E+009, 1.0E+010,
-            1.0E+011, 1.0E+012, 1.0E+013, 1.0E+014, 1.0E+015, 1.0E+016, 1.0E+017, 1.0E+018, 1.0E+019, 1.0E+020,
-            1.0E+021, 1.0E+022, 1.0E+023, 1.0E+024, 1.0E+025, 1.0E+026, 1.0E+027, 1.0E+028, 1.0E+029, 1.0E+030,
-            1.0E+031, 1.0E+032, 1.0E+033, 1.0E+034, 1.0E+035, 1.0E+036, 1.0E+037, 1.0E+038, 1.0E+039, 1.0E+040,
-            1.0E+041, 1.0E+042, 1.0E+043, 1.0E+044, 1.0E+045, 1.0E+046, 1.0E+047, 1.0E+048, 1.0E+049, 1.0E+050,
-            1.0E+051, 1.0E+052, 1.0E+053, 1.0E+054, 1.0E+055, 1.0E+056, 1.0E+057, 1.0E+058, 1.0E+059, 1.0E+060,
-            1.0E+061, 1.0E+062, 1.0E+063, 1.0E+064, 1.0E+065, 1.0E+066, 1.0E+067, 1.0E+068, 1.0E+069, 1.0E+070,
-            1.0E+071, 1.0E+072, 1.0E+073, 1.0E+074, 1.0E+075, 1.0E+076, 1.0E+077, 1.0E+078, 1.0E+079, 1.0E+080,
-            1.0E+081, 1.0E+082, 1.0E+083, 1.0E+084, 1.0E+085, 1.0E+086, 1.0E+087, 1.0E+088, 1.0E+089, 1.0E+090,
-            1.0E+091, 1.0E+092, 1.0E+093, 1.0E+094, 1.0E+095, 1.0E+096, 1.0E+097, 1.0E+098, 1.0E+099, 1.0E+100,
-            1.0E+101, 1.0E+102, 1.0E+103, 1.0E+104, 1.0E+105, 1.0E+106, 1.0E+107, 1.0E+108, 1.0E+109, 1.0E+110,
-            1.0E+111, 1.0E+112, 1.0E+113, 1.0E+114, 1.0E+115, 1.0E+116, 1.0E+117, 1.0E+118, 1.0E+119, 1.0E+120,
-            1.0E+121, 1.0E+122, 1.0E+123, 1.0E+124, 1.0E+125, 1.0E+126, 1.0E+127, 1.0E+128, 1.0E+129, 1.0E+130,
-            1.0E+131, 1.0E+132, 1.0E+133, 1.0E+134, 1.0E+135, 1.0E+136, 1.0E+137, 1.0E+138, 1.0E+139, 1.0E+140,
-            1.0E+141, 1.0E+142, 1.0E+143, 1.0E+144, 1.0E+145, 1.0E+146, 1.0E+147, 1.0E+148, 1.0E+149, 1.0E+150,
-            1.0E+151, 1.0E+152, 1.0E+153, 1.0E+154, 1.0E+155, 1.0E+156, 1.0E+157, 1.0E+158, 1.0E+159, 1.0E+160,
-            1.0E+161, 1.0E+162, 1.0E+163, 1.0E+164, 1.0E+165, 1.0E+166, 1.0E+167, 1.0E+168, 1.0E+169, 1.0E+170,
-            1.0E+171, 1.0E+172, 1.0E+173, 1.0E+174, 1.0E+175, 1.0E+176, 1.0E+177, 1.0E+178, 1.0E+179, 1.0E+180,
-            1.0E+181, 1.0E+182, 1.0E+183, 1.0E+184, 1.0E+185, 1.0E+186, 1.0E+187, 1.0E+188, 1.0E+189, 1.0E+190,
-            1.0E+191, 1.0E+192, 1.0E+193, 1.0E+194, 1.0E+195, 1.0E+196, 1.0E+197, 1.0E+198, 1.0E+199, 1.0E+200,
-            1.0E+201, 1.0E+202, 1.0E+203, 1.0E+204, 1.0E+205, 1.0E+206, 1.0E+207, 1.0E+208, 1.0E+209, 1.0E+210,
-            1.0E+211, 1.0E+212, 1.0E+213, 1.0E+214, 1.0E+215, 1.0E+216, 1.0E+217, 1.0E+218, 1.0E+219, 1.0E+220,
-            1.0E+221, 1.0E+222, 1.0E+223, 1.0E+224, 1.0E+225, 1.0E+226, 1.0E+227, 1.0E+228, 1.0E+229, 1.0E+230,
-            1.0E+231, 1.0E+232, 1.0E+233, 1.0E+234, 1.0E+235, 1.0E+236, 1.0E+237, 1.0E+238, 1.0E+239, 1.0E+240,
-            1.0E+241, 1.0E+242, 1.0E+243, 1.0E+244, 1.0E+245, 1.0E+246, 1.0E+247, 1.0E+248, 1.0E+249, 1.0E+250,
-            1.0E+251, 1.0E+252, 1.0E+253, 1.0E+254, 1.0E+255, 1.0E+256, 1.0E+257, 1.0E+258, 1.0E+259, 1.0E+260,
-            1.0E+261, 1.0E+262, 1.0E+263, 1.0E+264, 1.0E+265, 1.0E+266, 1.0E+267, 1.0E+268, 1.0E+269, 1.0E+270,
-            1.0E+271, 1.0E+272, 1.0E+273, 1.0E+274, 1.0E+275, 1.0E+276, 1.0E+277, 1.0E+278, 1.0E+279, 1.0E+280,
-            1.0E+281, 1.0E+282, 1.0E+283, 1.0E+284, 1.0E+285, 1.0E+286, 1.0E+287, 1.0E+288, 1.0E+289, 1.0E+290,
-            1.0E+291, 1.0E+292, 1.0E+293, 1.0E+294, 1.0E+295, 1.0E+296, 1.0E+297, 1.0E+298, 1.0E+299, 1.0E+300,
-            1.0E+301, 1.0E+302, 1.0E+303, 1.0E+304, 1.0E+305, 1.0E+306, 1.0E+307, 1.0E+308
-         };
-
-         static const int fract10_size = static_cast<int>(sizeof(fract10) / sizeof(double));
-
-         const int e = std::abs(exponent);
-
-         if (exponent >= std::numeric_limits<T>::min_exponent10)
-         {
-            if (e < fract10_size)
+            
+            inline value_t* end()
             {
-               if (exponent > 0)
-                  return T(d * fract10[e]);
-               else
-                  return T(d / fract10[e]);
+                return static_cast<value_t*>(data_ + ts_.size);
             }
+            
+            type_store_t& ts_;
+            value_t* data_;
+        };
+        
+        typedef type_view<T>    vector_view;
+        typedef type_view<char> string_view;
+        
+        struct scalar_view
+        {
+            typedef type_store<T> type_store_t;
+            typedef T value_t;
+            
+            scalar_view(type_store_t& ts)
+            : v_(*reinterpret_cast<value_t*>(ts.data))
+            {}
+            
+            scalar_view(const type_store_t& ts)
+            : v_(*reinterpret_cast<value_t*>(const_cast<type_store_t&>(ts).data))
+            {}
+            
+            inline value_t& operator()()
+            {
+                return v_;
+            }
+            
+            inline const value_t& operator()() const
+            {
+                return v_;
+            }
+            
+            template <typename IntType>
+            inline bool to_int(IntType& i) const
+            {
+                if (!exprtk::details::numeric::is_integer(v_))
+                    return false;
+                
+                i = static_cast<IntType>(v_);
+                
+                return true;
+            }
+            
+            template <typename UIntType>
+            inline bool to_uint(UIntType& u) const
+            {
+                if (v_ < T(0))
+                    return false;
+                else if (!exprtk::details::numeric::is_integer(v_))
+                    return false;
+                
+                u = static_cast<UIntType>(v_);
+                
+                return true;
+            }
+            
+            T& v_;
+        };
+    };
+    
+    template <typename StringView>
+    inline std::string to_str(const StringView& view)
+    {
+        return std::string(view.begin(),view.size());
+    }
+    
+    namespace details
+    {
+        template <typename T> class return_node;
+        template <typename T> class return_envelope_node;
+    }
+    
+    template <typename T>
+    class results_context
+    {
+    public:
+        
+        typedef type_store<T> type_store_t;
+        
+        results_context()
+        : results_available_(false)
+        {}
+        
+        inline std::size_t count() const
+        {
+            if (results_available_)
+                return parameter_list_.size();
             else
-               return T(d * std::pow(10.0, 10.0 * exponent));
-         }
-         else
-         {
-                     d /= T(fract10[           -std::numeric_limits<T>::min_exponent10]);
-            return T(d /    fract10[-exponent + std::numeric_limits<T>::min_exponent10]);
-         }
-      }
-
-      template <typename Iterator, typename T>
-      inline bool string_to_type_converter_impl_ref(Iterator& itr, const Iterator end, T& result)
-      {
-         if (itr == end)
-            return false;
-
-         bool negative = ('-' == (*itr));
-
-         if (negative || ('+' == (*itr)))
-         {
-            if (end == ++itr)
-               return false;
-         }
-
-         while ((end != itr) && ('0' == (*itr))) ++itr;
-
-         bool return_result = true;
-         unsigned int digit = 0;
-         const std::size_t length = std::distance(itr,end);
-
-         if (length <= 4)
-         {
-            switch (length)
-            {
-               #ifdef exprtk_use_lut
-
-               #define exprtk_process_digit \
-               if ((digit = details::digit_table[(int)*itr++]) < 10) result = result * 10 + (digit); else { return_result = false; break; }
-
-               #else
-               #define exprtk_process_digit \
-               if ((digit = (*itr++ - '0')) < 10) result = result * 10 + (digit); else { return_result = false; break; }
-
-               #endif
-
-               case  4 : exprtk_process_digit
-               case  3 : exprtk_process_digit
-               case  2 : exprtk_process_digit
-               case  1 : if ((digit = (*itr - '0'))>= 10) { digit = 0; return_result = false; }
-
-               #undef exprtk_process_digit
+                return 0;
+        }
+        
+        inline type_store_t& operator[](const std::size_t& index)
+        {
+            return parameter_list_[index];
+        }
+        
+        inline const type_store_t& operator[](const std::size_t& index) const
+        {
+            return parameter_list_[index];
+        }
+        
+    private:
+        
+        inline void clear()
+        {
+            results_available_ = false;
+        }
+        
+        typedef std::vector<type_store_t> ts_list_t;
+        typedef typename type_store_t::parameter_list parameter_list_t;
+        
+        inline void assign(const parameter_list_t& pl)
+        {
+            parameter_list_    = pl.parameter_list_;
+            results_available_ = true;
+        }
+        
+        bool results_available_;
+        ts_list_t parameter_list_;
+        
+        friend class details::return_node<T>;
+        friend class details::return_envelope_node<T>;
+    };
+    
+    namespace details
+    {
+        enum operator_type
+        {
+            e_default , e_null    , e_add     , e_sub     ,
+            e_mul     , e_div     , e_mod     , e_pow     ,
+            e_atan2   , e_min     , e_max     , e_avg     ,
+            e_sum     , e_prod    , e_lt      , e_lte     ,
+            e_eq      , e_equal   , e_ne      , e_nequal  ,
+            e_gte     , e_gt      , e_and     , e_nand    ,
+            e_or      , e_nor     , e_xor     , e_xnor    ,
+            e_mand    , e_mor     , e_scand   , e_scor    ,
+            e_shr     , e_shl     , 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_logn    ,
+            e_neg     , e_pos     , e_round   , e_roundn  ,
+            e_root    , e_sqrt    , e_sin     , e_sinc    ,
+            e_sinh    , e_sec     , e_csc     , e_tan     ,
+            e_tanh    , e_cot     , e_clamp   , e_iclamp  ,
+            e_inrange , e_sgn     , e_r2d     , e_d2r     ,
+            e_d2g     , e_g2d     , e_hypot   , e_notl    ,
+            e_erf     , e_erfc    , e_ncdf    , e_frac    ,
+            e_trunc   , e_assign  , e_addass  , e_subass  ,
+            e_mulass  , e_divass  , e_modass  , e_in      ,
+            e_like    , e_ilike   , e_multi   , e_swap    ,
+            
+            // Do not add new functions/operators after this point.
+            e_sf00 = 1000, e_sf01 = 1001, e_sf02 = 1002, e_sf03 = 1003,
+            e_sf04 = 1004, e_sf05 = 1005, e_sf06 = 1006, e_sf07 = 1007,
+            e_sf08 = 1008, e_sf09 = 1009, e_sf10 = 1010, e_sf11 = 1011,
+            e_sf12 = 1012, e_sf13 = 1013, e_sf14 = 1014, e_sf15 = 1015,
+            e_sf16 = 1016, e_sf17 = 1017, e_sf18 = 1018, e_sf19 = 1019,
+            e_sf20 = 1020, e_sf21 = 1021, e_sf22 = 1022, e_sf23 = 1023,
+            e_sf24 = 1024, e_sf25 = 1025, e_sf26 = 1026, e_sf27 = 1027,
+            e_sf28 = 1028, e_sf29 = 1029, e_sf30 = 1030, e_sf31 = 1031,
+            e_sf32 = 1032, e_sf33 = 1033, e_sf34 = 1034, e_sf35 = 1035,
+            e_sf36 = 1036, e_sf37 = 1037, e_sf38 = 1038, e_sf39 = 1039,
+            e_sf40 = 1040, e_sf41 = 1041, e_sf42 = 1042, e_sf43 = 1043,
+            e_sf44 = 1044, e_sf45 = 1045, e_sf46 = 1046, e_sf47 = 1047,
+            e_sf48 = 1048, e_sf49 = 1049, e_sf50 = 1050, e_sf51 = 1051,
+            e_sf52 = 1052, e_sf53 = 1053, e_sf54 = 1054, e_sf55 = 1055,
+            e_sf56 = 1056, e_sf57 = 1057, e_sf58 = 1058, e_sf59 = 1059,
+            e_sf60 = 1060, e_sf61 = 1061, e_sf62 = 1062, e_sf63 = 1063,
+            e_sf64 = 1064, e_sf65 = 1065, e_sf66 = 1066, e_sf67 = 1067,
+            e_sf68 = 1068, e_sf69 = 1069, e_sf70 = 1070, e_sf71 = 1071,
+            e_sf72 = 1072, e_sf73 = 1073, e_sf74 = 1074, e_sf75 = 1075,
+            e_sf76 = 1076, e_sf77 = 1077, e_sf78 = 1078, e_sf79 = 1079,
+            e_sf80 = 1080, e_sf81 = 1081, e_sf82 = 1082, e_sf83 = 1083,
+            e_sf84 = 1084, e_sf85 = 1085, e_sf86 = 1086, e_sf87 = 1087,
+            e_sf88 = 1088, e_sf89 = 1089, e_sf90 = 1090, e_sf91 = 1091,
+            e_sf92 = 1092, e_sf93 = 1093, e_sf94 = 1094, e_sf95 = 1095,
+            e_sf96 = 1096, e_sf97 = 1097, e_sf98 = 1098, e_sf99 = 1099,
+            e_sffinal  = 1100,
+            e_sf4ext00 = 2000, e_sf4ext01 = 2001, e_sf4ext02 = 2002, e_sf4ext03 = 2003,
+            e_sf4ext04 = 2004, e_sf4ext05 = 2005, e_sf4ext06 = 2006, e_sf4ext07 = 2007,
+            e_sf4ext08 = 2008, e_sf4ext09 = 2009, e_sf4ext10 = 2010, e_sf4ext11 = 2011,
+            e_sf4ext12 = 2012, e_sf4ext13 = 2013, e_sf4ext14 = 2014, e_sf4ext15 = 2015,
+            e_sf4ext16 = 2016, e_sf4ext17 = 2017, e_sf4ext18 = 2018, e_sf4ext19 = 2019,
+            e_sf4ext20 = 2020, e_sf4ext21 = 2021, e_sf4ext22 = 2022, e_sf4ext23 = 2023,
+            e_sf4ext24 = 2024, e_sf4ext25 = 2025, e_sf4ext26 = 2026, e_sf4ext27 = 2027,
+            e_sf4ext28 = 2028, e_sf4ext29 = 2029, e_sf4ext30 = 2030, e_sf4ext31 = 2031,
+            e_sf4ext32 = 2032, e_sf4ext33 = 2033, e_sf4ext34 = 2034, e_sf4ext35 = 2035,
+            e_sf4ext36 = 2036, e_sf4ext37 = 2037, e_sf4ext38 = 2038, e_sf4ext39 = 2039,
+            e_sf4ext40 = 2040, e_sf4ext41 = 2041, e_sf4ext42 = 2042, e_sf4ext43 = 2043,
+            e_sf4ext44 = 2044, e_sf4ext45 = 2045, e_sf4ext46 = 2046, e_sf4ext47 = 2047,
+            e_sf4ext48 = 2048, e_sf4ext49 = 2049, e_sf4ext50 = 2050, e_sf4ext51 = 2051,
+            e_sf4ext52 = 2052, e_sf4ext53 = 2053, e_sf4ext54 = 2054, e_sf4ext55 = 2055,
+            e_sf4ext56 = 2056, e_sf4ext57 = 2057, e_sf4ext58 = 2058, e_sf4ext59 = 2059,
+            e_sf4ext60 = 2060
+        };
+        
+        inline std::string to_str(const operator_type opr)
+        {
+            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";
+            }
+        }
+        
+        struct base_operation_t
+        {
+            base_operation_t(const operator_type t, const unsigned int& np)
+            : type(t),
+            num_params(np)
+            {}
+            
+            operator_type type;
+            unsigned int num_params;
+        };
+        
+        namespace loop_unroll
+        {
+#ifndef exprtk_disable_superscalar_unroll
+            const unsigned int global_loop_batch_size = 16;
+#else
+            const unsigned int global_loop_batch_size = 4;
+#endif
+            
+            struct details
+            {
+                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))
+                {}
+                
+                int  batch_size;
+                int   remainder;
+                int upper_bound;
+            };
+        }
+        
+#ifdef exprtk_enable_debugging
+        inline void dump_ptr(const std::string& s, const void* ptr, const std::size_t size = 0)
+        {
+            if (size)
+                exprtk_debug(("%s - addr: %p\n",s.c_str(),ptr));
+            else
+                exprtk_debug(("%s - addr: %p size: %d\n",
+                              s.c_str(),
+                              ptr,
+                              static_cast<unsigned int>(size)));
+        }
+#else
+        inline void dump_ptr(const std::string&, const void*) {}
+        inline void dump_ptr(const std::string&, const void*, const std::size_t) {}
+#endif
+        
+        template <typename T>
+        class vec_data_store
+        {
+        public:
+            
+            typedef vec_data_store<T> type;
+            typedef T* data_t;
+            
+        private:
+            
+            struct control_block
+            {
+                control_block()
+                : ref_count(1),
+                size     (0),
+                data     (0),
+                destruct (true)
+                {}
+                
+                control_block(const std::size_t& dsize)
+                : ref_count(1),
+                size     (dsize),
+                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 ),
+                destruct (dstrct)
+                {}
+                
+                ~control_block()
+                {
+                    if (data && destruct && (0 == ref_count))
+                    {
+                        dump_ptr("~control_block() data",data);
+                        delete[] data;
+                        data = 0;
+                    }
+                }
+                
+                static inline control_block* create(const std::size_t& size, data_t data_ptr = data_t(0), bool dstrct = false)
+                {
+                    if (size)
+                    {
+                        if (0 == data_ptr)
+                            return new control_block(size);
+                        else
+                            return new control_block(size, data_ptr, dstrct);
+                    }
+                    else
+                        return new control_block;
+                }
+                
+                static inline void destroy(control_block*& cntrl_blck)
+                {
+                    if (cntrl_blck)
+                    {
+                        if (
+                            (0 !=   cntrl_blck->ref_count) &&
+                            (0 == --cntrl_blck->ref_count)
+                            )
+                        {
+                            delete cntrl_blck;
+                        }
+                        
+                        cntrl_blck = 0;
+                    }
+                }
+                
+                std::size_t ref_count;
+                std::size_t size;
+                data_t      data;
+                bool        destruct;
+                
+            private:
+                
+                control_block(const control_block&);
+                control_block& operator=(const control_block&);
+                
+                inline void create_data()
+                {
+                    destruct = true;
+                    data     = new T[size];
+                    std::fill_n(data,size,T(0));
+                    dump_ptr("control_block::create_data() - data",data,size);
+                }
+            };
+            
+        public:
+            
+            vec_data_store()
+            : control_block_(control_block::create(0))
+            {}
+            
+            vec_data_store(const std::size_t& size)
+            : control_block_(control_block::create(size,(data_t)(0),true))
+            {}
+            
+            vec_data_store(const std::size_t& size, data_t data, bool dstrct = false)
+            : control_block_(control_block::create(size, data, dstrct))
+            {}
+            
+            vec_data_store(const type& vds)
+            {
+                control_block_ = vds.control_block_;
+                control_block_->ref_count++;
             }
-         }
-         else
-            return_result = false;
-
-         if (length && return_result)
-         {
-            result = result * 10 + static_cast<T>(digit);
-            ++itr;
-         }
-
-         result = negative ? -result : result;
-         return return_result;
-      }
-
-      template <typename Iterator, typename T>
-      static inline bool parse_nan(Iterator& itr, const Iterator end, T& t)
-      {
-         typedef typename std::iterator_traits<Iterator>::value_type type;
-         static const std::size_t nan_length = 3;
-         if (std::distance(itr,end) != static_cast<int>(nan_length))
-            return false;
-         if (static_cast<type>('n') == (*itr))
-         {
-            if (
-                 (static_cast<type>('a') != *(itr + 1)) ||
-                 (static_cast<type>('n') != *(itr + 2))
-               )
+            
+            ~vec_data_store()
             {
-               return false;
+                control_block::destroy(control_block_);
             }
-         }
-         else if (
-                   (static_cast<type>('A') != *(itr + 1)) ||
-                   (static_cast<type>('N') != *(itr + 2))
-                 )
-         {
-            return false;
-         }
-         t = std::numeric_limits<T>::quiet_NaN();
-         return true;
-      }
-
-      template <typename Iterator, typename T>
-      static inline bool parse_inf(Iterator& itr, const Iterator end, T& t, bool negative)
-      {
-         static const char inf_uc[] = "INFINITY";
-         static const char inf_lc[] = "infinity";
-         static const std::size_t inf_length = 8;
-         const std::size_t length = std::distance(itr,end);
-         if ((3 != length) && (inf_length != length))
-            return false;
-         const char* inf_itr = ('i' == (*itr)) ? inf_lc : inf_uc;
-         while (end != itr)
-         {
-            if (*inf_itr == static_cast<char>(*itr))
+            
+            type& operator=(const type& vds)
             {
-               ++itr;
-               ++inf_itr;
-               continue;
+                if (this != &vds)
+                {
+                    std::size_t final_size = min_size(control_block_, vds.control_block_);
+                    
+                    vds.control_block_->size = final_size;
+                    control_block_->size = final_size;
+                    
+                    if (control_block_->destruct || (0 == control_block_->data))
+                    {
+                        control_block::destroy(control_block_);
+                        
+                        control_block_ = vds.control_block_;
+                        control_block_->ref_count++;
+                    }
+                }
+                
+                return *this;
             }
-            else
-               return false;
-         }
-         if (negative)
-            t = -std::numeric_limits<T>::infinity();
-         else
-            t =  std::numeric_limits<T>::infinity();
-         return true;
-      }
-
-      template <typename Iterator, typename T>
-      inline bool string_to_real(Iterator& itr_external, const Iterator end, T& t, numeric::details::real_type_tag)
-      {
-         if (end == itr_external) return false;
-
-         Iterator itr = itr_external;
-
-         T d = T(0);
-
-         bool negative = ('-' == (*itr));
-
-         if (negative || '+' == (*itr))
-         {
-            if (end == ++itr)
-               return false;
-         }
-
-         bool instate = false;
-
-         #define parse_digit_1(d) \
-         if ((digit = (*itr - '0')) < 10) { d = d * T(10) + digit; } else break; if (end == ++itr) break; \
-
-         #define parse_digit_2(d) \
-         if ((digit = (*itr - '0')) < 10) { d = d * T(10) + digit; } else break; ++itr; \
-
-         if ('.' != (*itr))
-         {
-            const Iterator curr = itr;
-            while ((end != itr) && ('0' == (*itr))) ++itr;
-            unsigned int digit;
-
-            while (end != itr)
+            
+            inline data_t data()
             {
-               // Note: For 'physical' superscalar architectures it
-               // is advised that the following loop be: 4xPD1 and 1xPD2
-               #ifdef exprtk_enable_superscalar
-               parse_digit_1(d)
-               parse_digit_1(d)
-               #endif
-               parse_digit_1(d)
-               parse_digit_1(d)
-               parse_digit_2(d)
+                return control_block_->data;
             }
-
-            if (curr != itr) instate = true;
-         }
-
-         int exponent = 0;
-
-         if (end != itr)
-         {
-            if ('.' == (*itr))
+            
+            inline data_t data() const
             {
-               const Iterator curr = ++itr;
-               unsigned int digit;
-               T tmp_d = T(0);
-
-               while (end != itr)
-               {
-                  #ifdef exprtk_enable_superscalar
-                  parse_digit_1(tmp_d)
-                  parse_digit_1(tmp_d)
-                  parse_digit_1(tmp_d)
-                  #endif
-                  parse_digit_1(tmp_d)
-                  parse_digit_1(tmp_d)
-                  parse_digit_2(tmp_d)
-               }
-
-               if (curr != itr)
-               {
-                  instate = true;
-                  d += compute_pow10(tmp_d,-std::distance(curr,itr));
-               }
-
-               #undef parse_digit_1
-               #undef parse_digit_2
+                return control_block_->data;
             }
-
-            if (end != itr)
+            
+            inline std::size_t size()
             {
-               typename std::iterator_traits<Iterator>::value_type c = (*itr);
-
-               if (('e' == c) || ('E' == c))
-               {
-                  int exp = 0;
-
-                  if (!details::string_to_type_converter_impl_ref(++itr,end,exp))
-                  {
-                     if (end == itr)
-                        return false;
-                     else
-                        c = (*itr);
-                  }
-
-                  exponent += exp;
-               }
-
-               if (end != itr)
-               {
-                  if (('f' == c) || ('F' == c) || ('l' == c) || ('L' == c))
-                     ++itr;
-                  else if ('#' == c)
-                  {
-                     if (end == ++itr)
-                        return false;
-                     else if (('I' <= (*itr)) && ((*itr) <= 'n'))
-                     {
-                        if (('i' == (*itr)) || ('I' == (*itr)))
-                        {
-                           return parse_inf(itr,end,t,negative);
-                        }
-                        else if (('n' == (*itr)) || ('N' == (*itr)))
-                        {
-                           return parse_nan(itr,end,t);
-                        }
-                        else
-                           return false;
-                     }
-                     else
-                        return false;
-                  }
-                  else if (('I' <= (*itr)) && ((*itr) <= 'n'))
-                  {
-                     if (('i' == (*itr)) || ('I' == (*itr)))
-                     {
-                        return parse_inf(itr,end,t,negative);
-                     }
-                     else if (('n' == (*itr)) || ('N' == (*itr)))
-                     {
-                        return parse_nan(itr,end,t);
-                     }
-                     else
-                        return false;
-                  }
-                  else
-                     return false;
-               }
+                return control_block_->size;
             }
-         }
-
-         if ((end != itr) || (!instate))
-            return false;
-         else if (exponent)
-            d = compute_pow10(d,exponent);
-
-         t = static_cast<T>((negative) ? -d : d);
-         return true;
-      }
-
-      template <typename T>
-      inline bool string_to_real(const std::string& s, T& t)
-      {
-         const char* begin = s.data();
-         const char* end   = s.data() + s.size();
-         typename numeric::details::number_type<T>::type num_type;
-         return string_to_real(begin,end,t,num_type);
-      }
-
-      template <typename T>
-      struct functor_t
-      {
-         /*
-            Note: The following definitions for Type, may require tweaking
-                  based on the compiler and target architecture. The benchmark
-                  should provide enough information to make the right choice.
-         */
-         //typedef T Type;
-         //typedef const T Type;
-         typedef const T& Type;
-         typedef T (*qfunc_t)(Type t0, Type t1, Type t2, Type t3);
-         typedef T (*tfunc_t)(Type t0, Type t1, Type t2);
-         typedef T (*bfunc_t)(Type t0, Type t1);
-         typedef T (*ufunc_t)(Type t0);
-      };
-
-   } // namespace details
-
-   namespace lexer
-   {
-      struct token
-      {
-         enum token_type
-         {
-            e_none        =   0, e_error       =   1, e_err_symbol  =   2,
-            e_err_number  =   3, e_err_string  =   4, e_err_sfunc   =   5,
-            e_eof         =   6, e_number      =   7, e_symbol      =   8,
-            e_string      =   9, e_assign      =  10, e_addass      =  11,
-            e_subass      =  12, e_mulass      =  13, e_divass      =  14,
-            e_modass      =  15, e_shr         =  16, e_shl         =  17,
-            e_lte         =  18, e_ne          =  19, e_gte         =  20,
-            e_swap        =  21, e_lt          = '<', e_gt          = '>',
-            e_eq          = '=', e_rbracket    = ')', e_lbracket    = '(',
-            e_rsqrbracket = ']', e_lsqrbracket = '[', e_rcrlbracket = '}',
-            e_lcrlbracket = '{', e_comma       = ',', e_add         = '+',
-            e_sub         = '-', e_div         = '/', e_mul         = '*',
-            e_mod         = '%', e_pow         = '^', e_colon       = ':',
-            e_ternary     = '?'
-         };
-
-         token()
-         : type(e_none),
-           value(""),
-           position(std::numeric_limits<std::size_t>::max())
-         {}
-
-         void clear()
-         {
-            type     = e_none;
-            value    = "";
-            position = std::numeric_limits<std::size_t>::max();
-         }
-
-         template <typename Iterator>
-         inline token& set_operator(const token_type tt, const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0))
-         {
-            type = tt;
-            value.assign(begin,end);
-            if (base_begin)
-               position = std::distance(base_begin,begin);
-            return *this;
-         }
-
-         template <typename Iterator>
-         inline token& set_symbol(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0))
-         {
-            type = e_symbol;
-            value.assign(begin,end);
-            if (base_begin)
-               position = std::distance(base_begin,begin);
-            return *this;
-         }
-
-         template <typename Iterator>
-         inline token& set_numeric(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0))
-         {
-            type = e_number;
-            value.assign(begin,end);
-            if (base_begin)
-               position = std::distance(base_begin,begin);
-            return *this;
-         }
-
-         template <typename Iterator>
-         inline token& set_string(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0))
-         {
-            type = e_string;
-            value.assign(begin,end);
-            if (base_begin)
-               position = std::distance(base_begin,begin);
-            return *this;
-         }
-
-         inline token& set_string(const std::string& s, const std::size_t p)
-         {
-            type     = e_string;
-            value    = s;
-            position = p;
-            return *this;
-         }
-
-         template <typename Iterator>
-         inline token& set_error(const token_type et, const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0))
-         {
-            if (
-                 (e_error      == et) ||
-                 (e_err_symbol == et) ||
-                 (e_err_number == et) ||
-                 (e_err_string == et) ||
-                 (e_err_sfunc  == et)
-               )
+            
+            inline std::size_t size() const
             {
-               type = et;
+                return control_block_->size;
+            }
+            
+            inline data_t& ref()
+            {
+                return control_block_->data;
+            }
+            
+            inline void dump() const
+            {
+#ifdef exprtk_enable_debugging
+                exprtk_debug(("size: %d\taddress:%p\tdestruct:%c\n",
+                              size(),
+                              data(),
+                              (control_block_->destruct ? 'T' : 'F')));
+                
+                for (std::size_t i = 0; i < size(); ++i)
+                {
+                    if (5 == i)
+                        exprtk_debug(("\n"));
+                    
+                    exprtk_debug(("%15.10f ",data()[i]));
+                }
+                exprtk_debug(("\n"));
+#endif
             }
-            else
-               type = e_error;
-
-            value.assign(begin,end);
-
-            if (base_begin)
-               position = std::distance(base_begin,begin);
-
-            return *this;
-         }
-
-         static inline std::string to_str(token_type t)
-         {
-            switch (t)
-            {
-               case e_none        : return "NONE";
-               case e_error       : return "ERROR";
-               case e_err_symbol  : return "ERROR_SYMBOL";
-               case e_err_number  : return "ERROR_NUMBER";
-               case e_err_string  : return "ERROR_STRING";
-               case e_eof         : return "EOF";
-               case e_number      : return "NUMBER";
-               case e_symbol      : return "SYMBOL";
-               case e_string      : return "STRING";
-               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_shr         : return ">>";
-               case e_shl         : return "<<";
-               case e_lte         : return "<=";
-               case e_ne          : return "!=";
-               case e_gte         : return ">=";
-               case e_lt          : return "<";
-               case e_gt          : return ">";
-               case e_eq          : return "=";
-               case e_rbracket    : return ")";
-               case e_lbracket    : return "(";
-               case e_rsqrbracket : return "]";
-               case e_lsqrbracket : return "[";
-               case e_rcrlbracket : return "}";
-               case e_lcrlbracket : return "{";
-               case e_comma       : return ",";
-               case e_add         : return "+";
-               case e_sub         : return "-";
-               case e_div         : return "/";
-               case e_mul         : return "*";
-               case e_mod         : return "%";
-               case e_pow         : return "^";
-               case e_colon       : return ":";
-               case e_ternary     : return "?";
-               case e_swap        : return "<=>";
-               default            : return "UNKNOWN";
-            }
-         }
-
-         inline bool is_error() const
-         {
-            return (
-                     (e_error      == type) ||
-                     (e_err_symbol == type) ||
-                     (e_err_number == type) ||
-                     (e_err_string == type) ||
-                     (e_err_sfunc  == type)
-                   );
-         }
-
-         token_type type;
-         std::string value;
-         std::size_t position;
-      };
-
-      class generator
-      {
-      public:
-
-         typedef token token_t;
-         typedef std::vector<token_t> token_list_t;
-         typedef std::vector<token_t>::iterator token_list_itr_t;
-
-         generator()
-         : base_itr_(0),
-           s_itr_   (0),
-           s_end_   (0)
-         {
-            clear();
-         }
-
-         inline void clear()
-         {
-            base_itr_ = 0;
-            s_itr_    = 0;
-            s_end_    = 0;
-            token_list_.clear();
-            token_itr_ = token_list_.end();
-            store_token_itr_ = token_list_.end();
-         }
-
-         inline bool process(const std::string& str)
-         {
-            base_itr_ = str.data();
-            s_itr_    = str.data();
-            s_end_    = str.data() + str.size();
-
-            eof_token_.set_operator(token_t::e_eof,s_end_,s_end_,base_itr_);
-            token_list_.clear();
-
-            while (!is_end(s_itr_))
+            
+            static inline void match_sizes(type& vds0, type& vds1)
             {
-               scan_token();
-
-               if (token_list_.empty())
-                  return true;
-               else if (token_list_.back().is_error())
-               {
-                  return false;
-               }
+                std::size_t size = min_size(vds0.control_block_,vds1.control_block_);
+                vds0.control_block_->size = size;
+                vds1.control_block_->size = size;
             }
-
-            return true;
-         }
-
-         inline bool empty() const
-         {
-            return token_list_.empty();
-         }
-
-         inline std::size_t size() const
-         {
-            return token_list_.size();
-         }
-
-         inline void begin()
-         {
-            token_itr_ = token_list_.begin();
-            store_token_itr_ = token_list_.begin();
-         }
-
-         inline void store()
-         {
-            store_token_itr_ = token_itr_;
-         }
-
-         inline void restore()
-         {
-            token_itr_ = store_token_itr_;
-         }
-
-         inline token_t& next_token()
-         {
-            if (token_list_.end() != token_itr_)
+            
+        private:
+            
+            static inline std::size_t min_size(control_block* cb0, control_block* cb1)
             {
-               return *token_itr_++;
+                std::size_t size0 = cb0->size;
+                std::size_t size1 = cb1->size;
+                
+                if (size0 && size1)
+                    return std::min(size0,size1);
+                else
+                    return (size0) ? size0 : size1;
             }
-            else
-               return eof_token_;
-         }
-
-         inline token_t& peek_next_token()
-         {
-            if (token_list_.end() != token_itr_)
+            
+            control_block* control_block_;
+        };
+        
+        namespace numeric
+        {
+            namespace details
+            {
+                template <typename T>
+                inline T process_impl(const operator_type operation, const T arg)
+                {
+                    switch (operation)
+                    {
+                        case e_abs   : return numeric::abs  (arg);
+                        case e_acos  : return numeric::acos (arg);
+                        case e_acosh : return numeric::acosh(arg);
+                        case e_asin  : return numeric::asin (arg);
+                        case e_asinh : return numeric::asinh(arg);
+                        case e_atan  : return numeric::atan (arg);
+                        case e_atanh : return numeric::atanh(arg);
+                        case e_ceil  : return numeric::ceil (arg);
+                        case e_cos   : return numeric::cos  (arg);
+                        case e_cosh  : return numeric::cosh (arg);
+                        case e_exp   : return numeric::exp  (arg);
+                        case e_expm1 : return numeric::expm1(arg);
+                        case e_floor : return numeric::floor(arg);
+                        case e_log   : return numeric::log  (arg);
+                        case e_log10 : return numeric::log10(arg);
+                        case e_log2  : return numeric::log2 (arg);
+                        case e_log1p : return numeric::log1p(arg);
+                        case e_neg   : return numeric::neg  (arg);
+                        case e_pos   : return numeric::pos  (arg);
+                        case e_round : return numeric::round(arg);
+                        case e_sin   : return numeric::sin  (arg);
+                        case e_sinc  : return numeric::sinc (arg);
+                        case e_sinh  : return numeric::sinh (arg);
+                        case e_sqrt  : return numeric::sqrt (arg);
+                        case e_tan   : return numeric::tan  (arg);
+                        case e_tanh  : return numeric::tanh (arg);
+                        case e_cot   : return numeric::cot  (arg);
+                        case e_sec   : return numeric::sec  (arg);
+                        case e_csc   : return numeric::csc  (arg);
+                        case e_r2d   : return numeric::r2d  (arg);
+                        case e_d2r   : return numeric::d2r  (arg);
+                        case e_d2g   : return numeric::d2g  (arg);
+                        case e_g2d   : return numeric::g2d  (arg);
+                        case e_notl  : return numeric::notl (arg);
+                        case e_sgn   : return numeric::sgn  (arg);
+                        case e_erf   : return numeric::erf  (arg);
+                        case e_erfc  : return numeric::erfc (arg);
+                        case e_ncdf  : return numeric::ncdf (arg);
+                        case e_frac  : return numeric::frac (arg);
+                        case e_trunc : return numeric::trunc(arg);
+                        default      : return std::numeric_limits<T>::quiet_NaN();
+                    }
+                }
+                
+                template <typename T>
+                inline T process_impl(const operator_type operation, const T arg0, const T arg1)
+                {
+                    switch (operation)
+                    {
+                        case e_add    : return (arg0 + arg1);
+                        case e_sub    : return (arg0 - arg1);
+                        case e_mul    : return (arg0 * arg1);
+                        case e_div    : return (arg0 / arg1);
+                        case e_mod    : return modulus<T>(arg0,arg1);
+                        case e_pow    : return pow<T>(arg0,arg1);
+                        case e_atan2  : return atan2<T>(arg0,arg1);
+                        case e_min    : return std::min<T>(arg0,arg1);
+                        case e_max    : return std::max<T>(arg0,arg1);
+                        case e_logn   : return logn<T>(arg0,arg1);
+                        case e_lt     : return (arg0 <  arg1) ? T(1) : T(0);
+                        case e_lte    : return (arg0 <= arg1) ? T(1) : T(0);
+                        case e_eq     : return std::equal_to<T>()(arg0,arg1) ? T(1) : T(0);
+                        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_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_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_equal  : return equal<T>   (arg0,arg1);
+                        case e_nequal : return nequal<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       : return std::numeric_limits<T>::quiet_NaN();
+                    }
+                }
+                
+                template <typename T>
+                inline T process_impl(const operator_type operation, const T arg0, const T arg1, int_type_tag)
+                {
+                    switch (operation)
+                    {
+                        case e_add    : return (arg0 + arg1);
+                        case e_sub    : return (arg0 - arg1);
+                        case e_mul    : return (arg0 * arg1);
+                        case e_div    : return (arg0 / arg1);
+                        case e_mod    : return arg0 % arg1;
+                        case e_pow    : return pow<T>(arg0,arg1);
+                        case e_min    : return std::min<T>(arg0,arg1);
+                        case e_max    : return std::max<T>(arg0,arg1);
+                        case e_logn   : return logn<T>(arg0,arg1);
+                        case e_lt     : return (arg0 <  arg1) ? T(1) : T(0);
+                        case e_lte    : return (arg0 <= arg1) ? T(1) : T(0);
+                        case e_eq     : return (arg0 == arg1) ? T(1) : T(0);
+                        case e_ne     : return (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 ((arg0 != T(0)) && (arg1 != T(0))) ? T(1) : T(0);
+                        case e_nand   : return ((arg0 != T(0)) && (arg1 != T(0))) ? T(0) : T(1);
+                        case e_or     : return ((arg0 != T(0)) || (arg1 != T(0))) ? T(1) : T(0);
+                        case e_nor    : return ((arg0 != T(0)) || (arg1 != T(0))) ? T(0) : T(1);
+                        case e_xor    : return arg0 ^ arg1;
+                        case e_xnor   : return !(arg0 ^ arg1);
+                        case e_root   : return root<T>(arg0,arg1);
+                        case e_equal  : return arg0 == arg1;
+                        case e_nequal : return arg0 != arg1;
+                        case e_hypot  : return hypot<T>(arg0,arg1);
+                        case e_shr    : return arg0 >> arg1;
+                        case e_shl    : return arg0 << arg1;
+                        default       : return std::numeric_limits<T>::quiet_NaN();
+                    }
+                }
+            }
+            
+            template <typename T>
+            inline T process(const operator_type operation, const T arg)
             {
-               return *token_itr_;
+                return exprtk::details::numeric::details::process_impl(operation,arg);
+            }
+            
+            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);
+            }
+        }
+        
+        template <typename T>
+        class expression_node
+        {
+        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_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;
+            
+            virtual ~expression_node()
+            {}
+            
+            inline virtual T value() const
+            {
+                return std::numeric_limits<T>::quiet_NaN();
+            }
+            
+            inline virtual expression_node<T>* branch(const std::size_t& index = 0) const
+            {
+                return reinterpret_cast<expression_ptr>(index * 0);
+            }
+            
+            inline virtual node_type type() const
+            {
+                return e_none;
+            }
+        };
+        
+        template <typename T>
+        inline bool is_generally_string_node(const expression_node<T>* node);
+        
+        inline bool is_true(const double v)
+        {
+            return std::not_equal_to<double>()(0.0,v);
+        }
+        
+        inline bool is_true(const long double v)
+        {
+            return std::not_equal_to<long double>()(0.0L,v);
+        }
+        
+        inline bool is_true(const float v)
+        {
+            return std::not_equal_to<float>()(0.0f,v);
+        }
+        
+        template <typename T>
+        inline bool is_true(const std::complex<T>& v)
+        {
+            return std::not_equal_to<std::complex<T> >()(std::complex<T>(0),v);
+        }
+        
+        template <typename T>
+        inline bool is_true(const expression_node<T>* node)
+        {
+            return std::not_equal_to<T>()(T(0),node->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_unary_node(const expression_node<T>* node)
+        {
+            return node && (details::expression_node<T>::e_unary == node->type());
+        }
+        
+        template <typename T>
+        inline bool is_neg_unary_node(const expression_node<T>* node)
+        {
+            return node && (details::expression_node<T>::e_neg == node->type());
+        }
+        
+        template <typename T>
+        inline bool is_binary_node(const expression_node<T>* node)
+        {
+            return node && (details::expression_node<T>::e_binary == node->type());
+        }
+        
+        template <typename T>
+        inline bool is_variable_node(const expression_node<T>* node)
+        {
+            return node && (details::expression_node<T>::e_variable == node->type());
+        }
+        
+        template <typename T>
+        inline bool is_ivariable_node(const expression_node<T>* node)
+        {
+            return node &&
+            (
+             details::expression_node<T>::e_variable   == node->type() ||
+             details::expression_node<T>::e_vecelem    == node->type() ||
+             details::expression_node<T>::e_rbvecelem  == node->type() ||
+             details::expression_node<T>::e_rbveccelem == node->type()
+             );
+        }
+        
+        template <typename T>
+        inline bool is_vector_elem_node(const expression_node<T>* node)
+        {
+            return node && (details::expression_node<T>::e_vecelem == node->type());
+        }
+        
+        template <typename T>
+        inline bool is_rebasevector_elem_node(const expression_node<T>* node)
+        {
+            return node && (details::expression_node<T>::e_rbvecelem == node->type());
+        }
+        
+        template <typename T>
+        inline bool is_rebasevector_celem_node(const expression_node<T>* node)
+        {
+            return node && (details::expression_node<T>::e_rbveccelem == node->type());
+        }
+        
+        template <typename T>
+        inline bool is_vector_node(const expression_node<T>* node)
+        {
+            return node && (details::expression_node<T>::e_vector == node->type());
+        }
+        
+        template <typename T>
+        inline bool is_ivector_node(const expression_node<T>* node)
+        {
+            if (node)
+            {
+                switch (node->type())
+                {
+                    case details::expression_node<T>::e_vector      :
+                    case details::expression_node<T>::e_vecvalass   :
+                    case details::expression_node<T>::e_vecvecass   :
+                    case details::expression_node<T>::e_vecopvalass :
+                    case details::expression_node<T>::e_vecopvecass :
+                    case details::expression_node<T>::e_vecvecswap  :
+                    case details::expression_node<T>::e_vecvecarith :
+                    case details::expression_node<T>::e_vecvalarith :
+                    case details::expression_node<T>::e_valvecarith :
+                    case details::expression_node<T>::e_vecunaryop  : return true;
+                    default                                         : return false;
+                }
             }
             else
-               return eof_token_;
-         }
-
-         inline token_t& operator[](const std::size_t& index)
-         {
-            if (index < token_list_.size())
-               return token_list_[index];
-            else
-               return eof_token_;
-         }
-
-         inline token_t operator[](const std::size_t& index) const
-         {
-            if (index < token_list_.size())
-               return token_list_[index];
+                return false;
+        }
+        
+        template <typename T>
+        inline bool is_constant_node(const expression_node<T>* node)
+        {
+            return node && (details::expression_node<T>::e_constant == node->type());
+        }
+        
+        template <typename T>
+        inline bool is_null_node(const expression_node<T>* node)
+        {
+            return node && (details::expression_node<T>::e_null == node->type());
+        }
+        
+        template <typename T>
+        inline bool is_break_node(const expression_node<T>* node)
+        {
+            return node && (details::expression_node<T>::e_break == node->type());
+        }
+        
+        template <typename T>
+        inline bool is_continue_node(const expression_node<T>* node)
+        {
+            return node && (details::expression_node<T>::e_continue == node->type());
+        }
+        
+        template <typename T>
+        inline bool is_swap_node(const expression_node<T>* node)
+        {
+            return node && (details::expression_node<T>::e_swap == node->type());
+        }
+        
+        template <typename T>
+        inline bool is_function(const expression_node<T>* node)
+        {
+            return node && (details::expression_node<T>::e_function == node->type());
+        }
+        
+        template <typename T>
+        inline bool is_return_node(const expression_node<T>* node)
+        {
+            return node && (details::expression_node<T>::e_return == node->type());
+        }
+        
+        template <typename T> class unary_node;
+        
+        template <typename T>
+        inline bool is_negate_node(const expression_node<T>* node)
+        {
+            if (node && is_unary_node(node))
+            {
+                return (details::e_neg == static_cast<const unary_node<T>*>(node)->operation());
+            }
             else
-               return eof_token_;
-         }
-
-         inline bool finished() const
-         {
-            return (token_list_.end() == token_itr_);
-         }
-
-         inline void insert_front(token_t::token_type tk_type)
-         {
-            if (
-                 !token_list_.empty() &&
-                 (token_list_.end() != token_itr_)
-               )
+                return false;
+        }
+        
+        template <typename T>
+        inline bool branch_deletable(expression_node<T>* node)
+        {
+            return !is_variable_node(node) &&
+            !is_string_node  (node) ;
+        }
+        
+        template <std::size_t N, typename T>
+        inline bool all_nodes_valid(expression_node<T>* (&b)[N])
+        {
+            for (std::size_t i = 0; i < N; ++i)
             {
-               token_t t = *token_itr_;
-
-               t.type     = tk_type;
-               token_itr_ = token_list_.insert(token_itr_,t);
+                if (0 == b[i]) return false;
             }
-         }
-
-      private:
-
-         inline bool is_end(const char* itr)
-         {
-            return (s_end_ == itr);
-         }
-
-         inline void skip_whitespace()
-         {
-            while (!is_end(s_itr_) && details::is_whitespace(*s_itr_))
+            
+            return true;
+        }
+        
+        template <typename T,
+        typename Allocator,
+        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)
             {
-               ++s_itr_;
+                if (0 == b[i]) return false;
             }
-         }
-
-         inline void skip_comments()
-         {
-            #ifndef exprtk_disable_comments
-            // The following comment styles are supported:
-            // 1. // .... \n
-            // 2. #  .... \n
-            // 3. /* .... */
-            struct test
-            {
-               static inline bool comment_start(const char c0, const char c1, int& mode, int& incr)
-               {
-                  mode = 0;
-                       if ('#' == c0)    { mode = 1; incr = 1; }
-                  else if ('/' == c0)
-                  {
-                          if ('/' == c1) { mode = 1; incr = 2; }
-                     else if ('*' == c1) { mode = 2; incr = 2; }
-                  }
-                  return (0 != mode);
-               }
-
-               static inline bool comment_end(const char c0, const char c1, const int mode)
-               {
-                  return (
-                           ((1 == mode) && ('\n' == c0)) ||
-                           ((2 == mode) && ( '*' == c0) && ('/' == c1))
-                         );
-               }
-            };
-
-            int mode = 0;
-            int increment = 0;
-
-            if (is_end(s_itr_) || is_end((s_itr_ + 1)))
-               return;
-            else if (!test::comment_start(*s_itr_,*(s_itr_ + 1),mode,increment))
-               return;
-
-            s_itr_ += increment;
-
-            while (!is_end(s_itr_) && !test::comment_end(*s_itr_,*(s_itr_ + 1),mode))
+            
+            return true;
+        }
+        
+        template <std::size_t N, typename T>
+        inline bool all_nodes_variables(expression_node<T>* (&b)[N])
+        {
+            for (std::size_t i = 0; i < N; ++i)
             {
-               ++s_itr_;
+                if (0 == b[i])
+                    return false;
+                else if (!is_variable_node(b[i]))
+                    return false;
             }
-
-            if (!is_end(s_itr_))
+            
+            return true;
+        }
+        
+        template <typename T,
+        typename Allocator,
+        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)
             {
-               s_itr_ += mode;
-               skip_whitespace();
-               skip_comments();
+                if (0 == b[i])
+                    return false;
+                else if (!is_variable_node(b[i]))
+                    return false;
             }
-            #endif
-         }
-
-         inline void scan_token()
-         {
-            skip_whitespace();
-            skip_comments();
-            if (is_end(s_itr_))
+            
+            return true;
+        }
+        
+        template <typename NodeAllocator, typename T, std::size_t N>
+        inline void free_all_nodes(NodeAllocator& node_allocator, expression_node<T>* (&b)[N])
+        {
+            for (std::size_t i = 0; i < N; ++i)
             {
-               return;
+                free_node(node_allocator,b[i]);
             }
-            else if (details::is_operator_char(*s_itr_))
+        }
+        
+        template <typename NodeAllocator,
+        typename T,
+        typename Allocator,
+        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)
             {
-               scan_operator();
-               return;
+                free_node(node_allocator,b[i]);
             }
-            else if (details::is_letter(*s_itr_))
+            
+            b.clear();
+        }
+        
+        template <typename NodeAllocator, typename T>
+        inline void free_node(NodeAllocator& node_allocator, expression_node<T>*& node, const bool force_delete = false)
+        {
+            if (0 != node)
+            {
+                if (
+                    (is_variable_node(node) || is_string_node(node)) ||
+                    force_delete
+                    )
+                    return;
+                
+                node_allocator.free(node);
+                node = 0;
+            }
+        }
+        
+        template <typename Type>
+        class vector_holder
+        {
+        private:
+            
+            typedef Type value_type;
+            typedef value_type* value_ptr;
+            typedef const value_ptr const_value_ptr;
+            
+            class vector_holder_base
+            {
+            public:
+                
+                virtual ~vector_holder_base(){}
+                
+                inline value_ptr operator[](const std::size_t& index) const
+                {
+                    return value_at(index);
+                }
+                
+                inline std::size_t size() const
+                {
+                    return vector_size();
+                }
+                
+                inline value_ptr data() const
+                {
+                    return value_at(0);
+                }
+                
+                virtual inline bool rebaseable() const
+                {
+                    return false;
+                }
+                
+                virtual void set_ref(value_ptr*) {}
+                
+            protected:
+                
+                virtual value_ptr value_at(const std::size_t&) const = 0;
+                virtual std::size_t vector_size()              const = 0;
+            };
+            
+            class array_vector_impl : public vector_holder_base
+            {
+            public:
+                
+                array_vector_impl(const Type* vec, const std::size_t& vec_size)
+                : vec_(vec),
+                size_(vec_size)
+                {}
+                
+            protected:
+                
+                value_ptr value_at(const std::size_t& index) const
+                {
+                    if (index < size_)
+                        return const_cast<const_value_ptr>(vec_ + index);
+                    else
+                        return const_value_ptr(0);
+                }
+                
+                std::size_t vector_size() const
+                {
+                    return size_;
+                }
+                
+            private:
+                
+                array_vector_impl operator=(const array_vector_impl&);
+                
+                const Type* vec_;
+                const std::size_t size_;
+            };
+            
+            template <typename Allocator,
+            template <typename,typename> class Sequence>
+            class sequence_vector_impl : public vector_holder_base
+            {
+            public:
+                
+                typedef Sequence<Type,Allocator> sequence_t;
+                
+                sequence_vector_impl(sequence_t& seq)
+                : sequence_(seq)
+                {}
+                
+            protected:
+                
+                value_ptr value_at(const std::size_t& index) const
+                {
+                    return (index < sequence_.size()) ? (&sequence_[index]) : const_value_ptr(0);
+                }
+                
+                std::size_t vector_size() const
+                {
+                    return sequence_.size();
+                }
+                
+            private:
+                
+                sequence_vector_impl operator=(const sequence_vector_impl&);
+                
+                sequence_t& sequence_;
+            };
+            
+            class vector_view_impl : public vector_holder_base
+            {
+            public:
+                
+                typedef exprtk::vector_view<Type> vector_view_t;
+                
+                vector_view_impl(vector_view_t& vec_view)
+                : vec_view_(vec_view)
+                {}
+                
+                void set_ref(value_ptr* ref)
+                {
+                    vec_view_.set_ref(ref);
+                }
+                
+                virtual inline bool rebaseable() const
+                {
+                    return true;
+                }
+                
+            protected:
+                
+                value_ptr value_at(const std::size_t& index) const
+                {
+                    return (index < vec_view_.size()) ? (&vec_view_[index]) : const_value_ptr(0);
+                }
+                
+                std::size_t vector_size() const
+                {
+                    return vec_view_.size();
+                }
+                
+            private:
+                
+                vector_view_impl operator=(const vector_view_impl&);
+                
+                vector_view_t& vec_view_;
+            };
+            
+        public:
+            
+            typedef typename details::vec_data_store<Type> vds_t;
+            
+            vector_holder(Type* vec, const std::size_t& vec_size)
+            : vector_holder_base_(new(buffer)array_vector_impl(vec,vec_size))
+            {}
+            
+            vector_holder(const vds_t& vds)
+            : vector_holder_base_(new(buffer)array_vector_impl(vds.data(),vds.size()))
+            {}
+            
+            template <typename Allocator>
+            vector_holder(std::vector<Type,Allocator>& vec)
+            : vector_holder_base_(new(buffer)sequence_vector_impl<Allocator,std::vector>(vec))
+            {}
+            
+            vector_holder(exprtk::vector_view<Type>& vec)
+            : vector_holder_base_(new(buffer)vector_view_impl(vec))
+            {}
+            
+            inline value_ptr operator[](const std::size_t& index) const
             {
-               scan_symbol();
-               return;
+                return (*vector_holder_base_)[index];
             }
-            else if (details::is_digit((*s_itr_)) || ('.' == (*s_itr_)))
+            
+            inline std::size_t size() const
             {
-               scan_number();
-               return;
+                return vector_holder_base_->size();
             }
-            else if ('$' == (*s_itr_))
+            
+            inline value_ptr data() const
             {
-               scan_special_function();
-               return;
+                return vector_holder_base_->data();
             }
-            #ifndef exprtk_disable_string_capabilities
-            else if ('\'' == (*s_itr_))
+            
+            void set_ref(value_ptr* ref)
             {
-               scan_string();
-               return;
+                return vector_holder_base_->set_ref(ref);
             }
-            #endif
-            else if ('~' == (*s_itr_))
+            
+            bool rebaseable() const
             {
-               token_t t;
-               t.set_symbol(s_itr_,s_itr_ + 1,base_itr_);
-               token_list_.push_back(t);
-               ++s_itr_;
-               return;
+                return vector_holder_base_->rebaseable();
             }
-            else
+            
+        private:
+            
+            mutable vector_holder_base* vector_holder_base_;
+            uchar_t buffer[64];
+        };
+        
+        template <typename T>
+        class null_node : public expression_node<T>
+        {
+        public:
+            
+            inline T value() const
             {
-               token_t t;
-               t.set_error(token::e_error,s_itr_,s_itr_ + 2,base_itr_);
-               token_list_.push_back(t);
-               ++s_itr_;
+                return std::numeric_limits<T>::quiet_NaN();
             }
-         }
-
-         inline void scan_operator()
-         {
-            token_t t;
-
-            const char c0 = s_itr_[0];
-
-            if (!is_end(s_itr_ + 1))
+            
+            inline typename expression_node<T>::node_type type() const
             {
-               const char c1 = s_itr_[1];
-
-               if (!is_end(s_itr_ + 2))
-               {
-                  const char c2 = s_itr_[2];
-
-                  if ((c0 == '<') && (c1 == '=') && (c2 == '>'))
-                  {
-                     t.set_operator(token_t::e_swap,s_itr_,s_itr_ + 3,base_itr_);
-                     token_list_.push_back(t);
-                     s_itr_ += 3;
-                     return;
-                  }
-               }
-
-               token_t::token_type ttype = token_t::e_none;
-
-                    if ((c0 == '<') && (c1 == '=')) ttype = token_t::e_lte;
-               else if ((c0 == '>') && (c1 == '=')) ttype = token_t::e_gte;
-               else if ((c0 == '<') && (c1 == '>')) ttype = token_t::e_ne;
-               else if ((c0 == '!') && (c1 == '=')) ttype = token_t::e_ne;
-               else if ((c0 == '=') && (c1 == '=')) ttype = token_t::e_eq;
-               else if ((c0 == ':') && (c1 == '=')) ttype = token_t::e_assign;
-               else if ((c0 == '<') && (c1 == '<')) ttype = token_t::e_shl;
-               else if ((c0 == '>') && (c1 == '>')) ttype = token_t::e_shr;
-               else if ((c0 == '+') && (c1 == '=')) ttype = token_t::e_addass;
-               else if ((c0 == '-') && (c1 == '=')) ttype = token_t::e_subass;
-               else if ((c0 == '*') && (c1 == '=')) ttype = token_t::e_mulass;
-               else if ((c0 == '/') && (c1 == '=')) ttype = token_t::e_divass;
-               else if ((c0 == '%') && (c1 == '=')) ttype = token_t::e_modass;
-
-               if (token_t::e_none != ttype)
-               {
-                  t.set_operator(ttype,s_itr_,s_itr_ + 2,base_itr_);
-                  token_list_.push_back(t);
-                  s_itr_ += 2;
-                  return;
-               }
+                return expression_node<T>::e_null;
             }
-
-            if ('<' == c0)
-               t.set_operator(token_t::e_lt ,s_itr_,s_itr_ + 1,base_itr_);
-            else if ('>' == c0)
-               t.set_operator(token_t::e_gt ,s_itr_,s_itr_ + 1,base_itr_);
-            else if (';' == c0)
-               t.set_operator(token_t::e_eof,s_itr_,s_itr_ + 1,base_itr_);
-            else if ('&' == c0)
-               t.set_symbol(s_itr_,s_itr_ + 1,base_itr_);
-            else if ('|' == c0)
-               t.set_symbol(s_itr_,s_itr_ + 1,base_itr_);
-            else
-               t.set_operator(token_t::token_type(c0),s_itr_,s_itr_ + 1,base_itr_);
-
-            token_list_.push_back(t);
-            ++s_itr_;
-         }
-
-         inline void scan_symbol()
-         {
-            const char* initial_itr = s_itr_;
-
-            while (
-                    (!is_end(s_itr_)) &&
-                    (details::is_letter_or_digit(*s_itr_) || ((*s_itr_) == '_'))
-                  )
+        };
+        
+        template <typename T>
+        class null_eq_node : public expression_node<T>
+        {
+        public:
+            
+            typedef expression_node<T>* expression_ptr;
+            
+            null_eq_node(expression_ptr brnch, const bool equality = true)
+            : branch_(brnch),
+            branch_deletable_(branch_deletable(branch_)),
+            equality_(equality)
+            {}
+            
+            ~null_eq_node()
             {
-               ++s_itr_;
+                if (branch_ && branch_deletable_)
+                {
+                    delete branch_;
+                    branch_ = 0;
+                }
             }
-
-            token_t t;
-            t.set_symbol(initial_itr,s_itr_,base_itr_);
-            token_list_.push_back(t);
-         }
-
-         inline void scan_number()
-         {
-            /*
-               Attempt to match a valid numeric value in one of the following formats:
-               1. 123456
-               2. 123.456
-               3. 123.456e3
-               4. 123.456E3
-               5. 123.456e+3
-               6. 123.456E+3
-               7. 123.456e-3
-               8. 123.456E-3
-            */
-            const char* initial_itr = s_itr_;
-            bool dot_found         = false;
-            bool e_found           = false;
-            bool post_e_sign_found = false;
-            token_t t;
-
-            while (!is_end(s_itr_))
-            {
-               if ('.' == (*s_itr_))
-               {
-                  if (dot_found)
-                  {
-                     t.set_error(token::e_err_number,initial_itr,s_itr_,base_itr_);
-                     token_list_.push_back(t);
-                     return;
-                  }
-
-                  dot_found = true;
-                  ++s_itr_;
-
-                  continue;
-               }
-               else if (details::imatch('e',(*s_itr_)))
-               {
-                  const char& c = *(s_itr_ + 1);
-
-                  if (is_end(s_itr_ + 1))
-                  {
-                     t.set_error(token::e_err_number,initial_itr,s_itr_,base_itr_);
-                     token_list_.push_back(t);
-
-                     return;
-                  }
-                  else if (
-                            ('+' != c) &&
-                            ('-' != c) &&
-                            !details::is_digit(c)
-                          )
-                  {
-                     t.set_error(token::e_err_number,initial_itr,s_itr_,base_itr_);
-                     token_list_.push_back(t);
-
-                     return;
-                  }
-
-                  e_found = true;
-                  ++s_itr_;
-                  continue;
-               }
-               else if (e_found && details::is_sign(*s_itr_))
-               {
-                  if (post_e_sign_found)
-                  {
-                     t.set_error(token::e_err_number,initial_itr,s_itr_,base_itr_);
-                     token_list_.push_back(t);
-
-                     return;
-                  }
-
-                  post_e_sign_found = true;
-                  ++s_itr_;
-                  continue;
-               }
-               else if (('.' != (*s_itr_)) && !details::is_digit(*s_itr_))
-                  break;
-               else
-                  ++s_itr_;
+            
+            inline T value() const
+            {
+                const T v = branch_->value();
+                const bool result = details::numeric::is_nan(v);
+                
+                if (result)
+                    return (equality_) ? T(1) : T(0);
+                else
+                    return (equality_) ? T(0) : T(1);
             }
-
-            t.set_numeric(initial_itr,s_itr_,base_itr_);
-            token_list_.push_back(t);
-
-            return;
-         }
-
-         inline void scan_special_function()
-         {
-            const char* initial_itr = s_itr_;
-            token_t t;
-
-            // $fdd(x,x,x) = at least 11 chars
-            if (std::distance(s_itr_,s_end_) < 11)
+            
+            inline typename expression_node<T>::node_type type() const
             {
-               t.set_error(token::e_err_sfunc,initial_itr,s_itr_,base_itr_);
-               token_list_.push_back(t);
-
-               return;
+                return expression_node<T>::e_nulleq;
             }
-
-            if (
-                 !(('$' == *s_itr_)                       &&
-                   (details::imatch  ('f',*(s_itr_ + 1))) &&
-                   (details::is_digit(*(s_itr_ + 2)))     &&
-                   (details::is_digit(*(s_itr_ + 3))))
-               )
-            {
-               t.set_error(token::e_err_sfunc,initial_itr,s_itr_,base_itr_);
-               token_list_.push_back(t);
-
-               return;
+            
+            inline operator_type operation() const
+            {
+                return details::e_eq;
             }
-
-            s_itr_ += 4; // $fdd = 4chars
-
-            t.set_symbol(initial_itr,s_itr_,base_itr_);
-            token_list_.push_back(t);
-
-            return;
-         }
-
-         #ifndef exprtk_disable_string_capabilities
-         inline void scan_string()
-         {
-            const char* initial_itr = s_itr_ + 1;
-            token_t t;
-
-            if (std::distance(s_itr_,s_end_) < 2)
+            
+            inline expression_node<T>* branch(const std::size_t&) const
             {
-               t.set_error(token::e_err_string,s_itr_,s_end_,base_itr_);
-               token_list_.push_back(t);
-               return;
+                return branch_;
             }
-
-            ++s_itr_;
-
-            bool escaped_found = false;
-            bool escaped = false;
-
-            while (!is_end(s_itr_))
+            
+        private:
+            
+            expression_ptr branch_;
+            bool branch_deletable_;
+            bool equality_;
+        };
+        
+        template <typename T>
+        class literal_node : public expression_node<T>
+        {
+        public:
+            
+            explicit literal_node(const T& v)
+            : value_(v)
+            {}
+            
+            inline T value() const
             {
-               if ('\\' == *s_itr_)
-               {
-                  escaped_found = true;
-                  escaped = true;
-                  ++s_itr_;
-
-                  continue;
-               }
-               else if (!escaped)
-               {
-                  if ('\'' == *s_itr_)
-                     break;
-               }
-               else if (escaped)
-               {
-                  if (!is_end(s_itr_) && ('0' == *(s_itr_)))
-                  {
-                     if (
-                          is_end(s_itr_ + 1) ||
-                          is_end(s_itr_ + 2) ||
-                          is_end(s_itr_ + 3) ||
-                          (
-                            ('x' != *(s_itr_ + 1)) &&
-                            ('X' != *(s_itr_ + 1))
-                          ) ||
-                          (!details::is_hex_digit(*(s_itr_ + 2))) ||
-                          (!details::is_hex_digit(*(s_itr_ + 3)))
-                        )
-                     {
-                        t.set_error(token::e_err_string,initial_itr,s_itr_,base_itr_);
-                        token_list_.push_back(t);
-                        return;
-                     }
-                     else
-                        s_itr_ += 3;
-                  }
-
-                  escaped = false;
-               }
-
-               ++s_itr_;
+                return value_;
             }
-
-            if (is_end(s_itr_))
+            
+            inline typename expression_node<T>::node_type type() const
             {
-               t.set_error(token::e_err_string,initial_itr,s_itr_,base_itr_);
-               token_list_.push_back(t);
-
-               return;
+                return expression_node<T>::e_constant;
             }
-
-            if (!escaped_found)
-               t.set_string(initial_itr,s_itr_,base_itr_);
-            else
+            
+            inline expression_node<T>* branch(const std::size_t&) const
             {
-               std::string parsed_string(initial_itr,s_itr_);
-               details::cleanup_escapes(parsed_string);
-               t.set_string(parsed_string, std::distance(base_itr_,initial_itr));
+                return reinterpret_cast<expression_node<T>*>(0);
             }
-
-            token_list_.push_back(t);
-            ++s_itr_;
-
-            return;
-         }
-         #endif
-
-      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* base_itr_;
-         const char* s_itr_;
-         const char* s_end_;
-
-         friend class token_scanner;
-         friend class token_modifier;
-         friend class token_inserter;
-         friend class token_joiner;
-      };
-
-      class helper_interface
-      {
-      public:
-
-         virtual void init()                     {              }
-         virtual void reset()                    {              }
-         virtual bool result()                   { return true; }
-         virtual std::size_t process(generator&) { return 0;    }
-         virtual ~helper_interface()             {              }
-      };
-
-      class token_scanner : public helper_interface
-      {
-      public:
-
-         virtual ~token_scanner()
-         {}
-
-         explicit token_scanner(const std::size_t& stride)
-         : stride_(stride)
-         {
-            if (stride > 4)
+            
+        private:
+            
+            literal_node(literal_node<T>&) {}
+            literal_node<T>& operator=(literal_node<T>&) { return *this; }
+            
+            const T value_;
+        };
+        
+        template <typename T>
+        struct range_pack;
+        
+        template <typename T>
+        struct range_data_type;
+        
+        template <typename T>
+        class range_interface
+        {
+        public:
+            
+            typedef range_pack<T> range_t;
+            
+            virtual ~range_interface()
+            {}
+            
+            virtual range_t& range_ref() = 0;
+            
+            virtual const range_t& range_ref() const = 0;
+        };
+        
+        template <typename T>
+        class string_base_node
+        {
+        public:
+            
+            typedef range_data_type<T> range_data_type_t;
+            
+            virtual ~string_base_node()
+            {}
+            
+            virtual std::string str () const = 0;
+            
+            virtual const char* base() const = 0;
+            
+            virtual std::size_t size() const = 0;
+        };
+        
+        template <typename T>
+        class string_literal_node : public expression_node <T>,
+        public string_base_node<T>,
+        public range_interface <T>
+        {
+        public:
+            
+            typedef range_pack<T> range_t;
+            
+            explicit string_literal_node(const std::string& v)
+            : value_(v)
             {
-               throw std::invalid_argument("token_scanner() - Invalid stride value");
+                rp_.n0_c = std::make_pair<bool,std::size_t>(true,0);
+                rp_.n1_c = std::make_pair<bool,std::size_t>(true,v.size() - 1);
+                rp_.cache.first  = rp_.n0_c.second;
+                rp_.cache.second = rp_.n1_c.second;
             }
-         }
-
-         inline std::size_t process(generator& g)
-         {
-            if (g.token_list_.size() >= stride_)
+            
+            inline T value() const
             {
-               for (std::size_t i = 0; i < (g.token_list_.size() - stride_ + 1); ++i)
-               {
-                  token t;
-
-                  switch (stride_)
-                  {
-                     case 1 :
-                              {
-                                 const token& t0 = g.token_list_[i];
-
-                                 if (!operator()(t0))
-                                 {
-                                    return i;
-                                 }
-                              }
-                              break;
-
-                     case 2 :
-                              {
-                                 const token& t0 = g.token_list_[i    ];
-                                 const token& t1 = g.token_list_[i + 1];
-
-                                 if (!operator()(t0,t1))
-                                 {
-                                    return i;
-                                 }
-                              }
-                              break;
-
-                     case 3 :
-                              {
-                                 const token& t0 = g.token_list_[i    ];
-                                 const token& t1 = g.token_list_[i + 1];
-                                 const token& t2 = g.token_list_[i + 2];
-
-                                 if (!operator()(t0,t1,t2))
-                                 {
-                                    return i;
-                                 }
-                              }
-                              break;
-
-                     case 4 :
-                              {
-                                 const token& t0 = g.token_list_[i    ];
-                                 const token& t1 = g.token_list_[i + 1];
-                                 const token& t2 = g.token_list_[i + 2];
-                                 const token& t3 = g.token_list_[i + 3];
-
-                                 if (!operator()(t0,t1,t2,t3))
-                                 {
-                                    return i;
-                                 }
-                              }
-                              break;
-                  }
-               }
-            }
-
-            return (g.token_list_.size() - stride_ + 1);
-         }
-
-         virtual bool operator()(const token&)
-         {
-            return false;
-         }
-
-         virtual bool operator()(const token&, const token&)
-         {
-            return false;
-         }
-
-         virtual bool operator()(const token&, const token&, const token&)
-         {
-            return false;
-         }
-
-         virtual bool operator()(const token&, const token&, const token&, const token&)
-         {
-            return false;
-         }
-
-      private:
-
-         std::size_t stride_;
-      };
-
-      class token_modifier : public helper_interface
-      {
-      public:
-
-         inline std::size_t process(generator& g)
-         {
-            std::size_t changes = 0;
-
-            for (std::size_t i = 0; i < g.token_list_.size(); ++i)
-            {
-               if (modify(g.token_list_[i])) changes++;
+                return std::numeric_limits<T>::quiet_NaN();
             }
-
-            return changes;
-         }
-
-         virtual bool modify(token& t) = 0;
-      };
-
-      class token_inserter : public helper_interface
-      {
-      public:
-
-         explicit token_inserter(const std::size_t& stride)
-         : stride_(stride)
-         {
-            if (stride > 5)
+            
+            inline typename expression_node<T>::node_type type() const
             {
-               throw std::invalid_argument("token_inserter() - Invalid stride value");
+                return expression_node<T>::e_stringconst;
             }
-         }
-
-         inline std::size_t process(generator& g)
-         {
-            if (g.token_list_.empty())
-               return 0;
-            else if (g.token_list_.size() < stride_)
-               return 0;
-
-            std::size_t changes = 0;
-
-            for (std::size_t i = 0; i < (g.token_list_.size() - stride_ + 1); ++i)
+            
+            inline expression_node<T>* branch(const std::size_t&) const
             {
-               int insert_index = -1;
-               token t;
-
-               switch (stride_)
-               {
-                  case 1 : insert_index = insert(g.token_list_[i],t);
-                           break;
-
-                  case 2 : insert_index = insert(g.token_list_[i],g.token_list_[i + 1],t);
-                           break;
-
-                  case 3 : insert_index = insert(g.token_list_[i],g.token_list_[i + 1],g.token_list_[i + 2],t);
-                           break;
-
-                  case 4 : insert_index = insert(g.token_list_[i],g.token_list_[i + 1],g.token_list_[i + 2],g.token_list_[i + 3],t);
-                           break;
-
-                  case 5 : insert_index = insert(g.token_list_[i],g.token_list_[i + 1],g.token_list_[i + 2],g.token_list_[i + 3],g.token_list_[i + 4],t);
-                           break;
-               }
-
-               if ((insert_index >= 0) && (insert_index <= (static_cast<int>(stride_) + 1)))
-               {
-                  g.token_list_.insert(g.token_list_.begin() + (i + insert_index),t);
-                  changes++;
-               }
+                return reinterpret_cast<expression_node<T>*>(0);
             }
-
-            return changes;
-         }
-
-         inline virtual int insert(const token&, token& )
-         {
-            return -1;
-         }
-
-         inline virtual int insert(const token&, const token&, token&)
-         {
-            return -1;
-         }
-
-         inline virtual int insert(const token&, const token&, const token&, token&)
-         {
-            return -1;
-         }
-
-         inline virtual int insert(const token&, const token&, const token&, const token&, token&)
-         {
-            return -1;
-         }
-
-         inline virtual int insert(const token&, const token&, const token&, const token&, const token&, token&)
-         {
-            return -1;
-         }
-
-      private:
-
-         std::size_t stride_;
-      };
-
-      class token_joiner : public helper_interface
-      {
-      public:
-
-         token_joiner(const std::size_t& stride)
-         : stride_(stride)
-         {}
-
-         inline std::size_t process(generator& g)
-         {
-            if (g.token_list_.empty())
-               return 0;
-
-            switch (stride_)
+            
+            std::string str() const
             {
-               case 2  : return process_stride_2(g);
-               case 3  : return process_stride_3(g);
-               default : return 0;
+                return value_;
             }
-         }
-
-         virtual bool join(const token&, const token&, token&) { return false; }
-         virtual bool join(const token&, const token&, const token&, token&) { return false; }
-
-      private:
-
-         inline std::size_t process_stride_2(generator& g)
-         {
-            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)
+            
+            const char* base() const
             {
-               token t;
-
-               while (join(g.token_list_[i],g.token_list_[i + 1],t))
-               {
-                  g.token_list_[i] = t;
-                  g.token_list_.erase(g.token_list_.begin() + (i + 1));
-                  ++changes;
-               }
+                return value_.data();
             }
-
-            return changes;
-         }
-
-         inline std::size_t process_stride_3(generator& g)
-         {
-            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)
+            
+            std::size_t size() const
             {
-               token t;
-
-               while (join(g.token_list_[i],g.token_list_[i + 1],g.token_list_[i + 2],t))
-               {
-                  g.token_list_[i] = t;
-                  g.token_list_.erase(g.token_list_.begin() + (i + 1),
-                                      g.token_list_.begin() + (i + 3));
-                  ++changes;
-               }
+                return value_.size();
             }
-
-            return changes;
-         }
-
-         std::size_t stride_;
-      };
-
-      namespace helper
-      {
-
-         inline void dump(lexer::generator& generator)
-         {
-            for (std::size_t i = 0; i < generator.size(); ++i)
-            {
-               lexer::token t = generator[i];
-               printf("Token[%02d] @ %03d  %6s  -->  '%s'\n",
-                      static_cast<int>(i),
-                      static_cast<int>(t.position),
-                      t.to_str(t.type).c_str(),
-                      t.value.c_str());
-            }
-         }
-
-         class commutative_inserter : public lexer::token_inserter
-         {
-         public:
-
-            commutative_inserter()
-            : lexer::token_inserter(2)
-            {}
-
-            inline void ignore_symbol(const std::string& symbol)
+            
+            range_t& range_ref()
             {
-               ignore_set_.insert(symbol);
+                return rp_;
             }
-
-            inline int insert(const lexer::token& t0, const lexer::token& t1, lexer::token& new_token)
+            
+            const range_t& range_ref() const
             {
-               bool match         = false;
-               new_token.type     = lexer::token::e_mul;
-               new_token.value    = "*";
-               new_token.position = t1.position;
-
-               if (t0.type == lexer::token::e_symbol)
-               {
-                  if (ignore_set_.end() != ignore_set_.find(t0.value))
-                  {
-                     return -1;
-                  }
-                  else if (!t0.value.empty() && ('$' == t0.value[0]))
-                  {
-                     return -1;
-                  }
-               }
-
-               if (t1.type == lexer::token::e_symbol)
-               {
-                  if (ignore_set_.end() != ignore_set_.find(t1.value))
-                  {
-                     return -1;
-                  }
-               }
-                    if ((t0.type == lexer::token::e_number     ) && (t1.type == lexer::token::e_symbol     )) match = true;
-               else if ((t0.type == lexer::token::e_number     ) && (t1.type == lexer::token::e_lbracket   )) match = true;
-               else if ((t0.type == lexer::token::e_number     ) && (t1.type == lexer::token::e_lcrlbracket)) match = true;
-               else if ((t0.type == lexer::token::e_number     ) && (t1.type == lexer::token::e_lsqrbracket)) match = true;
-               else if ((t0.type == lexer::token::e_symbol     ) && (t1.type == lexer::token::e_number     )) match = true;
-               else if ((t0.type == lexer::token::e_rbracket   ) && (t1.type == lexer::token::e_number     )) match = true;
-               else if ((t0.type == lexer::token::e_rcrlbracket) && (t1.type == lexer::token::e_number     )) match = true;
-               else if ((t0.type == lexer::token::e_rsqrbracket) && (t1.type == lexer::token::e_number     )) match = true;
-               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;
-
-               return (match) ? 1 : -1;
+                return rp_;
             }
-
-         private:
-
-            std::set<std::string,details::ilesscompare> ignore_set_;
-         };
-
-         class operator_joiner : public token_joiner
-         {
-         public:
-
-            operator_joiner(const std::size_t& stride)
-            : token_joiner(stride)
+            
+        private:
+            
+            string_literal_node(const string_literal_node<T>&);
+            string_literal_node<T>& operator=(const string_literal_node<T>&);
+            
+            const std::string value_;
+            range_t rp_;
+        };
+        
+        template <typename T>
+        class unary_node : public expression_node<T>
+        {
+        public:
+            
+            typedef expression_node<T>* expression_ptr;
+            
+            unary_node(const operator_type& opr,
+                       expression_ptr brnch)
+            : operation_(opr),
+            branch_(brnch),
+            branch_deletable_(branch_deletable(branch_))
             {}
-
-            inline bool join(const lexer::token& t0, const lexer::token& t1, lexer::token& t)
-            {
-               // ': =' --> ':='
-               if ((t0.type == lexer::token::e_colon) && (t1.type == lexer::token::e_eq))
-               {
-                  t.type     = lexer::token::e_assign;
-                  t.value    = ":=";
-                  t.position = t0.position;
-                  return true;
-               }
-               // '+ =' --> '+='
-               else if ((t0.type == lexer::token::e_add) && (t1.type == lexer::token::e_eq))
-               {
-                  t.type     = lexer::token::e_addass;
-                  t.value    = "+=";
-                  t.position = t0.position;
-                  return true;
-               }
-               // '- =' --> '-='
-               else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_eq))
-               {
-                  t.type     = lexer::token::e_subass;
-                  t.value    = "-=";
-                  t.position = t0.position;
-                  return true;
-               }
-               // '* =' --> '*='
-               else if ((t0.type == lexer::token::e_mul) && (t1.type == lexer::token::e_eq))
-               {
-                  t.type     = lexer::token::e_mulass;
-                  t.value    = "*=";
-                  t.position = t0.position;
-                  return true;
-               }
-               // '/ =' --> '/='
-               else if ((t0.type == lexer::token::e_div) && (t1.type == lexer::token::e_eq))
-               {
-                  t.type     = lexer::token::e_divass;
-                  t.value    = "/=";
-                  t.position = t0.position;
-                  return true;
-               }
-               // '% =' --> '%='
-               else if ((t0.type == lexer::token::e_mod) && (t1.type == lexer::token::e_eq))
-               {
-                  t.type     = lexer::token::e_modass;
-                  t.value    = "%=";
-                  t.position = t0.position;
-                  return true;
-               }
-               // '> =' --> '>='
-               else if ((t0.type == lexer::token::e_gt) && (t1.type == lexer::token::e_eq))
-               {
-                  t.type     = lexer::token::e_gte;
-                  t.value    = ">=";
-                  t.position = t0.position;
-                  return true;
-               }
-               // '< =' --> '<='
-               else if ((t0.type == lexer::token::e_lt) && (t1.type == lexer::token::e_eq))
-               {
-                  t.type     = lexer::token::e_lte;
-                  t.value    = "<=";
-                  t.position = t0.position;
-                  return true;
-               }
-               // '= =' --> '=='
-               else if ((t0.type == lexer::token::e_eq) && (t1.type == lexer::token::e_eq))
-               {
-                  t.type     = lexer::token::e_eq;
-                  t.value    = "==";
-                  t.position = t0.position;
-                  return true;
-               }
-               // '! =' --> '!='
-               else if ((static_cast<char>(t0.type) == '!') && (t1.type == lexer::token::e_eq))
-               {
-                  t.type     = lexer::token::e_ne;
-                  t.value    = "!=";
-                  t.position = t0.position;
-                  return true;
-               }
-               // '< >' --> '<>'
-               else if ((t0.type == lexer::token::e_lt) && (t1.type == lexer::token::e_gt))
-               {
-                  t.type     = lexer::token::e_ne;
-                  t.value    = "<>";
-                  t.position = t0.position;
-                  return true;
-               }
-               // '<= >' --> '<=>'
-               else if ((t0.type == lexer::token::e_lte) && (t1.type == lexer::token::e_gt))
-               {
-                  t.type     = lexer::token::e_swap;
-                  t.value    = "<=>";
-                  t.position = t0.position;
-                  return true;
-               }
-               else
-                  return false;
+            
+            ~unary_node()
+            {
+                if (branch_ && branch_deletable_)
+                {
+                    delete branch_;
+                    branch_ = 0;
+                }
             }
-
-            inline bool join(const lexer::token& t0, const lexer::token& t1, const lexer::token& t2, lexer::token& t)
-            {
-               // '[ * ]' --> '[*]'
-               if (
-                    (t0.type == lexer::token::e_lsqrbracket) &&
-                    (t1.type == lexer::token::e_mul        ) &&
-                    (t2.type == lexer::token::e_rsqrbracket)
-                  )
-               {
-                  t.type     = lexer::token::e_symbol;
-                  t.value    = "[*]";
-                  t.position = t0.position;
-
-                  return true;
-               }
-               else
-                  return false;
+            
+            inline T value() const
+            {
+                const T arg = branch_->value();
+                return numeric::process<T>(operation_,arg);
             }
-         };
-
-         class bracket_checker : public lexer::token_scanner
-         {
-         public:
-
-            bracket_checker()
-            : token_scanner(1),
-              state_(true)
-            {}
-
-            bool result()
-            {
-               if (!stack_.empty())
-               {
-                  lexer::token t;
-                  t.value      = stack_.top().first;
-                  t.position   = stack_.top().second;
-                  error_token_ = t;
-                  state_       = false;
-
-                  return false;
-               }
-               else
-                  return state_;
+            
+            inline typename expression_node<T>::node_type type() const
+            {
+                return expression_node<T>::e_unary;
             }
-
-            lexer::token error_token()
+            
+            inline operator_type operation() const
             {
-               return error_token_;
+                return operation_;
             }
-
-            void reset()
+            
+            inline expression_node<T>* branch(const std::size_t&) const
             {
-               // Why? because msvc doesn't support swap properly.
-               stack_ = std::stack<std::pair<char,std::size_t> >();
-               state_ = true;
-               error_token_.clear();
+                return branch_;
             }
-
-            bool operator()(const lexer::token& t)
-            {
-               if (
-                    !t.value.empty()                       &&
-                    (lexer::token::e_string != t.type)     &&
-                    (lexer::token::e_symbol != t.type)     &&
-                    exprtk::details::is_bracket(t.value[0])
-                  )
-               {
-                  char c = t.value[0];
-
-                       if (t.type == lexer::token::e_lbracket)    stack_.push(std::make_pair(')',t.position));
-                  else if (t.type == lexer::token::e_lcrlbracket) stack_.push(std::make_pair('}',t.position));
-                  else if (t.type == lexer::token::e_lsqrbracket) stack_.push(std::make_pair(']',t.position));
-                  else if (exprtk::details::is_right_bracket(c))
-                  {
-                     if (stack_.empty())
-                     {
-                        state_ = false;
-                        error_token_ = t;
-
-                        return false;
-                     }
-                     else if (c != stack_.top().first)
-                     {
-                        state_ = false;
-                        error_token_ = t;
-
-                        return false;
-                     }
-                     else
-                        stack_.pop();
-                  }
-               }
-
-               return true;
+            
+            inline void release()
+            {
+                branch_deletable_ = false;
             }
-
-         private:
-
-            bool state_;
-            std::stack<std::pair<char,std::size_t> > stack_;
-            lexer::token error_token_;
-         };
-
-         class numeric_checker : public lexer::token_scanner
-         {
-         public:
-
-            numeric_checker()
-            : token_scanner (1),
-              current_index_(0)
+            
+        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>*)
             {}
-
-            bool result()
-            {
-               return error_list_.empty();
+        };
+        
+        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));
+                }
             }
-
-            void reset()
+        };
+        
+        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)
+                    {
+                        delete branch[i].first;
+                        branch[i].first = 0;
+                    }
+                }
+            }
+            
+            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)
+                    {
+                        delete branch[i].first;
+                        branch[i].first = 0;
+                    }
+                }
+            }
+        };
+        
+        template <typename T>
+        class binary_node : public expression_node<T>
+        {
+        public:
+            
+            typedef expression_node<T>* expression_ptr;
+            typedef std::pair<expression_ptr,bool> branch_t;
+            
+            binary_node(const operator_type& opr,
+                        expression_ptr branch0,
+                        expression_ptr branch1)
+            : operation_(opr)
+            {
+                init_branches<2>(branch_,branch0,branch1);
+            }
+            
+            ~binary_node()
+            {
+                cleanup_branches::execute<T,2>(branch_);
+            }
+            
+            inline T value() const
+            {
+                const T arg0 = branch_[0].first->value();
+                const T arg1 = branch_[1].first->value();
+                return numeric::process<T>(operation_,arg0,arg1);
+            }
+            
+            inline typename expression_node<T>::node_type type() const
+            {
+                return expression_node<T>::e_binary;
+            }
+            
+            inline operator_type operation()
+            {
+                return operation_;
+            }
+            
+            inline expression_node<T>* branch(const std::size_t& index = 0) const
+            {
+                if (0 == index)
+                    return branch_[0].first;
+                else if (1 == index)
+                    return branch_[1].first;
+                else
+                    return reinterpret_cast<expression_ptr>(0);
+            }
+            
+        protected:
+            
+            operator_type operation_;
+            branch_t branch_[2];
+        };
+        
+        template <typename T, typename Operation>
+        class binary_ext_node : public expression_node<T>
+        {
+        public:
+            
+            typedef expression_node<T>* expression_ptr;
+            typedef std::pair<expression_ptr,bool> branch_t;
+            
+            binary_ext_node(expression_ptr branch0, expression_ptr branch1)
             {
-               error_list_.clear();
-               current_index_ = 0;
+                init_branches<2>(branch_,branch0,branch1);
             }
-
-            bool operator()(const lexer::token& t)
+            
+            ~binary_ext_node()
             {
-               if (token::e_number == t.type)
-               {
-                  double v;
-
-                  if (!exprtk::details::string_to_real(t.value,v))
-                  {
-                     error_list_.push_back(current_index_);
-                  }
-               }
-
-               ++current_index_;
-
-               return true;
+                cleanup_branches::execute<T,2>(branch_);
             }
-
-            std::size_t error_count() const
+            
+            inline T value() const
             {
-               return error_list_.size();
+                const T arg0 = branch_[0].first->value();
+                const T arg1 = branch_[1].first->value();
+                
+                return Operation::process(arg0,arg1);
             }
-
-            std::size_t error_index(const std::size_t& i)
+            
+            inline typename expression_node<T>::node_type type() const
             {
-               if (i < error_list_.size())
-                  return error_list_[i];
-               else
-                  return std::numeric_limits<std::size_t>::max();
+                return expression_node<T>::e_binary_ext;
             }
-
-            void clear_errors()
+            
+            inline operator_type operation()
             {
-               error_list_.clear();
+                return Operation::operation();
             }
-
-         private:
-
-            std::size_t current_index_;
-            std::vector<std::size_t> error_list_;
-         };
-
-         class symbol_replacer : public lexer::token_modifier
-         {
-         private:
-
-            typedef std::map<std::string,std::pair<std::string,token::token_type>,details::ilesscompare> replace_map_t;
-
-         public:
-
-            bool remove(const std::string& target_symbol)
+            
+            inline expression_node<T>* branch(const std::size_t& index = 0) const
             {
-               replace_map_t::iterator itr = replace_map_.find(target_symbol);
-
-               if (replace_map_.end() == itr)
-                  return false;
-
-               replace_map_.erase(itr);
-
-               return true;
+                if (0 == index)
+                    return branch_[0].first;
+                else if (1 == index)
+                    return branch_[1].first;
+                else
+                    return reinterpret_cast<expression_ptr>(0);
             }
-
-            bool add_replace(const std::string& target_symbol,
-                             const std::string& replace_symbol,
-                             const lexer::token::token_type token_type = lexer::token::e_symbol)
+            
+        protected:
+            
+            branch_t branch_[2];
+        };
+        
+        template <typename T>
+        class trinary_node : public expression_node<T>
+        {
+        public:
+            
+            typedef expression_node<T>* expression_ptr;
+            typedef std::pair<expression_ptr,bool> branch_t;
+            
+            trinary_node(const operator_type& opr,
+                         expression_ptr branch0,
+                         expression_ptr branch1,
+                         expression_ptr branch2)
+            : operation_(opr)
+            {
+                init_branches<3>(branch_,branch0,branch1,branch2);
+            }
+            
+            ~trinary_node()
+            {
+                cleanup_branches::execute<T,3>(branch_);
+            }
+            
+            inline T value() const
+            {
+                const T arg0 = branch_[0].first->value();
+                const T arg1 = branch_[1].first->value();
+                const T arg2 = branch_[2].first->value();
+                
+                switch (operation_)
+                {
+                    case e_inrange : return (arg1 < arg0) ? T(0) : ((arg1 > arg2) ? T(0) : T(1));
+                        
+                    case e_clamp   : return (arg1 < arg0) ? arg0 : (arg1 > arg2 ? arg2 : arg1);
+                        
+                    case e_iclamp  : if ((arg1 <= arg0) || (arg1 >= arg2))
+                        return arg1;
+                    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();
+                    }
+                }
+            }
+            
+            inline typename expression_node<T>::node_type type() const
+            {
+                return expression_node<T>::e_trinary;
+            }
+            
+        protected:
+            
+            operator_type operation_;
+            branch_t branch_[3];
+        };
+        
+        template <typename T>
+        class quaternary_node : public expression_node<T>
+        {
+        public:
+            
+            typedef expression_node<T>* expression_ptr;
+            typedef std::pair<expression_ptr,bool> branch_t;
+            
+            quaternary_node(const operator_type& opr,
+                            expression_ptr branch0,
+                            expression_ptr branch1,
+                            expression_ptr branch2,
+                            expression_ptr branch3)
+            : operation_(opr)
             {
-               replace_map_t::iterator itr = replace_map_.find(target_symbol);
-
-               if (replace_map_.end() != itr)
-               {
-                  return false;
-               }
-
-               replace_map_[target_symbol] = std::make_pair(replace_symbol,token_type);
-
-               return true;
+                init_branches<4>(branch_,branch0,branch1,branch2,branch3);
             }
-
-            void clear()
+            
+            ~quaternary_node()
             {
-               replace_map_.clear();
+                cleanup_branches::execute<T,4>(branch_);
             }
-
-         private:
-
-            bool modify(lexer::token& t)
+            
+            inline T value() const
             {
-               if (lexer::token::e_symbol == t.type)
-               {
-                  if (replace_map_.empty())
-                     return false;
-
-                  replace_map_t::iterator itr = replace_map_.find(t.value);
-
-                  if (replace_map_.end() != itr)
-                  {
-                     t.value = itr->second.first;
-                     t.type  = itr->second.second;
-
-                     return true;
-                  }
-               }
-
-               return false;
+                return std::numeric_limits<T>::quiet_NaN();
             }
-
-            replace_map_t replace_map_;
-         };
-
-         class sequence_validator : public lexer::token_scanner
-         {
-         private:
-
-            typedef std::pair<lexer::token::token_type,lexer::token::token_type> token_pair_t;
-            typedef std::set<token_pair_t> set_t;
-
-         public:
-
-            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_string ,lexer::token::e_colon  );
-               add_invalid(lexer::token::e_string ,lexer::token::e_ternary);
-               add_invalid(lexer::token::e_colon  ,lexer::token::e_string );
-               add_invalid(lexer::token::e_ternary,lexer::token::e_string );
-               add_invalid_set1(lexer::token::e_assign );
-               add_invalid_set1(lexer::token::e_shr    );
-               add_invalid_set1(lexer::token::e_shl    );
-               add_invalid_set1(lexer::token::e_lte    );
-               add_invalid_set1(lexer::token::e_ne     );
-               add_invalid_set1(lexer::token::e_gte    );
-               add_invalid_set1(lexer::token::e_lt     );
-               add_invalid_set1(lexer::token::e_gt     );
-               add_invalid_set1(lexer::token::e_eq     );
-               add_invalid_set1(lexer::token::e_comma  );
-               add_invalid_set1(lexer::token::e_add    );
-               add_invalid_set1(lexer::token::e_sub    );
-               add_invalid_set1(lexer::token::e_div    );
-               add_invalid_set1(lexer::token::e_mul    );
-               add_invalid_set1(lexer::token::e_mod    );
-               add_invalid_set1(lexer::token::e_pow    );
-               add_invalid_set1(lexer::token::e_colon  );
-               add_invalid_set1(lexer::token::e_ternary);
+            
+            inline typename expression_node<T>::node_type type() const
+            {
+                return expression_node<T>::e_quaternary;
             }
-
-            bool result()
+            
+        protected:
+            
+            operator_type operation_;
+            branch_t branch_[4];
+        };
+        
+        template <typename T>
+        class conditional_node : public expression_node<T>
+        {
+        public:
+            
+            typedef expression_node<T>* expression_ptr;
+            
+            conditional_node(expression_ptr test,
+                             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_       ) delete test_;
+                if (consequent_  && consequent_deletable_ ) delete consequent_;
+                if (alternative_ && alternative_deletable_) delete alternative_;
+            }
+            
+            inline T value() const
+            {
+                if (is_true(test_))
+                    return consequent_->value();
+                else
+                    return alternative_->value();
+            }
+            
+            inline typename expression_node<T>::node_type type() const
+            {
+                return expression_node<T>::e_conditional;
+            }
+            
+        private:
+            
+            expression_ptr test_;
+            expression_ptr consequent_;
+            expression_ptr alternative_;
+            bool test_deletable_;
+            bool consequent_deletable_;
+            bool alternative_deletable_;
+        };
+        
+        template <typename T>
+        class cons_conditional_node : public expression_node<T>
+        {
+        public:
+            
+            // Consequent only conditional statement node
+            typedef expression_node<T>* expression_ptr;
+            
+            cons_conditional_node(expression_ptr test,
+                                  expression_ptr consequent)
+            : test_(test),
+            consequent_(consequent),
+            test_deletable_(branch_deletable(test_)),
+            consequent_deletable_(branch_deletable(consequent_))
+            {}
+            
+            ~cons_conditional_node()
             {
-               return error_list_.empty();
+                if (test_       && test_deletable_      ) delete test_;
+                if (consequent_ && consequent_deletable_) delete consequent_;
             }
-
-            bool operator()(const lexer::token& t0, const lexer::token& t1)
+            
+            inline T value() const
             {
-               set_t::value_type p = std::make_pair(t0.type,t1.type);
-
-               if (invalid_bracket_check(t0.type,t1.type))
-               {
-                  error_list_.push_back(std::make_pair(t0,t1));
-               }
-               else if (invalid_comb_.find(p) != invalid_comb_.end())
-               {
-                  error_list_.push_back(std::make_pair(t0,t1));
-               }
-
-               return true;
+                if (is_true(test_))
+                    return consequent_->value();
+                else
+                    return std::numeric_limits<T>::quiet_NaN();
             }
-
-            std::size_t error_count()
+            
+            inline typename expression_node<T>::node_type type() const
             {
-               return error_list_.size();
+                return expression_node<T>::e_conditional;
             }
-
-            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);
-               }
+            
+        private:
+            
+            expression_ptr test_;
+            expression_ptr consequent_;
+            bool test_deletable_;
+            bool consequent_deletable_;
+        };
+        
+#ifndef exprtk_disable_break_continue
+        template <typename T>
+        class break_exception
+        {
+        public:
+            
+            break_exception(const T& v)
+            : value(v)
+            {}
+            
+            T value;
+        };
+        
+        class continue_exception
+        {};
+        
+        template <typename T>
+        class break_node : public expression_node<T>
+        {
+        public:
+            
+            typedef expression_node<T>* expression_ptr;
+            
+            break_node(expression_ptr ret = expression_ptr(0))
+            : return_(ret),
+            return_deletable_(branch_deletable(return_))
+            {}
+            
+            ~break_node()
+            {
+                if (return_deletable_)
+                {
+                    delete return_;
+                }
             }
-
-            void clear_errors()
+            
+            inline T value() const
             {
-               error_list_.clear();
+                throw break_exception<T>(return_ ? return_->value() : std::numeric_limits<T>::quiet_NaN());
+#ifndef _MSC_VER
+                return std::numeric_limits<T>::quiet_NaN();
+#endif
             }
-
-         private:
-
-            void add_invalid(lexer::token::token_type base, lexer::token::token_type t)
+            
+            inline typename expression_node<T>::node_type type() const
             {
-               invalid_comb_.insert(std::make_pair(base,t));
+                return expression_node<T>::e_break;
             }
-
-            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 );
+            
+        private:
+            
+            expression_ptr return_;
+            bool return_deletable_;
+        };
+        
+        template <typename T>
+        class continue_node : public expression_node<T>
+        {
+        public:
+            
+            inline T value() const
+            {
+                throw continue_exception();
+#ifndef _MSC_VER
+                return std::numeric_limits<T>::quiet_NaN();
+#endif
             }
-
-            bool invalid_bracket_check(lexer::token::token_type base, lexer::token::token_type t)
-            {
-               if (details::is_right_bracket(static_cast<char>(base)))
-               {
-                  switch (t)
-                  {
-                     case lexer::token::e_assign : return (']' != base);
-                     case lexer::token::e_string : return true;
-                     default                     : return false;
-                  }
-               }
-               else if (details::is_left_bracket(static_cast<char>(base)))
-               {
-                  if (details::is_right_bracket(static_cast<char>(t)))
-                     return false;
-                  else if (details::is_left_bracket(static_cast<char>(t)))
-                     return false;
-                  else
-                  {
-                     switch (t)
-                     {
-                        case lexer::token::e_number  : return false;
-                        case lexer::token::e_symbol  : return false;
-                        case lexer::token::e_string  : return false;
-                        case lexer::token::e_add     : return false;
-                        case lexer::token::e_sub     : return false;
-                        case lexer::token::e_colon   : return false;
-                        case lexer::token::e_ternary : return false;
-                        default                      : return true;
-                     }
-                  }
-               }
-               else if (details::is_right_bracket(static_cast<char>(t)))
-               {
-                  switch (base)
-                  {
-                     case lexer::token::e_number  : return false;
-                     case lexer::token::e_symbol  : return false;
-                     case lexer::token::e_string  : return false;
-                     case lexer::token::e_eof     : return false;
-                     case lexer::token::e_colon   : return false;
-                     case lexer::token::e_ternary : return false;
-                     default                      : return true;
-                  }
-               }
-               else if (details::is_left_bracket(static_cast<char>(t)))
-               {
-                  switch (base)
-                  {
-                     case lexer::token::e_rbracket    : return true;
-                     case lexer::token::e_rsqrbracket : return true;
-                     case lexer::token::e_rcrlbracket : return true;
-                     default                          : return false;
-                  }
-               }
-
-               return false;
+            
+            inline typename expression_node<T>::node_type type() const
+            {
+                return expression_node<T>::e_break;
             }
-
-            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)
-            {
-               if (token_scanner_list.end() != std::find(token_scanner_list.begin(),
-                                                         token_scanner_list.end(),
-                                                         scanner))
-               {
-                  return false;
-               }
-
-               token_scanner_list.push_back(scanner);
-               return true;
+        };
+#endif
+        
+        template <typename T>
+        class while_loop_node : public expression_node<T>
+        {
+        public:
+            
+            typedef expression_node<T>* expression_ptr;
+            
+            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()
+            {
+                if (condition_ && condition_deletable_)
+                {
+                    delete condition_;
+                }
+                
+                if (loop_body_ && loop_body_deletable_)
+                {
+                    delete loop_body_;
+                }
+            }
+            
+            inline T value() const
+            {
+                T result = T(0);
+                
+                while (is_true(condition_))
+                {
+                    result = loop_body_->value();
+                }
+                
+                return result;
+            }
+            
+            inline typename expression_node<T>::node_type type() const
+            {
+                return expression_node<T>::e_while;
+            }
+            
+        private:
+            
+            expression_ptr condition_;
+            expression_ptr loop_body_;
+            bool condition_deletable_;
+            bool loop_body_deletable_;
+        };
+        
+        template <typename T>
+        class repeat_until_loop_node : public expression_node<T>
+        {
+        public:
+            
+            typedef expression_node<T>* expression_ptr;
+            
+            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()
+            {
+                if (condition_ && condition_deletable_)
+                {
+                    delete condition_;
+                }
+                
+                if (loop_body_ && loop_body_deletable_)
+                {
+                    delete loop_body_;
+                }
+            }
+            
+            inline T value() const
+            {
+                T result = T(0);
+                
+                do
+                {
+                    result = loop_body_->value();
+                }
+                while (is_false(condition_));
+                
+                return result;
+            }
+            
+            inline typename expression_node<T>::node_type type() const
+            {
+                return expression_node<T>::e_repeat;
+            }
+            
+        private:
+            
+            expression_ptr condition_;
+            expression_ptr loop_body_;
+            bool condition_deletable_;
+            bool loop_body_deletable_;
+        };
+        
+        template <typename T>
+        class for_loop_node : public expression_node<T>
+        {
+        public:
+            
+            typedef expression_node<T>* expression_ptr;
+            
+            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()
+            {
+                if (initialiser_ && initialiser_deletable_)
+                {
+                    delete initialiser_;
+                }
+                
+                if (condition_ && condition_deletable_)
+                {
+                    delete condition_;
+                }
+                
+                if (incrementor_ && incrementor_deletable_)
+                {
+                    delete incrementor_;
+                }
+                
+                if (loop_body_ && loop_body_deletable_)
+                {
+                    delete loop_body_;
+                }
+            }
+            
+            inline T value() const
+            {
+                T result = T(0);
+                
+                if (initialiser_)
+                    initialiser_->value();
+                
+                if (incrementor_)
+                {
+                    while (is_true(condition_))
+                    {
+                        result = loop_body_->value();
+                        incrementor_->value();
+                    }
+                }
+                else
+                {
+                    while (is_true(condition_))
+                    {
+                        result = loop_body_->value();
+                    }
+                }
+                
+                return result;
+            }
+            
+            inline typename expression_node<T>::node_type type() const
+            {
+                return expression_node<T>::e_for;
+            }
+            
+        private:
+            
+            expression_ptr initialiser_;
+            expression_ptr condition_  ;
+            expression_ptr incrementor_;
+            expression_ptr loop_body_  ;
+            bool initialiser_deletable_;
+            bool condition_deletable_  ;
+            bool incrementor_deletable_;
+            bool loop_body_deletable_  ;
+        };
+        
+#ifndef exprtk_disable_break_continue
+        template <typename T>
+        class while_loop_bc_node : public expression_node<T>
+        {
+        public:
+            
+            typedef expression_node<T>* expression_ptr;
+            
+            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()
+            {
+                if (condition_ && condition_deletable_)
+                {
+                    delete condition_;
+                }
+                
+                if (loop_body_ && loop_body_deletable_)
+                {
+                    delete loop_body_;
+                }
+            }
+            
+            inline T value() const
+            {
+                T result = T(0);
+                while (is_true(condition_))
+                {
+                    try
+                    {
+                        result = loop_body_->value();
+                    }
+                    catch(const break_exception<T>& e)
+                    {
+                        return e.value;
+                    }
+                    catch(const continue_exception&)
+                    {}
+                }
+                return result;
+            }
+            
+            inline typename expression_node<T>::node_type type() const
+            {
+                return expression_node<T>::e_while;
+            }
+            
+        private:
+            
+            expression_ptr condition_;
+            expression_ptr loop_body_;
+            bool condition_deletable_;
+            bool loop_body_deletable_;
+        };
+        
+        template <typename T>
+        class repeat_until_loop_bc_node : public expression_node<T>
+        {
+        public:
+            
+            typedef expression_node<T>* expression_ptr;
+            
+            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()
+            {
+                if (condition_ && condition_deletable_)
+                {
+                    delete condition_;
+                }
+                
+                if (loop_body_ && loop_body_deletable_)
+                {
+                    delete loop_body_;
+                }
+            }
+            
+            inline T value() const
+            {
+                T result = T(0);
+                
+                do
+                {
+                    try
+                    {
+                        result = loop_body_->value();
+                    }
+                    catch(const break_exception<T>& e)
+                    {
+                        return e.value;
+                    }
+                    catch(const continue_exception&)
+                    {}
+                }
+                while (is_false(condition_));
+                
+                return result;
+            }
+            
+            inline typename expression_node<T>::node_type type() const
+            {
+                return expression_node<T>::e_repeat;
+            }
+            
+        private:
+            
+            expression_ptr condition_;
+            expression_ptr loop_body_;
+            bool condition_deletable_;
+            bool loop_body_deletable_;
+        };
+        
+        template <typename T>
+        class for_loop_bc_node : public expression_node<T>
+        {
+        public:
+            
+            typedef expression_node<T>* expression_ptr;
+            
+            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()
+            {
+                if (initialiser_ && initialiser_deletable_)
+                {
+                    delete initialiser_;
+                }
+                
+                if (condition_ && condition_deletable_)
+                {
+                    delete condition_;
+                }
+                
+                if (incrementor_ && incrementor_deletable_)
+                {
+                    delete incrementor_;
+                }
+                
+                if (loop_body_ && loop_body_deletable_)
+                {
+                    delete loop_body_;
+                }
+            }
+            
+            inline T value() const
+            {
+                T result = T(0);
+                
+                if (initialiser_)
+                    initialiser_->value();
+                
+                if (incrementor_)
+                {
+                    while (is_true(condition_))
+                    {
+                        try
+                        {
+                            result = loop_body_->value();
+                        }
+                        catch(const break_exception<T>& e)
+                        {
+                            return e.value;
+                        }
+                        catch(const continue_exception&)
+                        {}
+                        
+                        incrementor_->value();
+                    }
+                }
+                else
+                {
+                    while (is_true(condition_))
+                    {
+                        try
+                        {
+                            result = loop_body_->value();
+                        }
+                        catch(const break_exception<T>& e)
+                        {
+                            return e.value;
+                        }
+                        catch(const continue_exception&)
+                        {}
+                    }
+                }
+                
+                return result;
+            }
+            
+            inline typename expression_node<T>::node_type type() const
+            {
+                return expression_node<T>::e_for;
+            }
+            
+        private:
+            
+            expression_ptr initialiser_;
+            expression_ptr condition_  ;
+            expression_ptr incrementor_;
+            expression_ptr loop_body_  ;
+            bool initialiser_deletable_;
+            bool condition_deletable_  ;
+            bool incrementor_deletable_;
+            bool loop_body_deletable_  ;
+        };
+#endif
+        
+        template <typename T>
+        class switch_node : public expression_node<T>
+        {
+        public:
+            
+            typedef expression_node<T>* expression_ptr;
+            
+            template <typename Allocator,
+            template <typename,typename> class Sequence>
+            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);
+                    }
+                    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])
+                    {
+                        delete arg_list_[i];
+                        arg_list_[i] = 0;
+                    }
+                }
+            }
+            
+            inline T value() const
+            {
+                if (!arg_list_.empty())
+                {
+                    const std::size_t upper_bound = (arg_list_.size() - 1);
+                    
+                    for (std::size_t i = 0; i < upper_bound; i += 2)
+                    {
+                        expression_ptr condition  = arg_list_[i    ];
+                        expression_ptr consequent = arg_list_[i + 1];
+                        
+                        if (is_true(condition))
+                        {
+                            return consequent->value();
+                        }
+                    }
+                    
+                    return arg_list_[upper_bound]->value();
+                }
+                else
+                    return std::numeric_limits<T>::quiet_NaN();
+            }
+            
+            inline typename expression_node<T>::node_type type() const
+            {
+                return expression_node<T>::e_switch;
+            }
+            
+        protected:
+            
+            std::vector<expression_ptr> arg_list_;
+            std::vector<unsigned char> delete_branch_;
+        };
+        
+        template <typename T, typename Switch_N>
+        class switch_n_node : public switch_node<T>
+        {
+        public:
+            
+            typedef expression_node<T>* expression_ptr;
+            
+            template <typename Allocator,
+            template <typename,typename> class Sequence>
+            switch_n_node(const Sequence<expression_ptr,Allocator>& arg_list)
+            : switch_node<T>(arg_list)
+            {}
+            
+            inline T value() const
+            {
+                return Switch_N::process(switch_node<T>::arg_list_);
             }
-
-            inline bool register_modifier(lexer::token_modifier* modifier)
-            {
-               if (token_modifier_list.end() != std::find(token_modifier_list.begin(),
-                                                          token_modifier_list.end(),
-                                                          modifier))
-               {
-                  return false;
-               }
-
-               token_modifier_list.push_back(modifier);
-               return true;
+        };
+        
+        template <typename T>
+        class multi_switch_node : public expression_node<T>
+        {
+        public:
+            
+            typedef expression_node<T>* expression_ptr;
+            
+            template <typename Allocator,
+            template <typename,typename> class Sequence>
+            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);
+                    }
+                    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])
+                    {
+                        delete arg_list_[i];
+                        arg_list_[i] = 0;
+                    }
+                }
+            }
+            
+            inline T value() const
+            {
+                T result = T(0);
+                
+                if (arg_list_.empty())
+                {
+                    return std::numeric_limits<T>::quiet_NaN();
+                }
+                
+                const std::size_t upper_bound = (arg_list_.size() - 1);
+                
+                for (std::size_t i = 0; i < upper_bound; i += 2)
+                {
+                    expression_ptr condition  = arg_list_[i    ];
+                    expression_ptr consequent = arg_list_[i + 1];
+                    
+                    if (is_true(condition))
+                    {
+                        result = consequent->value();
+                    }
+                }
+                
+                return result;
+            }
+            
+            inline typename expression_node<T>::node_type type() const
+            {
+                return expression_node<T>::e_mswitch;
+            }
+            
+        private:
+            
+            std::vector<expression_ptr> arg_list_;
+            std::vector<unsigned char> delete_branch_;
+        };
+        
+        template <typename T>
+        class ivariable
+        {
+        public:
+            
+            virtual ~ivariable()
+            {}
+            
+            virtual T& ref() = 0;
+            virtual const T& ref() const = 0;
+        };
+        
+        template <typename T>
+        class variable_node : public expression_node<T>,
+        public ivariable      <T>
+        {
+        public:
+            
+            static T null_value;
+            
+            explicit variable_node()
+            : value_(&null_value),
+            delete_value_(false)
+            {}
+            
+            variable_node(T& v)
+            : value_(&v),
+            delete_value_(false)
+            {}
+            
+            ~variable_node()
+            {
+                if (delete_value_)
+                {
+                    delete value_;
+                }
             }
-
-            inline bool register_joiner(lexer::token_joiner* joiner)
-            {
-               if (token_joiner_list.end() != std::find(token_joiner_list.begin(),
-                                                        token_joiner_list.end(),
-                                                        joiner))
-               {
-                  return false;
-               }
-
-               token_joiner_list.push_back(joiner);
-               return true;
+            
+            inline bool operator <(const variable_node<T>& v) const
+            {
+                return this < (&v);
             }
-
-            inline bool register_inserter(lexer::token_inserter* inserter)
-            {
-               if (token_inserter_list.end() != std::find(token_inserter_list.begin(),
-                                                          token_inserter_list.end(),
-                                                          inserter))
-               {
-                  return false;
-               }
-
-               token_inserter_list.push_back(inserter);
-               return true;
+            
+            inline T value() const
+            {
+                return (*value_);
             }
-
-            inline bool run_modifiers(lexer::generator& g)
+            
+            inline T& ref()
             {
-               error_token_modifier = reinterpret_cast<lexer::token_modifier*>(0);
-               bool result = true;
-
-               for (std::size_t i = 0; i < token_modifier_list.size(); ++i)
-               {
-                  lexer::token_modifier& modifier = (*token_modifier_list[i]);
-
-                  modifier.reset();
-                  modifier.process(g);
-
-                  if (!modifier.result())
-                  {
-                     error_token_modifier = token_modifier_list[i];
-                     return false;
-                  }
-               }
-
-               return result;
+                return (*value_);
             }
-
-            inline bool run_joiners(lexer::generator& g)
+            
+            inline const T& ref() const
             {
-               error_token_joiner = reinterpret_cast<lexer::token_joiner*>(0);
-               bool result = true;
-
-               for (std::size_t i = 0; i < token_joiner_list.size(); ++i)
-               {
-                  lexer::token_joiner& joiner = (*token_joiner_list[i]);
-
-                  joiner.reset();
-                  joiner.process(g);
-
-                  if (!joiner.result())
-                  {
-                     error_token_joiner = token_joiner_list[i];
-                     return false;
-                  }
-               }
-
-               return result;
+                return (*value_);
             }
-
-            inline bool run_inserters(lexer::generator& g)
+            
+            inline typename expression_node<T>::node_type type() const
             {
-               error_token_inserter = reinterpret_cast<lexer::token_inserter*>(0);
-               bool result = true;
-
-               for (std::size_t i = 0; i < token_inserter_list.size(); ++i)
-               {
-                  lexer::token_inserter& inserter = (*token_inserter_list[i]);
-
-                  inserter.reset();
-                  inserter.process(g);
-
-                  if (!inserter.result())
-                  {
-                     error_token_inserter = token_inserter_list[i];
-                     return false;
-                  }
-               }
-
-               return result;
+                return expression_node<T>::e_variable;
             }
-
-            inline bool run_scanners(lexer::generator& g)
+            
+            inline bool& delete_value()
             {
-               error_token_scanner = reinterpret_cast<lexer::token_scanner*>(0);
-               bool result = true;
-
-               for (std::size_t i = 0; i < token_scanner_list.size(); ++i)
-               {
-                  lexer::token_scanner& scanner = (*token_scanner_list[i]);
-
-                  scanner.reset();
-                  scanner.process(g);
-
-                  if (!scanner.result())
-                  {
-                     error_token_scanner = token_scanner_list[i];
-                     return false;
-                  }
-               }
-
-               return result;
+                return delete_value_;
             }
-
-            std::vector<lexer::token_scanner*>  token_scanner_list;
-            std::vector<lexer::token_modifier*> token_modifier_list;
-            std::vector<lexer::token_joiner*>   token_joiner_list;
-            std::vector<lexer::token_inserter*> token_inserter_list;
-
-            lexer::token_scanner*  error_token_scanner;
-            lexer::token_modifier* error_token_modifier;
-            lexer::token_joiner*   error_token_joiner;
-            lexer::token_inserter* error_token_inserter;
-         };
-      }
-   }
-
-   template <typename T>
-   struct type_store
-   {
-      enum store_type
-      {
-         e_unknown,
-         e_scalar,
-         e_vector,
-         e_string
-      };
-
-      type_store()
-      : size(0),
-        data(0),
-        type(e_unknown)
-      {}
-
-      std::size_t size;
-      void*       data;
-      store_type  type;
-
-      class parameter_list
-      {
-      public:
-
-         parameter_list(std::vector<type_store>& pl)
-         : parameter_list_(pl)
-         {}
-
-         inline bool empty() const
-         {
-            return parameter_list_.empty();
-         }
-
-         inline std::size_t size() const
-         {
-            return parameter_list_.size();
-         }
-
-         inline type_store& operator[](const std::size_t& index)
-         {
-            return parameter_list_[index];
-         }
-
-         inline const type_store& operator[](const std::size_t& index) const
-         {
-            return parameter_list_[index];
-         }
-
-         inline type_store& front()
-         {
-            return parameter_list_[0];
-         }
-
-         inline const type_store& front() const
-         {
-            return parameter_list_[0];
-         }
-
-         inline type_store& back()
-         {
-            return parameter_list_[size() - 1];
-         }
-
-         inline const type_store& back() const
-         {
-            return parameter_list_[size() - 1];
-         }
-
-      private:
-
-         std::vector<type_store>& parameter_list_;
-      };
-
-      template <typename ViewType>
-      struct type_view
-      {
-         typedef type_store<T> type_store_t;
-         typedef ViewType      value_t;
-
-         type_view(type_store_t& ts)
-         : ts_(ts),
-           data_(reinterpret_cast<value_t*>(ts_.data))
-         {}
-
-         inline std::size_t size() const
-         {
-            return ts_.size;
-         }
-
-         inline value_t& operator[](const std::size_t& i)
-         {
-            return data_[i];
-         }
-
-         inline const value_t& operator[](const std::size_t& i) const
-         {
-            return data_[i];
-         }
-
-         inline const value_t* begin() const { return data_; }
-         inline       value_t* begin()       { return data_; }
-
-         inline const value_t* end() const   { return data_ + ts_.size; }
-         inline       value_t* end()         { return data_ + ts_.size; }
-
-         type_store_t& ts_;
-         value_t* data_;
-      };
-
-      typedef type_view<T>    vector_view;
-      typedef type_view<char> string_view;
-
-      struct scalar_view
-      {
-         typedef type_store<T> type_store_t;
-         typedef T value_t;
-
-         scalar_view(type_store_t& ts)
-         : v_(*reinterpret_cast<value_t*>(ts.data))
-         {}
-
-         value_t& operator()()
-         {
-            return v_;
-         }
-
-         const value_t& operator()() const
-         {
-            return v_;
-         }
-
-         T& v_;
-      };
-   };
-
-   template <typename StringView>
-   inline std::string to_str(const StringView& view)
-   {
-      return std::string(view.begin(),view.size());
-   }
-
-   namespace details
-   {
-      enum operator_type
-      {
-         e_default , e_null    , e_add     , e_sub     ,
-         e_mul     , e_div     , e_mod     , e_pow     ,
-         e_atan2   , e_min     , e_max     , e_avg     ,
-         e_sum     , e_prod    , e_lt      , e_lte     ,
-         e_eq      , e_equal   , e_ne      , e_nequal  ,
-         e_gte     , e_gt      , e_and     , e_nand    ,
-         e_or      , e_nor     , e_xor     , e_xnor    ,
-         e_mand    , e_mor     , e_scand   , e_scor    ,
-         e_shr     , e_shl     , 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_logn    ,
-         e_neg     , e_pos     , e_round   , e_roundn  ,
-         e_root    , e_sqrt    , e_sin     , e_sinc    ,
-         e_sinh    , e_sec     , e_csc     , e_tan     ,
-         e_tanh    , e_cot     , e_clamp   , e_iclamp  ,
-         e_inrange , e_sgn     , e_r2d     , e_d2r     ,
-         e_d2g     , e_g2d     , e_hypot   , e_notl    ,
-         e_erf     , e_erfc    , e_ncdf    , e_frac    ,
-         e_trunc   , e_assign  , e_addass  , e_subass  ,
-         e_mulass  , e_divass  , e_modass  , e_in      ,
-         e_like    , e_ilike   , e_multi   , e_swap    ,
-
-         // Do not add new functions/operators after this point.
-         e_sf00 = 1000, e_sf01 = 1001, e_sf02 = 1002, e_sf03 = 1003,
-         e_sf04 = 1004, e_sf05 = 1005, e_sf06 = 1006, e_sf07 = 1007,
-         e_sf08 = 1008, e_sf09 = 1009, e_sf10 = 1010, e_sf11 = 1011,
-         e_sf12 = 1012, e_sf13 = 1013, e_sf14 = 1014, e_sf15 = 1015,
-         e_sf16 = 1016, e_sf17 = 1017, e_sf18 = 1018, e_sf19 = 1019,
-         e_sf20 = 1020, e_sf21 = 1021, e_sf22 = 1022, e_sf23 = 1023,
-         e_sf24 = 1024, e_sf25 = 1025, e_sf26 = 1026, e_sf27 = 1027,
-         e_sf28 = 1028, e_sf29 = 1029, e_sf30 = 1030, e_sf31 = 1031,
-         e_sf32 = 1032, e_sf33 = 1033, e_sf34 = 1034, e_sf35 = 1035,
-         e_sf36 = 1036, e_sf37 = 1037, e_sf38 = 1038, e_sf39 = 1039,
-         e_sf40 = 1040, e_sf41 = 1041, e_sf42 = 1042, e_sf43 = 1043,
-         e_sf44 = 1044, e_sf45 = 1045, e_sf46 = 1046, e_sf47 = 1047,
-         e_sf48 = 1048, e_sf49 = 1049, e_sf50 = 1050, e_sf51 = 1051,
-         e_sf52 = 1052, e_sf53 = 1053, e_sf54 = 1054, e_sf55 = 1055,
-         e_sf56 = 1056, e_sf57 = 1057, e_sf58 = 1058, e_sf59 = 1059,
-         e_sf60 = 1060, e_sf61 = 1061, e_sf62 = 1062, e_sf63 = 1063,
-         e_sf64 = 1064, e_sf65 = 1065, e_sf66 = 1066, e_sf67 = 1067,
-         e_sf68 = 1068, e_sf69 = 1069, e_sf70 = 1070, e_sf71 = 1071,
-         e_sf72 = 1072, e_sf73 = 1073, e_sf74 = 1074, e_sf75 = 1075,
-         e_sf76 = 1076, e_sf77 = 1077, e_sf78 = 1078, e_sf79 = 1079,
-         e_sf80 = 1080, e_sf81 = 1081, e_sf82 = 1082, e_sf83 = 1083,
-         e_sf84 = 1084, e_sf85 = 1085, e_sf86 = 1086, e_sf87 = 1087,
-         e_sf88 = 1088, e_sf89 = 1089, e_sf90 = 1090, e_sf91 = 1091,
-         e_sf92 = 1092, e_sf93 = 1093, e_sf94 = 1094, e_sf95 = 1095,
-         e_sf96 = 1096, e_sf97 = 1097, e_sf98 = 1098, e_sf99 = 1099,
-         e_sffinal  = 1100,
-         e_sf4ext00 = 2000, e_sf4ext01 = 2001, e_sf4ext02 = 2002, e_sf4ext03 = 2003,
-         e_sf4ext04 = 2004, e_sf4ext05 = 2005, e_sf4ext06 = 2006, e_sf4ext07 = 2007,
-         e_sf4ext08 = 2008, e_sf4ext09 = 2009, e_sf4ext10 = 2010, e_sf4ext11 = 2011,
-         e_sf4ext12 = 2012, e_sf4ext13 = 2013, e_sf4ext14 = 2014, e_sf4ext15 = 2015,
-         e_sf4ext16 = 2016, e_sf4ext17 = 2017, e_sf4ext18 = 2018, e_sf4ext19 = 2019,
-         e_sf4ext20 = 2020, e_sf4ext21 = 2021, e_sf4ext22 = 2022, e_sf4ext23 = 2023,
-         e_sf4ext24 = 2024, e_sf4ext25 = 2025, e_sf4ext26 = 2026, e_sf4ext27 = 2027,
-         e_sf4ext28 = 2028, e_sf4ext29 = 2029, e_sf4ext30 = 2030, e_sf4ext31 = 2031,
-         e_sf4ext32 = 2032, e_sf4ext33 = 2033, e_sf4ext34 = 2034, e_sf4ext35 = 2035,
-         e_sf4ext36 = 2036, e_sf4ext37 = 2037, e_sf4ext38 = 2038, e_sf4ext39 = 2039,
-         e_sf4ext40 = 2040, e_sf4ext41 = 2041, e_sf4ext42 = 2042, e_sf4ext43 = 2043,
-         e_sf4ext44 = 2044, e_sf4ext45 = 2045, e_sf4ext46 = 2046, e_sf4ext47 = 2047,
-         e_sf4ext48 = 2048, e_sf4ext49 = 2049, e_sf4ext50 = 2050, e_sf4ext51 = 2051,
-         e_sf4ext52 = 2052, e_sf4ext53 = 2053, e_sf4ext54 = 2054, e_sf4ext55 = 2055,
-         e_sf4ext56 = 2056, e_sf4ext57 = 2057, e_sf4ext58 = 2058, e_sf4ext59 = 2059
-      };
-
-      struct base_operation_t
-      {
-         base_operation_t(const operator_type t, const unsigned int& np)
-         : type(t),
-           num_params(np)
-         {}
-
-         operator_type type;
-         unsigned int num_params;
-      };
-
-      namespace numeric
-      {
-         namespace details
-         {
-            template <typename T>
-            inline T process_impl(const operator_type operation, const T arg)
-            {
-               switch (operation)
-               {
-                  case e_abs   : return numeric::abs  (arg);
-                  case e_acos  : return numeric::acos (arg);
-                  case e_acosh : return numeric::acosh(arg);
-                  case e_asin  : return numeric::asin (arg);
-                  case e_asinh : return numeric::asinh(arg);
-                  case e_atan  : return numeric::atan (arg);
-                  case e_atanh : return numeric::atanh(arg);
-                  case e_ceil  : return numeric::ceil (arg);
-                  case e_cos   : return numeric::cos  (arg);
-                  case e_cosh  : return numeric::cosh (arg);
-                  case e_exp   : return numeric::exp  (arg);
-                  case e_expm1 : return numeric::expm1(arg);
-                  case e_floor : return numeric::floor(arg);
-                  case e_log   : return numeric::log  (arg);
-                  case e_log10 : return numeric::log10(arg);
-                  case e_log2  : return numeric::log2 (arg);
-                  case e_log1p : return numeric::log1p(arg);
-                  case e_neg   : return numeric::neg  (arg);
-                  case e_pos   : return numeric::pos  (arg);
-                  case e_round : return numeric::round(arg);
-                  case e_sin   : return numeric::sin  (arg);
-                  case e_sinc  : return numeric::sinc (arg);
-                  case e_sinh  : return numeric::sinh (arg);
-                  case e_sqrt  : return numeric::sqrt (arg);
-                  case e_tan   : return numeric::tan  (arg);
-                  case e_tanh  : return numeric::tanh (arg);
-                  case e_cot   : return numeric::cot  (arg);
-                  case e_sec   : return numeric::sec  (arg);
-                  case e_csc   : return numeric::csc  (arg);
-                  case e_r2d   : return numeric::r2d  (arg);
-                  case e_d2r   : return numeric::d2r  (arg);
-                  case e_d2g   : return numeric::d2g  (arg);
-                  case e_g2d   : return numeric::g2d  (arg);
-                  case e_notl  : return numeric::notl (arg);
-                  case e_sgn   : return numeric::sgn  (arg);
-                  case e_erf   : return numeric::erf  (arg);
-                  case e_erfc  : return numeric::erfc (arg);
-                  case e_ncdf  : return numeric::ncdf (arg);
-                  case e_frac  : return numeric::frac (arg);
-                  case e_trunc : return numeric::trunc(arg);
-                  default      : return std::numeric_limits<T>::quiet_NaN();
-               }
+            
+        private:
+            
+            T* value_;
+            bool delete_value_;
+        };
+        
+        template <typename T>
+        T variable_node<T>::null_value = T(std::numeric_limits<T>::quiet_NaN());
+        
+        template <typename T>
+        struct range_pack
+        {
+            typedef expression_node<T>*           expression_node_ptr;
+            typedef std::pair<std::size_t,std::size_t> cached_range_t;
+            
+            range_pack()
+            : n0_e (std::make_pair(false,expression_node_ptr(0))),
+            n1_e (std::make_pair(false,expression_node_ptr(0))),
+            n0_c (std::make_pair(false,0)),
+            n1_c (std::make_pair(false,0)),
+            cache(std::make_pair(0,0))
+            {}
+            
+            void clear()
+            {
+                n0_e  = std::make_pair(false,expression_node_ptr(0));
+                n1_e  = std::make_pair(false,expression_node_ptr(0));
+                n0_c  = std::make_pair(false,0);
+                n1_c  = std::make_pair(false,0);
+                cache = std::make_pair(0,0);
+            }
+            
+            void free()
+            {
+                if (n0_e.first && n0_e.second)
+                {
+                    n0_e.first = false;
+                    
+                    if (
+                        !is_variable_node(n0_e.second) &&
+                        !is_string_node  (n0_e.second)
+                        )
+                    {
+                        delete n0_e.second;
+                        n0_e.second = expression_node_ptr(0);
+                    }
+                }
+                
+                if (n1_e.first && n1_e.second)
+                {
+                    n1_e.first = false;
+                    
+                    if (
+                        !is_variable_node(n1_e.second) &&
+                        !is_string_node  (n1_e.second)
+                        )
+                    {
+                        delete n1_e.second;
+                        n1_e.second = expression_node_ptr(0);
+                    }
+                }
+            }
+            
+            bool const_range()
+            {
+                return ( n0_c.first &&  n1_c.first) &&
+                (!n0_e.first && !n1_e.first);
+            }
+            
+            bool var_range()
+            {
+                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
+            {
+                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));
+                }
+                else
+                    return false;
+                
+                if (n1_c.first)
+                    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));
+                }
+                else
+                    return false;
+                
+                if (
+                    (std::numeric_limits<std::size_t>::max() != size) &&
+                    (std::numeric_limits<std::size_t>::max() == r1  )
+                    )
+                {
+                    r1 = size - 1;
+                }
+                
+                cache.first  = r0;
+                cache.second = r1;
+                
+                return (r0 <= r1);
+            }
+            
+            inline std::size_t const_size() const
+            {
+                return (n1_c.second - n0_c.second + 1);
+            }
+            
+            inline std::size_t cache_size() const
+            {
+                return (cache.second - cache.first + 1);
+            }
+            
+            std::pair<bool,expression_node_ptr> n0_e;
+            std::pair<bool,expression_node_ptr> n1_e;
+            std::pair<bool,std::size_t        > n0_c;
+            std::pair<bool,std::size_t        > n1_c;
+            mutable cached_range_t             cache;
+        };
+        
+        template <typename T>
+        class string_base_node;
+        
+        template <typename T>
+        struct range_data_type
+        {
+            typedef range_pack<T> range_t;
+            typedef string_base_node<T>* strbase_ptr_t;
+            
+            range_data_type()
+            : range(0),
+            data (0),
+            size (0),
+            type_size(0),
+            str_node (0)
+            {}
+            
+            range_t*      range;
+            void*         data;
+            std::size_t   size;
+            std::size_t   type_size;
+            strbase_ptr_t str_node;
+        };
+        
+        template <typename T> class vector_node;
+        
+        template <typename T>
+        class vector_interface
+        {
+        public:
+            
+            typedef vector_node<T>*   vector_node_ptr;
+            typedef vec_data_store<T>           vds_t;
+            
+            virtual ~vector_interface()
+            {}
+            
+            virtual std::size_t size   () const = 0;
+            
+            virtual vector_node_ptr vec() const = 0;
+            
+            virtual vector_node_ptr vec()       = 0;
+            
+            virtual       vds_t& vds   ()       = 0;
+            
+            virtual const vds_t& vds   () const = 0;
+            
+            virtual bool side_effect   () const { return false; }
+        };
+        
+        template <typename T>
+        class vector_node : public expression_node <T>,
+        public vector_interface<T>
+        {
+        public:
+            
+            typedef expression_node<T>*  expression_ptr;
+            typedef vector_holder<T>    vector_holder_t;
+            typedef vector_node<T>*     vector_node_ptr;
+            typedef vec_data_store<T>             vds_t;
+            
+            vector_node(vector_holder_t* vh)
+            : vector_holder_(vh),
+            vds_((*vector_holder_).size(),(*vector_holder_)[0])
+            {
+                vector_holder_->set_ref(&vds_.ref());
+            }
+            
+            vector_node(const vds_t& vds, vector_holder_t* vh)
+            : vector_holder_(vh),
+            vds_(vds)
+            {}
+            
+            inline T value() const
+            {
+                return vds().data()[0];
             }
-
-            template <typename T>
-            inline T process_impl(const operator_type operation, const T arg0, const T arg1)
-            {
-               switch (operation)
-               {
-                  case e_add    : return (arg0 + arg1);
-                  case e_sub    : return (arg0 - arg1);
-                  case e_mul    : return (arg0 * arg1);
-                  case e_div    : return (arg0 / arg1);
-                  case e_mod    : return modulus<T>(arg0,arg1);
-                  case e_pow    : return pow<T>(arg0,arg1);
-                  case e_atan2  : return atan2<T>(arg0,arg1);
-                  case e_min    : return std::min<T>(arg0,arg1);
-                  case e_max    : return std::max<T>(arg0,arg1);
-                  case e_logn   : return logn<T>(arg0,arg1);
-                  case e_lt     : return (arg0 <  arg1) ? T(1) : T(0);
-                  case e_lte    : return (arg0 <= arg1) ? T(1) : T(0);
-                  case e_eq     : return std::equal_to<T>()(arg0,arg1) ? T(1) : T(0);
-                  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_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_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_equal  : return equal<T>   (arg0,arg1);
-                  case e_nequal : return nequal<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       : return std::numeric_limits<T>::quiet_NaN();
-               }
+            
+            vector_node_ptr vec() const
+            {
+                return const_cast<vector_node_ptr>(this);
             }
-
-            template <typename T>
-            inline T process_impl(const operator_type operation, const T arg0, const T arg1, int_type_tag)
-            {
-               switch (operation)
-               {
-                  case e_add    : return (arg0 + arg1);
-                  case e_sub    : return (arg0 - arg1);
-                  case e_mul    : return (arg0 * arg1);
-                  case e_div    : return (arg0 / arg1);
-                  case e_mod    : return arg0 % arg1;
-                  case e_pow    : return pow<T>(arg0,arg1);
-                  case e_min    : return std::min<T>(arg0,arg1);
-                  case e_max    : return std::max<T>(arg0,arg1);
-                  case e_logn   : return logn<T>(arg0,arg1);
-                  case e_lt     : return (arg0 <  arg1) ? T(1) : T(0);
-                  case e_lte    : return (arg0 <= arg1) ? T(1) : T(0);
-                  case e_eq     : return (arg0 == arg1) ? T(1) : T(0);
-                  case e_ne     : return (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 ((arg0 != T(0)) && (arg1 != T(0))) ? T(1) : T(0);
-                  case e_nand   : return ((arg0 != T(0)) && (arg1 != T(0))) ? T(0) : T(1);
-                  case e_or     : return ((arg0 != T(0)) || (arg1 != T(0))) ? T(1) : T(0);
-                  case e_nor    : return ((arg0 != T(0)) || (arg1 != T(0))) ? T(0) : T(1);
-                  case e_xor    : return arg0 ^ arg1;
-                  case e_xnor   : return !(arg0 ^ arg1);
-                  case e_root   : return root<T>(arg0,arg1);
-                  case e_equal  : return arg0 == arg1;
-                  case e_nequal : return arg0 != arg1;
-                  case e_hypot  : return hypot<T>(arg0,arg1);
-                  case e_shr    : return arg0 >> arg1;
-                  case e_shl    : return arg0 << arg1;
-                  default       : return std::numeric_limits<T>::quiet_NaN();
-               }
-            }
-         }
-
-         template <typename T>
-         inline T process(const operator_type operation, const T arg)
-         {
-            return exprtk::details::numeric::details::process_impl(operation,arg);
-         }
-
-         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);
-         }
-      }
-
-      template <typename T>
-      class expression_node
-      {
-      public:
-
-         enum node_type
-         {
-            e_none         , e_null         , e_constant     , e_unary        ,
-            e_binary       , e_binary_ext   , e_trinary      , e_quaternary   ,
-            e_quinary      , e_senary       , e_vararg       , e_conditional  ,
-            e_while        , e_repeat       , e_for          , e_switch       ,
-            e_mswitch      , e_variable     , e_stringvar    , e_stringconst  ,
-            e_stringvarrng , e_cstringvarrng, e_strgenrange  , e_strconcat    ,
-            e_stringvarsize, e_strswap      , e_stringsize   , e_function     ,
-            e_vafunction   , e_genfunction  , e_strfunction  , 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_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;
-
-         virtual ~expression_node()
-         {}
-
-         inline virtual T value() const
-         {
-            return std::numeric_limits<T>::quiet_NaN();
-         }
-
-         inline virtual expression_node<T>* branch(const std::size_t& index = 0) const
-         {
-            return reinterpret_cast<expression_ptr>(index * 0);
-         }
-
-         inline virtual node_type type() const
-         {
-            return e_none;
-         }
-      };
-
-      template <typename T>
-      inline bool is_generally_string_node(const expression_node<T>* node);
-
-      inline bool is_true(const double v)
-      {
-         return std::not_equal_to<double>()(0.0,v);
-      }
-
-      inline bool is_true(const long double v)
-      {
-         return std::not_equal_to<long double>()(0.0L,v);
-      }
-
-      inline bool is_true(const float v)
-      {
-         return std::not_equal_to<float>()(0.0f,v);
-      }
-
-      template <typename T>
-      inline bool is_true(const expression_node<T>* node)
-      {
-         return std::not_equal_to<T>()(T(0),node->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_unary_node(const expression_node<T>* node)
-      {
-         return node && (details::expression_node<T>::e_unary == node->type());
-      }
-
-      template <typename T>
-      inline bool is_neg_unary_node(const expression_node<T>* node)
-      {
-         return node && (details::expression_node<T>::e_neg == node->type());
-      }
-
-      template <typename T>
-      inline bool is_binary_node(const expression_node<T>* node)
-      {
-         return node && (details::expression_node<T>::e_binary == node->type());
-      }
-
-      template <typename T>
-      inline bool is_variable_node(const expression_node<T>* node)
-      {
-         return node && (details::expression_node<T>::e_variable == node->type());
-      }
-
-      template <typename T>
-      inline bool is_ivariable_node(const expression_node<T>* node)
-      {
-         return node &&
-                (
-                  details::expression_node<T>::e_variable == node->type() ||
-                  details::expression_node<T>::e_vecelem  == node->type()
-                );
-      }
-
-      template <typename T>
-      inline bool is_vector_elem_node(const expression_node<T>* node)
-      {
-         return node && (details::expression_node<T>::e_vecelem == node->type());
-      }
-
-      template <typename T>
-      inline bool is_vector_node(const expression_node<T>* node)
-      {
-         return node && (details::expression_node<T>::e_vector == node->type());
-      }
-
-      template <typename T>
-      inline bool is_ivector_node(const expression_node<T>* node)
-      {
-         if (node)
-         {
-            switch (node->type())
-            {
-               case details::expression_node<T>::e_vector      :
-               case details::expression_node<T>::e_vecvalass   :
-               case details::expression_node<T>::e_vecvecass   :
-               case details::expression_node<T>::e_vecopvalass :
-               case details::expression_node<T>::e_vecopvecass :
-               case details::expression_node<T>::e_vecvecswap  :
-               case details::expression_node<T>::e_vecvecarith :
-               case details::expression_node<T>::e_vecvalarith :
-               case details::expression_node<T>::e_valvecarith :
-               case details::expression_node<T>::e_vecunaryop  : return true;
-               default                                         : return false;
-            }
-         }
-         else
-            return false;
-      }
-
-      template <typename T>
-      inline bool is_constant_node(const expression_node<T>* node)
-      {
-         return node && (details::expression_node<T>::e_constant == node->type());
-      }
-
-      template <typename T>
-      inline bool is_null_node(const expression_node<T>* node)
-      {
-         return node && (details::expression_node<T>::e_null == node->type());
-      }
-
-      template <typename T>
-      inline bool is_break_node(const expression_node<T>* node)
-      {
-         return node && (details::expression_node<T>::e_break == node->type());
-      }
-
-      template <typename T>
-      inline bool is_continue_node(const expression_node<T>* node)
-      {
-         return node && (details::expression_node<T>::e_continue == node->type());
-      }
-
-      template <typename T>
-      inline bool is_swap_node(const expression_node<T>* node)
-      {
-         return node && (details::expression_node<T>::e_swap == node->type());
-      }
-
-      template <typename T>
-      inline bool is_function(const expression_node<T>* node)
-      {
-         return node && (details::expression_node<T>::e_function == node->type());
-      }
-
-      template <typename T> class unary_node;
-
-      template <typename T>
-      inline bool is_negate_node(const expression_node<T>* node)
-      {
-         if (node && is_unary_node(node))
-         {
-            return (details::e_neg == static_cast<const unary_node<T>*>(node)->operation());
-         }
-         else
-            return false;
-      }
-
-      template <typename T>
-      inline bool branch_deletable(expression_node<T>* node)
-      {
-         return !is_variable_node(node) &&
-                !is_string_node  (node) ;
-      }
-
-      template <std::size_t N, typename T>
-      inline bool all_nodes_valid(expression_node<T>* (&b)[N])
-      {
-         for (std::size_t i = 0; i < N; ++i)
-         {
-            if (0 == b[i]) return false;
-         }
-
-         return true;
-      }
-
-      template <typename T,
-                typename Allocator,
-                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)
-         {
-            if (0 == b[i]) return false;
-         }
-
-         return true;
-      }
-
-      template <std::size_t N, typename T>
-      inline bool all_nodes_variables(expression_node<T>* (&b)[N])
-      {
-         for (std::size_t i = 0; i < N; ++i)
-         {
-            if (0 == b[i])
-               return false;
-            else if (!is_variable_node(b[i]))
-               return false;
-         }
-
-         return true;
-      }
-
-      template <typename T,
-                typename Allocator,
-                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)
-         {
-            if (0 == b[i])
-               return false;
-            else if (!is_variable_node(b[i]))
-               return false;
-         }
-
-         return true;
-      }
-
-      template <typename NodeAllocator, typename T, std::size_t N>
-      inline void free_all_nodes(NodeAllocator& node_allocator, expression_node<T>* (&b)[N])
-      {
-         for (std::size_t i = 0; i < N; ++i)
-         {
-            free_node(node_allocator,b[i]);
-         }
-      }
-
-      template <typename NodeAllocator,
-                typename T,
-                typename Allocator,
-                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)
-         {
-            free_node(node_allocator,b[i]);
-         }
-
-         b.clear();
-      }
-
-      template <typename NodeAllocator, typename T>
-      inline void free_node(NodeAllocator& node_allocator, expression_node<T>*& node, const bool force_delete = false)
-      {
-         if (0 != node)
-         {
-            if (
-                 (is_variable_node(node) || is_string_node(node)) ||
-                 force_delete
-               )
-               return;
-
-            node_allocator.free(node);
-            node = 0;
-         }
-      }
-
-      template <typename Type>
-      class vector_holder
-      {
-      private:
-
-         typedef Type value_type;
-         typedef value_type* value_ptr;
-         typedef const value_ptr const_value_ptr;
-
-         class vector_holder_base
-         {
-         public:
-
-            virtual ~vector_holder_base(){}
-
-            inline value_ptr operator[](const std::size_t& index) const
+            
+            vector_node_ptr vec()
             {
-               return value_at(index);
+                return this;
             }
-
-            inline std::size_t size() const
+            
+            inline typename expression_node<T>::node_type type() const
             {
-               return vector_size();
+                return expression_node<T>::e_vector;
             }
-
-         protected:
-
-            virtual value_ptr value_at(const std::size_t&) const = 0;
-            virtual std::size_t vector_size()              const = 0;
-         };
-
-         class array_vector_impl : public vector_holder_base
-         {
-         public:
-
-            array_vector_impl(const Type* vec, const std::size_t& vec_size)
-            : vec_(vec),
-              size_(vec_size)
+            
+            std::size_t size() const
+            {
+                return vds().size();
+            }
+            
+            vds_t& vds()
+            {
+                return vds_;
+            }
+            
+            const vds_t& vds() const
+            {
+                return vds_;
+            }
+            
+            inline vector_holder_t& vec_holder()
+            {
+                return (*vector_holder_);
+            }
+            
+        private:
+            
+            vector_holder_t* vector_holder_;
+            vds_t                      vds_;
+        };
+        
+        template <typename T>
+        class vector_elem_node : public expression_node<T>,
+        public ivariable      <T>
+        {
+        public:
+            
+            typedef expression_node<T>* expression_ptr;
+            typedef vector_holder<T>    vector_holder_t;
+            typedef vector_holder_t*    vector_holder_ptr;
+            
+            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_))
             {}
-
-         protected:
-
-            value_ptr value_at(const std::size_t& index) const
+            
+            ~vector_elem_node()
             {
-               if (index < size_)
-                  return const_cast<const_value_ptr>(vec_ + index);
-               else
-                  return const_value_ptr(0);
+                if (index_ && index_deletable_)
+                {
+                    delete index_;
+                }
             }
-
-            std::size_t vector_size() const
+            
+            inline T value() const
             {
-               return size_;
+                return *(vector_base_ + static_cast<std::size_t>(details::numeric::to_int64(index_->value())));
             }
-
-         private:
-
-            array_vector_impl operator=(const array_vector_impl&);
-
-            const Type* vec_;
+            
+            inline T& ref()
+            {
+                return *(vector_base_ + static_cast<std::size_t>(details::numeric::to_int64(index_->value())));
+            }
+            
+            inline const T& ref() const
+            {
+                return *(vector_base_ + static_cast<std::size_t>(details::numeric::to_int64(index_->value())));
+            }
+            
+            inline typename expression_node<T>::node_type type() const
+            {
+                return expression_node<T>::e_vecelem;
+            }
+            
+            inline vector_holder_t& vec_holder()
+            {
+                return (*vec_holder_);
+            }
+            
+        private:
+            
+            expression_ptr index_;
+            vector_holder_ptr vec_holder_;
+            T* vector_base_;
+            bool index_deletable_;
+        };
+        
+        template <typename T>
+        class rebasevector_elem_node : public expression_node<T>,
+        public ivariable      <T>
+        {
+        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;
+            
+            rebasevector_elem_node(expression_ptr index, vector_holder_ptr vec_holder)
+            : index_(index),
+            index_deletable_(branch_deletable(index_)),
+            vector_holder_(vec_holder),
+            vds_((*vector_holder_).size(),(*vector_holder_)[0])
+            {
+                vector_holder_->set_ref(&vds_.ref());
+            }
+            
+            ~rebasevector_elem_node()
+            {
+                if (index_ && index_deletable_)
+                {
+                    delete index_;
+                }
+            }
+            
+            inline T value() const
+            {
+                return *(vds_.data() + static_cast<std::size_t>(details::numeric::to_int64(index_->value())));
+            }
+            
+            inline T& ref()
+            {
+                return *(vds_.data() + static_cast<std::size_t>(details::numeric::to_int64(index_->value())));
+            }
+            
+            inline const T& ref() const
+            {
+                return *(vds_.data() + static_cast<std::size_t>(details::numeric::to_int64(index_->value())));
+            }
+            
+            inline typename expression_node<T>::node_type type() const
+            {
+                return expression_node<T>::e_rbvecelem;
+            }
+            
+            inline vector_holder_t& vec_holder()
+            {
+                return (*vector_holder_);
+            }
+            
+        private:
+            
+            expression_ptr index_;
+            bool index_deletable_;
+            vector_holder_ptr vector_holder_;
+            vds_t             vds_;
+        };
+        
+        template <typename T>
+        class rebasevector_celem_node : public expression_node<T>,
+        public ivariable      <T>
+        {
+        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;
+            
+            rebasevector_celem_node(const std::size_t index, vector_holder_ptr vec_holder)
+            : index_(index),
+            vector_holder_(vec_holder),
+            vds_((*vector_holder_).size(),(*vector_holder_)[0])
+            {
+                vector_holder_->set_ref(&vds_.ref());
+            }
+            
+            inline T value() const
+            {
+                return *(vds_.data() + index_);
+            }
+            
+            inline T& ref()
+            {
+                return *(vds_.data() + index_);
+            }
+            
+            inline const T& ref() const
+            {
+                return *(vds_.data() + index_);
+            }
+            
+            inline typename expression_node<T>::node_type type() const
+            {
+                return expression_node<T>::e_rbveccelem;
+            }
+            
+            inline vector_holder_t& vec_holder()
+            {
+                return (*vector_holder_);
+            }
+            
+        private:
+            
+            std::size_t index_;
+            vector_holder_ptr vector_holder_;
+            vds_t vds_;
+        };
+        
+        template <typename T>
+        class vector_assignment_node : public expression_node<T>
+        {
+        public:
+            
+            typedef expression_node<T>* expression_ptr;
+            
+            vector_assignment_node(T* vector_base,
+                                   const std::size_t& size,
+                                   const std::vector<expression_ptr>& initialiser_list,
+                                   const bool single_value_initialse)
+            : vector_base_(vector_base),
+            initialiser_list_(initialiser_list),
+            size_(size),
+            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]))
+                    {
+                        delete initialiser_list_[i];
+                    }
+                }
+            }
+            
+            inline T value() const
+            {
+                if (single_value_initialse_)
+                {
+                    for (std::size_t i = 0; i < size_; ++i)
+                    {
+                        *(vector_base_ + i) = initialiser_list_[0]->value();
+                    }
+                }
+                else
+                {
+                    std::size_t il_size = initialiser_list_.size();
+                    
+                    for (std::size_t i = 0; i < il_size; ++i)
+                    {
+                        *(vector_base_ + i) = initialiser_list_[i]->value();
+                    }
+                    
+                    if (il_size < size_)
+                    {
+                        for (std::size_t i = il_size; i < size_; ++i)
+                        {
+                            *(vector_base_ + i) = T(0);
+                        }
+                    }
+                }
+                
+                return *(vector_base_);
+            }
+            
+            inline typename expression_node<T>::node_type type() const
+            {
+                return expression_node<T>::e_vecdefass;
+            }
+            
+        private:
+            
+            vector_assignment_node<T>& operator=(const vector_assignment_node<T>&);
+            
+            mutable T* vector_base_;
+            std::vector<expression_ptr> initialiser_list_;
             const std::size_t size_;
-         };
-
-         template <typename Allocator,
-                   template <typename,typename> class Sequence>
-         class sequence_vector_impl : public vector_holder_base
-         {
-         public:
-
-            typedef Sequence<Type,Allocator> sequence_t;
-
-            sequence_vector_impl(sequence_t& seq)
-            : sequence_(seq)
+            const bool single_value_initialse_;
+        };
+        
+        template <typename T>
+        class swap_node : public expression_node<T>
+        {
+        public:
+            
+            typedef expression_node<T>* expression_ptr;
+            typedef variable_node<T>*   variable_node_ptr;
+            
+            swap_node(variable_node_ptr var0, variable_node_ptr var1)
+            : var0_(var0),
+            var1_(var1)
             {}
-
-         protected:
-
-            value_ptr value_at(const std::size_t& index) const
+            
+            inline T value() const
             {
-               return (index < sequence_.size()) ? (&sequence_[index]) : const_value_ptr(0);
+                std::swap(var0_->ref(),var1_->ref());
+                return var1_->ref();
             }
-
-            std::size_t vector_size() const
+            
+            inline typename expression_node<T>::node_type type() const
             {
-               return sequence_.size();
+                return expression_node<T>::e_swap;
             }
-
-         private:
-
-            sequence_vector_impl operator=(const sequence_vector_impl&);
-
-            sequence_t& sequence_;
-         };
-
-      public:
-
-         vector_holder(Type* vec, const std::size_t& vec_size)
-         : vector_holder_base_(new(buffer)array_vector_impl(vec,vec_size))
-         {}
-
-         template <typename Allocator>
-         vector_holder(std::vector<Type,Allocator>& vec)
-         : vector_holder_base_(new(buffer)sequence_vector_impl<Allocator,std::vector>(vec))
-         {}
-
-         template <typename Allocator>
-         vector_holder(std::deque<Type,Allocator>& deq)
-         : vector_holder_base_(new(buffer)sequence_vector_impl<Allocator,std::deque>(deq))
-         {}
-
-         inline value_ptr operator[](const std::size_t& index) const
-         {
-            return (*vector_holder_base_)[index];
-         }
-
-         inline std::size_t size() const
-         {
-            return vector_holder_base_->size();
-         }
-
-      private:
-
-         mutable vector_holder_base* vector_holder_base_;
-         unsigned char buffer[64];
-      };
-
-      template <typename T>
-      class null_node : public expression_node<T>
-      {
-      public:
-
-         inline T value() const
-         {
-            return std::numeric_limits<T>::quiet_NaN();
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_null;
-         }
-      };
-
-      template <typename T>
-      class null_eq_node : public expression_node<T>
-      {
-      public:
-
-         typedef expression_node<T>* expression_ptr;
-
-         null_eq_node(expression_ptr brnch, const bool equality = true)
-         : branch_(brnch),
-           branch_deletable_(branch_deletable(branch_)),
-           equality_(equality)
-         {}
-
-        ~null_eq_node()
-         {
-            if (branch_ && branch_deletable_)
+            
+        private:
+            
+            variable_node_ptr var0_;
+            variable_node_ptr var1_;
+        };
+        
+        template <typename T>
+        class swap_generic_node : public binary_node<T>
+        {
+        public:
+            
+            typedef expression_node<T>* expression_ptr;
+            typedef ivariable<T>* ivariable_ptr;
+            
+            swap_generic_node(expression_ptr var0, expression_ptr var1)
+            : binary_node<T>(details::e_swap,var0,var1),
+            var0_(dynamic_cast<ivariable_ptr>(var0)),
+            var1_(dynamic_cast<ivariable_ptr>(var1))
+            {}
+            
+            inline T value() const
             {
-               delete branch_;
-               branch_ = 0;
+                std::swap(var0_->ref(),var1_->ref());
+                return var1_->ref();
             }
-         }
-
-         inline T value() const
-         {
-            const T v = branch_->value();
-            const bool result = details::numeric::is_nan(v);
-
-            if (result)
-               return (equality_) ? T(1) : T(0);
-            else
-               return (equality_) ? T(0) : T(1);
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_nulleq;
-         }
-
-         inline operator_type operation() const
-         {
-            return details::e_eq;
-         }
-
-         inline expression_node<T>* branch(const std::size_t&) const
-         {
-            return branch_;
-         }
-
-      private:
-
-         expression_ptr branch_;
-         bool branch_deletable_;
-         bool equality_;
-      };
-
-      template <typename T>
-      class literal_node : public expression_node<T>
-      {
-      public:
-
-         explicit literal_node(const T& v)
-         : value_(v)
-         {}
-
-         inline T value() const
-         {
-            return value_;
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_constant;
-         }
-
-         inline expression_node<T>* branch(const std::size_t&) const
-         {
-            return reinterpret_cast<expression_node<T>*>(0);
-         }
-
-      private:
-
-         literal_node(literal_node<T>&) {}
-         literal_node<T>& operator=(literal_node<T>&) { return *this; }
-
-         const T value_;
-      };
-
-      template <typename T>
-      struct range_pack;
-
-      template <typename T>
-      struct range_data_type;
-
-      template <typename T>
-      class range_interface
-      {
-      public:
-
-         typedef range_pack<T> range_t;
-
-         virtual range_t& range_ref() = 0;
-
-         virtual const range_t& range_ref() const = 0;
-      };
-
-      template <typename T>
-      class string_base_node
-      {
-      public:
-
-         typedef range_data_type<T> range_data_type_t;
-
-         virtual std::string str () const = 0;
-
-         virtual const char* base() const = 0;
-
-         virtual std::size_t size() const = 0;
-      };
-
-      template <typename T>
-      class string_literal_node : public expression_node <T>,
-                                  public string_base_node<T>,
-                                  public range_interface <T>
-      {
-      public:
-
-         typedef range_pack<T> range_t;
-
-         explicit string_literal_node(const std::string& v)
-         : value_(v)
-         {
-            rp_.n0_c = std::make_pair<bool,std::size_t>(true,0);
-            rp_.n1_c = std::make_pair<bool,std::size_t>(true,v.size() - 1);
-            rp_.cache.first  = rp_.n0_c.second;
-            rp_.cache.second = rp_.n1_c.second;
-         }
-
-         inline T value() const
-         {
-            return std::numeric_limits<T>::quiet_NaN();
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_stringconst;
-         }
-
-         inline expression_node<T>* branch(const std::size_t&) const
-         {
-            return reinterpret_cast<expression_node<T>*>(0);
-         }
-
-         std::string str() const
-         {
-            return value_;
-         }
-
-         const char* base() const
-         {
-           return value_.data();
-         }
-
-         std::size_t size() const
-         {
-            return value_.size();
-         }
-
-         range_t& range_ref()
-         {
-            return rp_;
-         }
-
-         const range_t& range_ref() const
-         {
-            return rp_;
-         }
-
-      private:
-
-         string_literal_node(const string_literal_node<T>&);
-         string_literal_node<T>& operator=(const string_literal_node<T>&);
-
-         const std::string value_;
-         range_t rp_;
-      };
-
-      template <typename T>
-      class unary_node : public expression_node<T>
-      {
-      public:
-
-         typedef expression_node<T>* expression_ptr;
-
-         unary_node(const operator_type& opr,
-                    expression_ptr brnch)
-         : operation_(opr),
-           branch_(brnch),
-           branch_deletable_(branch_deletable(branch_))
-         {}
-
-        ~unary_node()
-         {
-            if (branch_ && branch_deletable_)
+            
+            inline typename expression_node<T>::node_type type() const
             {
-               delete branch_;
-               branch_ = 0;
+                return expression_node<T>::e_swap;
             }
-         }
-
-         inline T value() const
-         {
-            const T arg = branch_->value();
-            return numeric::process<T>(operation_,arg);
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_unary;
-         }
-
-         inline operator_type operation() const
-         {
-            return operation_;
-         }
-
-         inline expression_node<T>* branch(const std::size_t&) const
-         {
-            return branch_;
-         }
-
-         inline void release()
-         {
-            branch_deletable_ = false;
-         }
-
-      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)
+            
+        private:
+            
+            ivariable_ptr var0_;
+            ivariable_ptr var1_;
+        };
+        
+        template <typename T>
+        class swap_vecvec_node : public binary_node     <T>,
+        public vector_interface<T>
+        {
+        public:
+            
+            typedef expression_node<T>*  expression_ptr;
+            typedef vector_node<T>*     vector_node_ptr;
+            typedef vec_data_store<T>             vds_t;
+            
+            swap_vecvec_node(expression_ptr branch0,
+                             expression_ptr branch1)
+            : binary_node<T>(details::e_swap,branch0,branch1),
+            vec0_node_ptr_(0),
+            vec1_node_ptr_(0),
+            vec_size_     (0),
+            initialised_  (false)
+            {
+                if (is_ivector_node(binary_node<T>::branch_[0].first))
+                {
+                    vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
+                    
+                    if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[0].first)))
+                    {
+                        vec0_node_ptr_ = vi->vec();
+                        vds()          = vi->vds();
+                    }
+                }
+                
+                if (is_ivector_node(binary_node<T>::branch_[1].first))
+                {
+                    vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
+                    
+                    if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
+                    {
+                        vec1_node_ptr_ = vi->vec();
+                    }
+                }
+                
+                if (vec0_node_ptr_ && vec1_node_ptr_)
+                {
+                    vec_size_ = std::min(vec0_node_ptr_->vds().size(),
+                                         vec1_node_ptr_->vds().size());
+                    
+                    initialised_ = true;
+                }
+            }
+            
+            inline T value() const
+            {
+                if (initialised_)
+                {
+                    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();
+                    
+                    for (std::size_t i = 0; i < vec_size_; ++i)
+                    {
+                        std::swap(vec0[i],vec1[i]);
+                    }
+                    
+                    return vec1_node_ptr_->value();
+                }
+                else
+                    return std::numeric_limits<T>::quiet_NaN();
+            }
+            
+            vector_node_ptr vec() const
+            {
+                return vec0_node_ptr_;
+            }
+            
+            vector_node_ptr vec()
+            {
+                return vec0_node_ptr_;
+            }
+            
+            inline typename expression_node<T>::node_type type() const
+            {
+                return expression_node<T>::e_vecvecswap;
+            }
+            
+            std::size_t size() const
+            {
+                return vec_size_;
+            }
+            
+            vds_t& vds()
+            {
+                return vds_;
+            }
+            
+            const vds_t& vds() const
+            {
+                return vds_;
+            }
+            
+        private:
+            
+            vector_node<T>* vec0_node_ptr_;
+            vector_node<T>* vec1_node_ptr_;
+            std::size_t     vec_size_;
+            bool            initialised_;
+            vds_t           vds_;
+        };
+        
+#ifndef exprtk_disable_string_capabilities
+        template <typename T>
+        class stringvar_node : public expression_node <T>,
+        public string_base_node<T>,
+        public range_interface <T>
+        {
+        public:
+            
+            typedef range_pack<T> range_t;
+            
+            static std::string null_value;
+            
+            explicit stringvar_node()
+            : value_(&null_value)
+            {}
+            
+            explicit stringvar_node(std::string& v)
+            : value_(&v)
             {
-               if (branch[i].first && branch[i].second)
-               {
-                  delete branch[i].first;
-                  branch[i].first = 0;
-               }
+                rp_.n0_c = std::make_pair<bool,std::size_t>(true,0);
+                rp_.n1_c = std::make_pair<bool,std::size_t>(true,v.size() - 1);
+                rp_.cache.first  = rp_.n0_c.second;
+                rp_.cache.second = rp_.n1_c.second;
             }
-         }
-
-         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)
-               {
-                  delete branch[i].first;
-                  branch[i].first = 0;
-               }
-            }
-         }
-      };
-
-      template <typename T>
-      class binary_node : public expression_node<T>
-      {
-      public:
-
-         typedef expression_node<T>* expression_ptr;
-         typedef std::pair<expression_ptr,bool> branch_t;
-
-         binary_node(const operator_type& opr,
-                     expression_ptr branch0,
-                     expression_ptr branch1)
-         : operation_(opr)
-         {
-            init_branches<2>(branch_,branch0,branch1);
-         }
-
-        ~binary_node()
-         {
-            cleanup_branches::execute<T,2>(branch_);
-         }
-
-         inline T value() const
-         {
-            const T arg0 = branch_[0].first->value();
-            const T arg1 = branch_[1].first->value();
-            return numeric::process<T>(operation_,arg0,arg1);
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_binary;
-         }
-
-         inline operator_type operation()
-         {
-            return operation_;
-         }
-
-         inline expression_node<T>* branch(const std::size_t& index = 0) const
-         {
-            if (0 == index)
-               return branch_[0].first;
-            else if (1 == index)
-               return branch_[1].first;
-            else
-               return reinterpret_cast<expression_ptr>(0);
-         }
-
-      protected:
-
-         operator_type operation_;
-         branch_t branch_[2];
-      };
-
-      template <typename T, typename Operation>
-      class binary_ext_node : public expression_node<T>
-      {
-      public:
-
-         typedef expression_node<T>* expression_ptr;
-         typedef std::pair<expression_ptr,bool> branch_t;
-
-         binary_ext_node(expression_ptr branch0, expression_ptr branch1)
-         {
-            init_branches<2>(branch_,branch0,branch1);
-         }
-
-        ~binary_ext_node()
-         {
-            cleanup_branches::execute<T,2>(branch_);
-         }
-
-         inline T value() const
-         {
-            const T arg0 = branch_[0].first->value();
-            const T arg1 = branch_[1].first->value();
-            return Operation::process(arg0,arg1);
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_binary_ext;
-         }
-
-         inline operator_type operation()
-         {
-            return Operation::operation();
-         }
-
-         inline expression_node<T>* branch(const std::size_t& index = 0) const
-         {
-            if (0 == index)
-               return branch_[0].first;
-            else if (1 == index)
-               return branch_[1].first;
-            else
-               return reinterpret_cast<expression_ptr>(0);
-         }
-
-      protected:
-
-         branch_t branch_[2];
-      };
-
-      template <typename T>
-      class trinary_node : public expression_node<T>
-      {
-      public:
-
-         typedef expression_node<T>* expression_ptr;
-         typedef std::pair<expression_ptr,bool> branch_t;
-
-         trinary_node(const operator_type& opr,
-                      expression_ptr branch0,
-                      expression_ptr branch1,
-                      expression_ptr branch2)
-         : operation_(opr)
-         {
-            init_branches<3>(branch_,branch0,branch1,branch2);
-         }
-
-        ~trinary_node()
-         {
-            cleanup_branches::execute<T,3>(branch_);
-         }
-
-         inline T value() const
-         {
-            const T arg0 = branch_[0].first->value();
-            const T arg1 = branch_[1].first->value();
-            const T arg2 = branch_[2].first->value();
-
-            switch (operation_)
-            {
-               case e_inrange : return (arg1 < arg0) ? T(0) : ((arg1 > arg2) ? T(0) : T(1));
-               case e_min     : return std::min<T>(std::min<T>(arg0,arg1),arg2);
-               case e_max     : return std::max<T>(std::max<T>(arg0,arg1),arg2);
-               case e_clamp   : return (arg1 < arg0) ? arg0 : (arg1 > arg2 ? arg2 : arg1);
-               case e_iclamp  : if ((arg1 <= arg0) || (arg1 >= arg2))
-                                   return arg1;
-                                else
-                                   return ((T(2) * arg1  <= (arg2 + arg0)) ? arg0 : arg2);
-               default        : return std::numeric_limits<T>::quiet_NaN();
-            }
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_trinary;
-         }
-
-      protected:
-
-         operator_type operation_;
-         branch_t branch_[3];
-      };
-
-      template <typename T>
-      class quaternary_node : public expression_node<T>
-      {
-      public:
-
-         typedef expression_node<T>* expression_ptr;
-         typedef std::pair<expression_ptr,bool> branch_t;
-
-         quaternary_node(const operator_type& opr,
-                         expression_ptr branch0,
-                         expression_ptr branch1,
-                         expression_ptr branch2,
-                         expression_ptr branch3)
-         : operation_(opr)
-         {
-            init_branches<4>(branch_,branch0,branch1,branch2,branch3);
-         }
-
-        ~quaternary_node()
-         {
-            cleanup_branches::execute<T,4>(branch_);
-         }
-
-         inline T value() const
-         {
-            const T arg0 = branch_[0].first->value();
-            const T arg1 = branch_[1].first->value();
-            const T arg2 = branch_[2].first->value();
-            const T arg3 = branch_[3].first->value();
-
-            switch (operation_)
+            
+            inline bool operator <(const stringvar_node<T>& v) const
             {
-               case e_min : return std::min<T>(std::min<T>(arg0,arg1),std::min<T>(arg2,arg3));
-               case e_max : return std::max<T>(std::max<T>(arg0,arg1),std::max<T>(arg2,arg3));
-               default    : return std::numeric_limits<T>::quiet_NaN();
+                return this < (&v);
             }
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_quaternary;
-         }
-
-      protected:
-
-         operator_type operation_;
-         branch_t branch_[4];
-      };
-
-      template <typename T>
-      class quinary_node : public expression_node<T>
-      {
-      public:
-
-         typedef expression_node<T>* expression_ptr;
-         typedef std::pair<expression_ptr,bool> branch_t;
-
-         quinary_node(const operator_type& opr,
-                      expression_ptr branch0,
-                      expression_ptr branch1,
-                      expression_ptr branch2,
-                      expression_ptr branch3,
-                      expression_ptr branch4)
-         : operation_(opr)
-         {
-            init_branches<5>(branch_,branch0,branch1,branch2,branch3,branch4);
-         }
-
-        ~quinary_node()
-         {
-            cleanup_branches::execute<T,5>(branch_);
-         }
-
-         inline T value() const
-         {
-            const T arg0 = branch_[0].first->value();
-            const T arg1 = branch_[1].first->value();
-            const T arg2 = branch_[2].first->value();
-            const T arg3 = branch_[3].first->value();
-            const T arg4 = branch_[4].first->value();
-
-            switch (operation_)
+            
+            inline T value() const
             {
-               case e_min  : return std::min<T>(std::min<T>(std::min<T>(arg0,arg1),std::min<T>(arg2,arg3)),arg4);
-               case e_max  : return std::max<T>(std::max<T>(std::max<T>(arg0,arg1),std::max<T>(arg2,arg3)),arg4);
-               default     : return std::numeric_limits<T>::quiet_NaN();
+                rp_.n1_c.second  = (*value_).size() - 1;
+                rp_.cache.second = rp_.n1_c.second;
+                return std::numeric_limits<T>::quiet_NaN();
             }
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_quinary;
-         }
-
-      private:
-
-         operator_type operation_;
-         branch_t branch_[5];
-      };
-
-      template <typename T>
-      class senary_node : public expression_node<T>
-      {
-      public:
-
-         typedef expression_node<T>* expression_ptr;
-         typedef std::pair<expression_ptr,bool> branch_t;
-
-         senary_node(const operator_type& opr,
-                     expression_ptr branch0,
-                     expression_ptr branch1,
-                     expression_ptr branch2,
-                     expression_ptr branch3,
-                     expression_ptr branch4,
-                     expression_ptr branch5)
-         : operation_(opr)
-         {
-            init_branches<6>(branch_,branch0,branch1,branch2,branch3,branch4,branch5);
-         }
-
-        ~senary_node()
-         {
-            cleanup_branches::execute<T,6>(branch_);
-         }
-
-         inline T value() const
-         {
-            const T arg0 = branch_[0].first->value();
-            const T arg1 = branch_[1].first->value();
-            const T arg2 = branch_[2].first->value();
-            const T arg3 = branch_[3].first->value();
-            const T arg4 = branch_[4].first->value();
-            const T arg5 = branch_[5].first->value();
-
-            switch (operation_)
+            
+            std::string str() const
             {
-               case e_min     : return std::min<T>(std::min<T>(std::min<T>(arg0,arg1),std::min<T>(arg2,arg3)),std::min<T>(arg4,arg5));
-               case e_max     : return std::max<T>(std::max<T>(std::max<T>(arg0,arg1),std::max<T>(arg2,arg3)),std::max<T>(arg4,arg5));
-               case e_default :
-               default        : return std::numeric_limits<T>::quiet_NaN();
+                return ref();
             }
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_senary;
-         }
-
-      private:
-
-         operator_type operation_;
-         branch_t branch_[6];
-      };
-
-      template <typename T>
-      class conditional_node : public expression_node<T>
-      {
-      public:
-
-         typedef expression_node<T>* expression_ptr;
-
-         conditional_node(expression_ptr test,
-                          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_       ) delete test_;
-            if (consequent_  && consequent_deletable_ ) delete consequent_;
-            if (alternative_ && alternative_deletable_) delete alternative_;
-         }
-
-         inline T value() const
-         {
-            if (is_true(test_))
-               return consequent_->value();
-            else
-               return alternative_->value();
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_conditional;
-         }
-
-      private:
-
-         expression_ptr test_;
-         expression_ptr consequent_;
-         expression_ptr alternative_;
-         bool test_deletable_;
-         bool consequent_deletable_;
-         bool alternative_deletable_;
-      };
-
-      template <typename T>
-      class cons_conditional_node : public expression_node<T>
-      {
-      public:
-
-         // Consequent only conditional statement node
-         typedef expression_node<T>* expression_ptr;
-
-         cons_conditional_node(expression_ptr test,
-                               expression_ptr consequent)
-         : test_(test),
-           consequent_(consequent),
-           test_deletable_(branch_deletable(test_)),
-           consequent_deletable_(branch_deletable(consequent_))
-         {}
-
-        ~cons_conditional_node()
-         {
-            if (test_       && test_deletable_      ) delete test_;
-            if (consequent_ && consequent_deletable_) delete consequent_;
-         }
-
-         inline T value() const
-         {
-            if (is_true(test_))
-               return consequent_->value();
-            else
-               return std::numeric_limits<T>::quiet_NaN();
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_conditional;
-         }
-
-      private:
-
-         expression_ptr test_;
-         expression_ptr consequent_;
-         bool test_deletable_;
-         bool consequent_deletable_;
-      };
-
-      #ifndef exprtk_disable_break_continue
-      template <typename T>
-      class break_exception : public std::exception
-      {
-      public:
-
-         break_exception(const T& v)
-         : value(v)
-         {}
-
-         T value;
-      };
-
-      class continue_exception : public std::exception
-      {};
-
-      template <typename T>
-      class break_node : public expression_node<T>
-      {
-      public:
-
-         typedef expression_node<T>* expression_ptr;
-
-         break_node(expression_ptr ret = expression_ptr(0))
-         : return_(ret),
-           return_deletable_(branch_deletable(return_))
-         {}
-
-        ~break_node()
-         {
-            if (return_deletable_)
+            
+            const char* base() const
             {
-               delete return_;
+                return &(*value_)[0];
             }
-         }
-
-         inline T value() const
-         {
-            throw break_exception<T>(return_ ? return_->value() : std::numeric_limits<T>::quiet_NaN());
-            #ifndef _MSC_VER
-            return std::numeric_limits<T>::quiet_NaN();
-            #endif
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_break;
-         }
-
-      private:
-
-         expression_ptr return_;
-         bool return_deletable_;
-      };
-
-      template <typename T>
-      class continue_node : public expression_node<T>
-      {
-      public:
-
-         inline T value() const
-         {
-            throw continue_exception();
-            #ifndef _MSC_VER
-            return std::numeric_limits<T>::quiet_NaN();
-            #endif
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_break;
-         }
-      };
-      #endif
-
-      template <typename T>
-      class while_loop_node : public expression_node<T>
-      {
-      public:
-
-         typedef expression_node<T>* expression_ptr;
-
-         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()
-         {
-            if (condition_ && condition_deletable_)
+            
+            std::size_t size() const
             {
-               delete condition_;
+                return ref().size();
             }
-
-            if (loop_body_ && loop_body_deletable_)
+            
+            std::string& ref()
             {
-               delete loop_body_;
+                return (*value_);
             }
-         }
-
-         inline T value() const
-         {
-            T result = T(0);
-
-            while (is_true(condition_))
+            
+            const std::string& ref() const
             {
-               result = loop_body_->value();
+                return (*value_);
             }
-
-            return result;
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_while;
-         }
-
-      private:
-
-         expression_ptr condition_;
-         expression_ptr loop_body_;
-         bool condition_deletable_;
-         bool loop_body_deletable_;
-      };
-
-      template <typename T>
-      class repeat_until_loop_node : public expression_node<T>
-      {
-      public:
-
-         typedef expression_node<T>* expression_ptr;
-
-         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()
-         {
-            if (condition_ && condition_deletable_)
+            
+            range_t& range_ref()
             {
-               delete condition_;
+                return rp_;
             }
-
-            if (loop_body_ && loop_body_deletable_)
+            
+            const range_t& range_ref() const
             {
-               delete loop_body_;
+                return rp_;
             }
-         }
-
-         inline T value() const
-         {
-            T result = T(0);
-
-            do
+            
+            inline typename expression_node<T>::node_type type() const
             {
-               result = loop_body_->value();
+                return expression_node<T>::e_stringvar;
             }
-            while (is_false(condition_));
-
-            return result;
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_repeat;
-         }
-
-      private:
-
-         expression_ptr condition_;
-         expression_ptr loop_body_;
-         bool condition_deletable_;
-         bool loop_body_deletable_;
-      };
-
-      template <typename T>
-      class for_loop_node : public expression_node<T>
-      {
-      public:
-
-         typedef expression_node<T>* expression_ptr;
-
-         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()
-         {
-            if (initialiser_ && initialiser_deletable_)
+            
+        private:
+            
+            std::string* value_;
+            mutable range_t rp_;
+        };
+        
+        template <typename T>
+        std::string stringvar_node<T>::null_value = std::string("");
+        
+        template <typename T>
+        class string_range_node : public expression_node <T>,
+        public string_base_node<T>,
+        public range_interface <T>
+        {
+        public:
+            
+            typedef range_pack<T> range_t;
+            
+            static std::string null_value;
+            
+            explicit string_range_node(std::string& v, const range_t& rp)
+            : value_(&v),
+            rp_(rp)
+            {}
+            
+            virtual ~string_range_node()
             {
-               delete initialiser_;
+                rp_.free();
             }
-
-            if (condition_ && condition_deletable_)
+            
+            inline bool operator <(const string_range_node<T>& v) const
             {
-               delete condition_;
+                return this < (&v);
             }
-
-            if (incrementor_ && incrementor_deletable_)
+            
+            inline T value() const
             {
-               delete incrementor_;
+                return std::numeric_limits<T>::quiet_NaN();
             }
-
-            if (loop_body_ && loop_body_deletable_)
+            
+            inline std::string str() const
             {
-               delete loop_body_;
+                return (*value_);
             }
-         }
-
-         inline T value() const
-         {
-            T result = T(0);
-
-            if (initialiser_)
-               initialiser_->value();
-
-            if (incrementor_)
+            
+            const char* base() const
             {
-               while (is_true(condition_))
-               {
-                  result = loop_body_->value();
-                  incrementor_->value();
-               }
+                return &(*value_)[0];
             }
-            else
+            
+            std::size_t size() const
             {
-               while (is_true(condition_))
-               {
-                  result = loop_body_->value();
-               }
+                return ref().size();
             }
-
-            return result;
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_for;
-         }
-
-      private:
-
-         expression_ptr initialiser_;
-         expression_ptr condition_  ;
-         expression_ptr incrementor_;
-         expression_ptr loop_body_  ;
-         bool initialiser_deletable_;
-         bool condition_deletable_  ;
-         bool incrementor_deletable_;
-         bool loop_body_deletable_  ;
-      };
-
-      #ifndef exprtk_disable_break_continue
-      template <typename T>
-      class while_loop_bc_node : public expression_node<T>
-      {
-      public:
-
-         typedef expression_node<T>* expression_ptr;
-
-         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()
-         {
-            if (condition_ && condition_deletable_)
+            
+            inline range_t range() const
             {
-               delete condition_;
+                return rp_;
             }
-
-            if (loop_body_ && loop_body_deletable_)
+            
+            inline virtual std::string& ref()
             {
-               delete loop_body_;
-            }
-         }
-
-         inline T value() const
-         {
-            T result = T(0);
-            while (is_true(condition_))
-            {
-               try
-               {
-                  result = loop_body_->value();
-               }
-               catch(const break_exception<T>& e)
-               {
-                  return e.value;
-               }
-               catch(const continue_exception&)
-               {}
+                return (*value_);
             }
-            return result;
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_while;
-         }
-
-      private:
-
-         expression_ptr condition_;
-         expression_ptr loop_body_;
-         bool condition_deletable_;
-         bool loop_body_deletable_;
-      };
-
-      template <typename T>
-      class repeat_until_loop_bc_node : public expression_node<T>
-      {
-      public:
-
-         typedef expression_node<T>* expression_ptr;
-
-         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()
-         {
-            if (condition_ && condition_deletable_)
+            
+            inline virtual const std::string& ref() const
             {
-               delete condition_;
+                return (*value_);
             }
-
-            if (loop_body_ && loop_body_deletable_)
+            
+            inline range_t& range_ref()
             {
-               delete loop_body_;
+                return rp_;
             }
-         }
-
-         inline T value() const
-         {
-            T result = T(0);
-
-            do
-            {
-               try
-               {
-                  result = loop_body_->value();
-               }
-               catch(const break_exception<T>& e)
-               {
-                  return e.value;
-               }
-               catch(const continue_exception&)
-               {}
-            }
-            while (is_false(condition_));
-
-            return result;
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_repeat;
-         }
-
-      private:
-
-         expression_ptr condition_;
-         expression_ptr loop_body_;
-         bool condition_deletable_;
-         bool loop_body_deletable_;
-      };
-
-      template <typename T>
-      class for_loop_bc_node : public expression_node<T>
-      {
-      public:
-
-         typedef expression_node<T>* expression_ptr;
-
-         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()
-         {
-            if (initialiser_ && initialiser_deletable_)
+            
+            inline const range_t& range_ref() const
             {
-               delete initialiser_;
+                return rp_;
             }
-
-            if (condition_ && condition_deletable_)
+            
+            inline typename expression_node<T>::node_type type() const
             {
-               delete condition_;
+                return expression_node<T>::e_stringvarrng;
             }
-
-            if (incrementor_ && incrementor_deletable_)
+            
+        private:
+            
+            std::string* value_;
+            range_t      rp_;
+        };
+        
+        template <typename T>
+        std::string string_range_node<T>::null_value = std::string("");
+        
+        template <typename T>
+        class const_string_range_node : public expression_node <T>,
+        public string_base_node<T>,
+        public range_interface <T>
+        {
+        public:
+            
+            typedef range_pack<T> range_t;
+            
+            explicit const_string_range_node(const std::string& v, const range_t& rp)
+            : value_(v),
+            rp_(rp)
+            {}
+            
+            ~const_string_range_node()
             {
-               delete incrementor_;
+                rp_.free();
             }
-
-            if (loop_body_ && loop_body_deletable_)
+            
+            inline T value() const
             {
-               delete loop_body_;
-            }
-         }
-
-         inline T value() const
-         {
-            T result = T(0);
-
-            if (initialiser_)
-               initialiser_->value();
-
-            if (incrementor_)
-            {
-               while (is_true(condition_))
-               {
-                  try
-                  {
-                     result = loop_body_->value();
-                  }
-                  catch(const break_exception<T>& e)
-                  {
-                     return e.value;
-                  }
-                  catch(const continue_exception&)
-                  {}
-
-                  incrementor_->value();
-               }
+                return std::numeric_limits<T>::quiet_NaN();
             }
-            else
+            
+            std::string str() const
             {
-               while (is_true(condition_))
-               {
-                  try
-                  {
-                     result = loop_body_->value();
-                  }
-                  catch(const break_exception<T>& e)
-                  {
-                     return e.value;
-                  }
-                  catch(const continue_exception&)
-                  {}
-               }
+                return value_;
             }
-
-            return result;
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_for;
-         }
-
-      private:
-
-         expression_ptr initialiser_;
-         expression_ptr condition_  ;
-         expression_ptr incrementor_;
-         expression_ptr loop_body_  ;
-         bool initialiser_deletable_;
-         bool condition_deletable_  ;
-         bool incrementor_deletable_;
-         bool loop_body_deletable_  ;
-      };
-      #endif
-
-      template <typename T>
-      class switch_node : public expression_node<T>
-      {
-      public:
-
-         typedef expression_node<T>* expression_ptr;
-
-         template <typename Allocator,
-                   template <typename,typename> class Sequence>
-         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)
+            
+            const char* base() const
             {
-               if (arg_list[i])
-               {
-                       arg_list_[i] = arg_list[i];
-                  delete_branch_[i] = static_cast<unsigned char>(branch_deletable(arg_list_[i]) ? 1 : 0);
-               }
-               else
-               {
-                  arg_list_.clear();
-                  delete_branch_.clear();
-                  return;
-               }
-            }
-         }
-
-        ~switch_node()
-         {
-            for (std::size_t i = 0; i < arg_list_.size(); ++i)
+                return value_.data();
+            }
+            
+            std::size_t size() const
             {
-               if (arg_list_[i] && delete_branch_[i])
-               {
-                  delete arg_list_[i];
-                  arg_list_[i] = 0;
-               }
+                return value_.size();
             }
-         }
-
-         inline T value() const
-         {
-            if (!arg_list_.empty())
+            
+            range_t range() const
             {
-               const std::size_t upper_bound = (arg_list_.size() - 1);
-
-               for (std::size_t i = 0; i < upper_bound; i += 2)
-               {
-                  expression_ptr condition  = arg_list_[i    ];
-                  expression_ptr consequent = arg_list_[i + 1];
-
-                  if (is_true(condition))
-                  {
-                     return consequent->value();
-                  }
-               }
-
-               return arg_list_[upper_bound]->value();
+                return rp_;
             }
-            else
-               return std::numeric_limits<T>::quiet_NaN();
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_switch;
-         }
-
-      private:
-
-         std::vector<expression_ptr> arg_list_;
-         std::vector<unsigned char> delete_branch_;
-      };
-
-      template <typename T>
-      class multi_switch_node : public expression_node<T>
-      {
-      public:
-
-         typedef expression_node<T>* expression_ptr;
-
-         template <typename Allocator,
-                   template <typename,typename> class Sequence>
-         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)
+            
+            range_t& range_ref()
             {
-               if (arg_list[i])
-               {
-                       arg_list_[i] = arg_list[i];
-                  delete_branch_[i] = static_cast<unsigned char>(branch_deletable(arg_list_[i]) ? 1 : 0);
-               }
-               else
-               {
-                  arg_list_.clear();
-                  delete_branch_.clear();
-                  return;
-               }
-            }
-         }
-
-        ~multi_switch_node()
-         {
-            for (std::size_t i = 0; i < arg_list_.size(); ++i)
+                return rp_;
+            }
+            
+            const range_t& range_ref() const
             {
-               if (arg_list_[i] && delete_branch_[i])
-               {
-                  delete arg_list_[i];
-                  arg_list_[i] = 0;
-               }
+                return rp_;
             }
-         }
-
-         inline T value() const
-         {
-            T result = T(0);
-
-            if (arg_list_.empty())
+            
+            inline typename expression_node<T>::node_type type() const
             {
-               return std::numeric_limits<T>::quiet_NaN();
+                return expression_node<T>::e_cstringvarrng;
             }
-
-            const std::size_t upper_bound = (arg_list_.size() - 1);
-
-            for (std::size_t i = 0; i < upper_bound; i += 2)
+            
+        private:
+            
+            const_string_range_node<T>& operator=(const const_string_range_node<T>&);
+            
+            const std::string value_;
+            range_t rp_;
+        };
+        
+        template <typename T>
+        class generic_string_range_node : public expression_node <T>,
+        public string_base_node<T>,
+        public range_interface <T>
+        {
+        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;
+            
+            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)
+            {
+                range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
+                range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
+                range_.cache.first  = range_.n0_c.second;
+                range_.cache.second = range_.n1_c.second;
+                
+                if (is_generally_string_node(branch_))
+                {
+                    str_base_ptr_ = dynamic_cast<str_base_ptr>(branch_);
+                    
+                    if (0 == str_base_ptr_)
+                        return;
+                    
+                    str_range_ptr_ = dynamic_cast<irange_ptr>(branch_);
+                    
+                    if (0 == str_range_ptr_)
+                        return;
+                }
+                
+                initialised_ = (str_base_ptr_ && str_range_ptr_);
+            }
+            
+            ~generic_string_range_node()
+            {
+                base_range_.free();
+                
+                if (branch_ && branch_deletable_)
+                {
+                    delete branch_;
+                    branch_ = 0;
+                }
+            }
+            
+            inline T value() const
+            {
+                if (initialised_)
+                {
+                    branch_->value();
+                    
+                    std::size_t str_r0 = 0;
+                    std::size_t str_r1 = 0;
+                    
+                    std::size_t r0 = 0;
+                    std::size_t r1 = 0;
+                    
+                    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)
+                        )
+                    {
+                        const std::size_t size = (r1 - r0) + 1;
+                        
+                        range_.n1_c.second  = size - 1;
+                        range_.cache.second = range_.n1_c.second;
+                        
+                        value_.assign(str_base_ptr_->base() + str_r0 + r0, size);
+                    }
+                }
+                
+                return std::numeric_limits<T>::quiet_NaN();
+            }
+            
+            std::string str() const
             {
-               expression_ptr condition  = arg_list_[i    ];
-               expression_ptr consequent = arg_list_[i + 1];
-
-               if (is_true(condition))
-               {
-                  result = consequent->value();
-               }
+                return value_;
             }
-
-            return result;
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_mswitch;
-         }
-
-      private:
-
-         std::vector<expression_ptr> arg_list_;
-         std::vector<unsigned char> delete_branch_;
-      };
-
-      template <typename T>
-      class ivariable
-      {
-      public:
-
-         virtual T& ref() = 0;
-         virtual const T& ref() const = 0;
-      };
-
-      template <typename T>
-      class variable_node : public expression_node<T>,
-                            public ivariable<T>
-      {
-      public:
-
-         static T null_value;
-
-         explicit variable_node()
-         : value_(&null_value),
-           delete_value_(false)
-         {}
-
-         variable_node(T& v)
-         : value_(&v),
-           delete_value_(false)
-         {}
-
-        ~variable_node()
-         {
-            if (delete_value_)
+            
+            const char* base() const
             {
-               delete value_;
+                return &value_[0];
             }
-         }
-
-         inline bool operator <(const variable_node<T>& v) const
-         {
-            return this < (&v);
-         }
-
-         inline T value() const
-         {
-            return (*value_);
-         }
-
-         inline T& ref()
-         {
-            return (*value_);
-         }
-
-         inline const T& ref() const
-         {
-            return (*value_);
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_variable;
-         }
-
-         inline bool& delete_value()
-         {
-            return delete_value_;
-         }
-
-      private:
-
-         T* value_;
-         bool delete_value_;
-      };
-
-      template <typename T>
-      T variable_node<T>::null_value = T(std::numeric_limits<T>::quiet_NaN());
-
-      template <typename T>
-      struct range_pack
-      {
-         typedef expression_node<T>*           expression_node_ptr;
-         typedef std::pair<std::size_t,std::size_t> cached_range_t;
-
-         range_pack()
-         : n0_e (std::make_pair(false,expression_node_ptr(0))),
-           n1_e (std::make_pair(false,expression_node_ptr(0))),
-           n0_c (std::make_pair(false,0)),
-           n1_c (std::make_pair(false,0)),
-           cache(std::make_pair(0,0))
-         {}
-
-         void clear()
-         {
-            n0_e  = std::make_pair(false,expression_node_ptr(0));
-            n1_e  = std::make_pair(false,expression_node_ptr(0));
-            n0_c  = std::make_pair(false,0);
-            n1_c  = std::make_pair(false,0);
-            cache = std::make_pair(0,0);
-         }
-
-         void free()
-         {
-            if (n0_e.first && n0_e.second)
+            
+            std::size_t size() const
             {
-               n0_e.first = false;
-
-               if (
-                    !is_variable_node(n0_e.second) &&
-                    !is_string_node  (n0_e.second)
-                  )
-               {
-                  delete n0_e.second;
-                  n0_e.second = expression_node_ptr(0);
-               }
+                return value_.size();
             }
-
-            if (n1_e.first && n1_e.second)
+            
+            range_t& range_ref()
             {
-               n1_e.first = false;
-
-               if (
-                    !is_variable_node(n1_e.second) &&
-                    !is_string_node  (n1_e.second)
-                  )
-               {
-                  delete n1_e.second;
-                  n1_e.second = expression_node_ptr(0);
-               }
-            }
-         }
-
-         bool const_range()
-         {
-           return ( n0_c.first &&  n1_c.first) &&
-                  (!n0_e.first && !n1_e.first);
-         }
-
-         bool var_range()
-         {
-           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
-         {
-            if (n0_c.first)
-               r0 = n0_c.second;
-            else if (n0_e.first)
+                return range_;
+            }
+            
+            const range_t& range_ref() const
             {
-               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));
+                return range_;
             }
-            else
-               return false;
-
-            if (n1_c.first)
-               r1 = n1_c.second;
-            else if (n1_e.first)
+            
+            inline typename expression_node<T>::node_type type() const
             {
-               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));
+                return expression_node<T>::e_strgenrange;
             }
-            else
-               return false;
-
-            if (
-                 (std::numeric_limits<std::size_t>::max() != size) &&
-                 (std::numeric_limits<std::size_t>::max() == r1  )
-               )
+            
+        private:
+            
+            bool               initialised_;
+            expression_ptr          branch_;
+            bool          branch_deletable_;
+            str_base_ptr      str_base_ptr_;
+            irange_ptr       str_range_ptr_;
+            mutable range_t     base_range_;
+            mutable range_t          range_;
+            mutable std::string      value_;
+        };
+        
+        template <typename T>
+        class string_concat_node : public binary_node     <T>,
+        public string_base_node<T>,
+        public range_interface <T>
+        {
+        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;
+            
+            string_concat_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_range_ptr_(0),
+            str1_range_ptr_(0)
+            {
+                range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
+                range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
+                
+                range_.cache.first  = range_.n0_c.second;
+                range_.cache.second = range_.n1_c.second;
+                
+                if (is_generally_string_node(binary_node<T>::branch_[0].first))
+                {
+                    str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
+                    
+                    if (0 == str0_base_ptr_)
+                        return;
+                    
+                    str0_range_ptr_ = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first);
+                    
+                    if (0 == str0_range_ptr_)
+                        return;
+                }
+                
+                if (is_generally_string_node(binary_node<T>::branch_[1].first))
+                {
+                    str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);
+                    
+                    if (0 == str1_base_ptr_)
+                        return;
+                    
+                    str1_range_ptr_ = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
+                    
+                    if (0 == str1_range_ptr_)
+                        return;
+                }
+                
+                initialised_ = str0_base_ptr_  &&
+                str1_base_ptr_  &&
+                str0_range_ptr_ &&
+                str1_range_ptr_ ;
+            }
+            
+            inline T value() const
+            {
+                if (initialised_)
+                {
+                    binary_node<T>::branch_[0].first->value();
+                    binary_node<T>::branch_[1].first->value();
+                    
+                    std::size_t str0_r0 = 0;
+                    std::size_t str0_r1 = 0;
+                    
+                    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();
+                    
+                    if (
+                        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;
+                        const std::size_t size1 = (str1_r1 - str1_r0) + 1;
+                        
+                        value_.assign(str0_base_ptr_->base() + str0_r0, size0);
+                        value_.append(str1_base_ptr_->base() + str1_r0, size1);
+                        
+                        range_.n1_c.second  = value_.size() - 1;
+                        range_.cache.second = range_.n1_c.second;
+                    }
+                }
+                
+                return std::numeric_limits<T>::quiet_NaN();
+            }
+            
+            std::string str() const
             {
-               r1 = size - 1;
+                return value_;
             }
-
-            cache.first  = r0;
-            cache.second = r1;
-
-            return (r0 <= r1);
-         }
-
-         inline std::size_t const_size() const
-         {
-            return (n1_c.second - n0_c.second + 1);
-         }
-
-         inline std::size_t cache_size() const
-         {
-            return (cache.second - cache.first + 1);
-         }
-
-         std::pair<bool,expression_node_ptr> n0_e;
-         std::pair<bool,expression_node_ptr> n1_e;
-         std::pair<bool,std::size_t        > n0_c;
-         std::pair<bool,std::size_t        > n1_c;
-         mutable cached_range_t             cache;
-      };
-
-      template <typename T>
-      class string_base_node;
-
-      template <typename T>
-      struct range_data_type
-      {
-         typedef range_pack<T> range_t;
-         typedef string_base_node<T>* strbase_ptr_t;
-
-         range_data_type()
-         : range(0),
-           data (0),
-           size (0),
-           type_size(0),
-           str_node (0)
-         {}
-
-         range_t*      range;
-         void*         data;
-         std::size_t   size;
-         std::size_t   type_size;
-         strbase_ptr_t str_node;
-      };
-
-      template <typename T> class vector_node;
-
-      template <typename T>
-      class vector_interface
-      {
-      public:
-
-         typedef vector_node<T>* vector_node_ptr;
-
-         virtual ~vector_interface()
-         {}
-
-         virtual vector_node_ptr vec() const = 0;
-
-         virtual vector_node_ptr vec() = 0;
-
-         virtual std::size_t size() const = 0;
-      };
-
-      template <typename T>
-      class vector_node : public expression_node<T>,
-                          public vector_interface<T>
-      {
-      public:
-
-         typedef expression_node<T>*  expression_ptr;
-         typedef vector_holder<T>    vector_holder_t;
-         typedef vector_node<T>*     vector_node_ptr;
-
-         vector_node(vector_holder_t* vh)
-         : vector_holder_(vh)
-         {}
-
-         inline T value() const
-         {
-            return *(ref()[0]);
-         }
-
-         inline const vector_holder_t& ref() const
-         {
-            return (*vector_holder_);
-         }
-
-         inline vector_holder_t& ref()
-         {
-            return (*vector_holder_);
-         }
-
-         vector_node_ptr vec() const
-         {
-            return const_cast<vector_node_ptr>(this);
-         }
-
-         vector_node_ptr vec()
-         {
-            return this;
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_vector;
-         }
-
-         std::size_t size() const
-         {
-            return ref().size();
-         }
-
-      private:
-
-         vector_holder_t* vector_holder_;
-      };
-
-      template <typename T>
-      class vector_elem_node : public expression_node<T>,
-                               public ivariable<T>
-      {
-      public:
-
-         typedef expression_node<T>* expression_ptr;
-
-         vector_elem_node(expression_ptr index, T* vector_base)
-         : index_(index),
-           vector_base_(vector_base),
-           index_deletable_(branch_deletable(index_))
-         {}
-
-        ~vector_elem_node()
-         {
-            if (index_ && index_deletable_)
+            
+            const char* base() const
             {
-               delete index_;
+                return &value_[0];
             }
-         }
-
-         inline T value() const
-         {
-           return *(vector_base_ + static_cast<std::size_t>(details::numeric::to_int64(index_->value())));
-         }
-
-         inline T& ref()
-         {
-            return *(vector_base_ + static_cast<std::size_t>(details::numeric::to_int64(index_->value())));
-         }
-
-         inline const T& ref() const
-         {
-            return *(vector_base_ + static_cast<std::size_t>(details::numeric::to_int64(index_->value())));
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_vecelem;
-         }
-
-      private:
-
-         expression_ptr index_;
-         T* vector_base_;
-         bool index_deletable_;
-      };
-
-      template <typename T>
-      class vector_assignment_node : public expression_node<T>
-      {
-      public:
-
-         typedef expression_node<T>* expression_ptr;
-
-         vector_assignment_node(T* vector_base,
-                                const std::size_t& size,
-                                const std::vector<expression_ptr>& initialiser_list,
-                                const bool single_value_initialse)
-         : vector_base_(vector_base),
-           initialiser_list_(initialiser_list),
-           size_(size),
-           single_value_initialse_(single_value_initialse)
-         {}
-
-        ~vector_assignment_node()
-         {
-            for (std::size_t i = 0; i < initialiser_list_.size(); ++i)
+            
+            std::size_t size() const
             {
-               if (branch_deletable(initialiser_list_[i]))
-               {
-                  delete initialiser_list_[i];
-               }
+                return value_.size();
             }
-         }
-
-         inline T value() const
-         {
-            if (single_value_initialse_)
+            
+            range_t& range_ref()
             {
-               for (std::size_t i = 0; i < size_; ++i)
-               {
-                  *(vector_base_ + i) = initialiser_list_[0]->value();
-               }
+                return range_;
             }
-            else
+            
+            const range_t& range_ref() const
             {
-               std::size_t il_size = initialiser_list_.size();
-
-               for (std::size_t i = 0; i < il_size; ++i)
-               {
-                  *(vector_base_ + i) = initialiser_list_[i]->value();
-               }
-
-               if (il_size < size_)
-               {
-                  for (std::size_t i = il_size; i < size_; ++i)
-                  {
-                     *(vector_base_ + i) = T(0);
-                  }
-               }
+                return range_;
             }
-
-            return *(vector_base_);
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_vecdefass;
-         }
-
-      private:
-
-         vector_assignment_node<T>& operator=(const vector_assignment_node<T>&);
-
-         mutable T* vector_base_;
-         std::vector<expression_ptr> initialiser_list_;
-         const std::size_t size_;
-         const bool single_value_initialse_;
-      };
-
-      template <typename T>
-      class swap_node : public expression_node<T>
-      {
-      public:
-
-         typedef expression_node<T>* expression_ptr;
-         typedef variable_node<T>*   variable_node_ptr;
-
-         swap_node(variable_node_ptr var0, variable_node_ptr var1)
-         : var0_(var0),
-           var1_(var1)
-         {}
-
-         inline T value() const
-         {
-            std::swap(var0_->ref(),var1_->ref());
-            return var1_->ref();
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_swap;
-         }
-
-      private:
-
-         variable_node_ptr var0_;
-         variable_node_ptr var1_;
-      };
-
-      template <typename T>
-      class swap_generic_node : public binary_node<T>
-      {
-      public:
-
-         typedef expression_node<T>* expression_ptr;
-         typedef ivariable<T>* ivariable_ptr;
-
-         swap_generic_node(expression_ptr var0, expression_ptr var1)
-         : binary_node<T>(details::e_swap,var0,var1),
-           var0_(dynamic_cast<ivariable_ptr>(var0)),
-           var1_(dynamic_cast<ivariable_ptr>(var1))
-         {}
-
-         inline T value() const
-         {
-            std::swap(var0_->ref(),var1_->ref());
-            return var1_->ref();
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_swap;
-         }
-
-      private:
-
-         ivariable_ptr var0_;
-         ivariable_ptr var1_;
-      };
-
-      template <typename T>
-      class swap_vecvec_node : public binary_node<T>,
-                               public vector_interface<T>
-      {
-      public:
-
-         typedef expression_node<T>* expression_ptr;
-         typedef vector_node<T>*     vector_node_ptr;
-
-         swap_vecvec_node(expression_ptr branch0,
-                          expression_ptr branch1)
-         : binary_node<T>(details::e_swap,branch0,branch1),
-           vec0_node_ptr_(0),
-           vec1_node_ptr_(0),
-           vec_size_     (0)
-         {
-            if (is_ivector_node(binary_node<T>::branch_[0].first))
-            {
-               vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
-
-               if ((vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[0].first)))
-               {
-                  vec0_node_ptr_ = vi->vec();
-               }
+            
+            inline typename expression_node<T>::node_type type() const
+            {
+                return expression_node<T>::e_strconcat;
             }
-
-            if (is_ivector_node(binary_node<T>::branch_[1].first))
+            
+        private:
+            
+            bool initialised_;
+            str_base_ptr str0_base_ptr_;
+            str_base_ptr str1_base_ptr_;
+            irange_ptr   str0_range_ptr_;
+            irange_ptr   str1_range_ptr_;
+            mutable range_t     range_;
+            mutable std::string value_;
+        };
+        
+        template <typename T>
+        class swap_string_node : public binary_node     <T>,
+        public string_base_node<T>,
+        public range_interface <T>
+        {
+        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;
+            
+            swap_string_node(expression_ptr branch0, expression_ptr branch1)
+            : binary_node<T>(details::e_swap,branch0,branch1),
+            initialised_(false),
+            str0_node_ptr_(0),
+            str1_node_ptr_(0)
+            {
+                if (is_string_node(binary_node<T>::branch_[0].first))
+                {
+                    str0_node_ptr_ = static_cast<strvar_node_ptr>(binary_node<T>::branch_[0].first);
+                }
+                
+                if (is_string_node(binary_node<T>::branch_[1].first))
+                {
+                    str1_node_ptr_ = static_cast<strvar_node_ptr>(binary_node<T>::branch_[1].first);
+                }
+                
+                initialised_ = (str0_node_ptr_ && str1_node_ptr_);
+            }
+            
+            inline T value() const
+            {
+                if (initialised_)
+                {
+                    binary_node<T>::branch_[0].first->value();
+                    binary_node<T>::branch_[1].first->value();
+                    
+                    std::swap(str0_node_ptr_->ref(),str1_node_ptr_->ref());
+                }
+                
+                return std::numeric_limits<T>::quiet_NaN();
+            }
+            
+            std::string str() const
+            {
+                return str0_node_ptr_->str();
+            }
+            
+            const char* base() const
+            {
+                return str0_node_ptr_->base();
+            }
+            
+            std::size_t size() const
+            {
+                return str0_node_ptr_->size();
+            }
+            
+            range_t& range_ref()
+            {
+                return str0_node_ptr_->range_ref();
+            }
+            
+            const range_t& range_ref() const
+            {
+                return str0_node_ptr_->range_ref();
+            }
+            
+            inline typename expression_node<T>::node_type type() const
+            {
+                return expression_node<T>::e_strswap;
+            }
+            
+        private:
+            
+            bool initialised_;
+            strvar_node_ptr str0_node_ptr_;
+            strvar_node_ptr str1_node_ptr_;
+        };
+        
+        template <typename T>
+        class swap_genstrings_node : public binary_node<T>
+        {
+        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;
+            
+            swap_genstrings_node(expression_ptr branch0,
+                                 expression_ptr branch1)
+            : binary_node<T>(details::e_default,branch0,branch1),
+            str0_base_ptr_ (0),
+            str1_base_ptr_ (0),
+            str0_range_ptr_(0),
+            str1_range_ptr_(0),
+            initialised_(false)
+            {
+                if (is_generally_string_node(binary_node<T>::branch_[0].first))
+                {
+                    str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
+                    
+                    if (0 == str0_base_ptr_)
+                        return;
+                    
+                    irange_ptr range_ptr = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first);
+                    
+                    if (0 == range_ptr)
+                        return;
+                    
+                    str0_range_ptr_ = &(range_ptr->range_ref());
+                }
+                
+                if (is_generally_string_node(binary_node<T>::branch_[1].first))
+                {
+                    str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);
+                    
+                    if (0 == str1_base_ptr_)
+                        return;
+                    
+                    irange_ptr range_ptr = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
+                    
+                    if (0 == range_ptr)
+                        return;
+                    
+                    str1_range_ptr_ = &(range_ptr->range_ref());
+                }
+                
+                initialised_ = str0_base_ptr_  &&
+                str1_base_ptr_  &&
+                str0_range_ptr_ &&
+                str1_range_ptr_ ;
+            }
+            
+            inline T value() const
+            {
+                if (initialised_)
+                {
+                    binary_node<T>::branch_[0].first->value();
+                    binary_node<T>::branch_[1].first->value();
+                    
+                    std::size_t str0_r0 = 0;
+                    std::size_t str0_r1 = 0;
+                    
+                    std::size_t str1_r0 = 0;
+                    std::size_t str1_r1 = 0;
+                    
+                    range_t& range0 = (*str0_range_ptr_);
+                    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())
+                        )
+                    {
+                        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* s0 = const_cast<char*>(str0_base_ptr_->base() + str0_r0);
+                        char* s1 = const_cast<char*>(str1_base_ptr_->base() + str1_r0);
+                        
+                        loop_unroll::details lud(max_size);
+                        const char* upper_bound = s0 + lud.upper_bound;
+                        
+                        while (s0 < upper_bound)
+                        {
+#define exprtk_loop(N)   \
+std::swap(s0[N], s1[N]); \
+
+                            exprtk_loop( 0) exprtk_loop( 1)
+                            exprtk_loop( 2) exprtk_loop( 3)
+#ifndef exprtk_disable_superscalar_unroll
+                            exprtk_loop( 4) exprtk_loop( 5)
+                            exprtk_loop( 6) exprtk_loop( 7)
+                            exprtk_loop( 8) exprtk_loop( 9)
+                            exprtk_loop(10) exprtk_loop(11)
+                            exprtk_loop(12) exprtk_loop(13)
+                            exprtk_loop(14) exprtk_loop(15)
+#endif
+                            
+                            s0 += lud.batch_size;
+                            s1 += lud.batch_size;
+                        }
+                        
+                        int i = 0;
+                        
+                        switch (lud.remainder)
+                        {
+#define case_stmt(N)                      \
+case N : { std::swap(s0[i],s1[i]); ++i; } \
+
+#ifndef exprtk_disable_superscalar_unroll
+                                case_stmt(15) case_stmt(14)
+                                case_stmt(13) case_stmt(12)
+                                case_stmt(11) case_stmt(10)
+                                case_stmt( 9) case_stmt( 8)
+                                case_stmt( 7) case_stmt( 6)
+                                case_stmt( 5) case_stmt( 4)
+#endif
+                                case_stmt( 3) case_stmt( 2)
+                                case_stmt( 1)
+                        }
+                        
+#undef exprtk_loop
+#undef case_stmt
+                    }
+                }
+                
+                return std::numeric_limits<T>::quiet_NaN();
+            }
+            
+            inline typename expression_node<T>::node_type type() const
+            {
+                return expression_node<T>::e_strswap;
+            }
+            
+        private:
+            
+            swap_genstrings_node(swap_genstrings_node<T>&);
+            swap_genstrings_node<T>& operator=(swap_genstrings_node<T>&);
+            
+            str_base_ptr str0_base_ptr_;
+            str_base_ptr str1_base_ptr_;
+            range_ptr    str0_range_ptr_;
+            range_ptr    str1_range_ptr_;
+            bool         initialised_;
+        };
+        
+        template <typename T>
+        class stringvar_size_node : public expression_node<T>
+        {
+        public:
+            
+            static std::string null_value;
+            
+            explicit stringvar_size_node()
+            : value_(&null_value)
+            {}
+            
+            explicit stringvar_size_node(std::string& v)
+            : value_(&v)
+            {}
+            
+            inline T value() const
             {
-               vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
-
-               if ((vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
-               {
-                  vec1_node_ptr_ = vi->vec();
-               }
+                return T((*value_).size());
             }
-
-            if (vec0_node_ptr_ && vec1_node_ptr_)
+            
+            inline typename expression_node<T>::node_type type() const
             {
-               vec_size_ = std::min(vec0_node_ptr_->ref().size(),
-                                    vec1_node_ptr_->ref().size());
+                return expression_node<T>::e_stringvarsize;
             }
-         }
-
-         inline T value() const
-         {
-            if (vec0_node_ptr_ && vec1_node_ptr_)
+            
+        private:
+            
+            std::string* value_;
+        };
+        
+        template <typename T>
+        std::string stringvar_size_node<T>::null_value = std::string("");
+        
+        template <typename T>
+        class string_size_node : public expression_node<T>
+        {
+        public:
+            
+            typedef expression_node <T>* expression_ptr;
+            typedef string_base_node<T>*   str_base_ptr;
+            
+            string_size_node(expression_ptr brnch)
+            : branch_(brnch),
+            branch_deletable_(branch_deletable(branch_)),
+            str_base_ptr_(0)
+            {
+                if (is_generally_string_node(branch_))
+                {
+                    str_base_ptr_ = dynamic_cast<str_base_ptr>(branch_);
+                    
+                    if (0 == str_base_ptr_)
+                        return;
+                }
+            }
+            
+            ~string_size_node()
+            {
+                if (branch_ && branch_deletable_)
+                {
+                    delete branch_;
+                    branch_ = 0;
+                }
+            }
+            
+            inline T value() const
+            {
+                T result = std::numeric_limits<T>::quiet_NaN();
+                
+                if (str_base_ptr_)
+                {
+                    branch_->value();
+                    result = T(str_base_ptr_->size());
+                }
+                
+                return result;
+            }
+            
+            inline typename expression_node<T>::node_type type() const
+            {
+                return expression_node<T>::e_stringsize;
+            }
+            
+        private:
+            
+            expression_ptr branch_;
+            bool branch_deletable_;
+            str_base_ptr str_base_ptr_;
+        };
+        
+        struct asn_assignment
+        {
+            static inline void execute(std::string& s, const char* data, const std::size_t size)
+            { s.assign(data,size); }
+        };
+        
+        struct asn_addassignment
+        {
+            static inline void execute(std::string& s, const char* data, const std::size_t size)
+            { s.append(data,size); }
+        };
+        
+        template <typename T, typename AssignmentProcess = asn_assignment>
+        class assignment_string_node : public binary_node     <T>,
+        public string_base_node<T>,
+        public range_interface <T>
+        {
+        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;
+            
+            assignment_string_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),
+            str1_range_ptr_(0)
+            {
+                if (is_string_node(binary_node<T>::branch_[0].first))
+                {
+                    str0_node_ptr_ = static_cast<strvar_node_ptr>(binary_node<T>::branch_[0].first);
+                    
+                    str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
+                }
+                
+                if (is_generally_string_node(binary_node<T>::branch_[1].first))
+                {
+                    str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);
+                    
+                    if (0 == str1_base_ptr_)
+                        return;
+                    
+                    irange_ptr range_ptr = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
+                    
+                    if (0 == range_ptr)
+                        return;
+                    
+                    str1_range_ptr_ = &(range_ptr->range_ref());
+                }
+                
+                initialised_ = str0_base_ptr_  &&
+                str1_base_ptr_  &&
+                str0_node_ptr_  &&
+                str1_range_ptr_ ;
+            }
+            
+            inline T value() const
+            {
+                if (initialised_)
+                {
+                    binary_node<T>::branch_[1].first->value();
+                    
+                    std::size_t r0 = 0;
+                    std::size_t r1 = 0;
+                    
+                    range_t& range = (*str1_range_ptr_);
+                    
+                    if (range(r0,r1,str1_base_ptr_->size()))
+                    {
+                        AssignmentProcess::execute(str0_node_ptr_->ref(),
+                                                   str1_base_ptr_->base() + r0,
+                                                   (r1 - r0) + 1);
+                        
+                        binary_node<T>::branch_[0].first->value();
+                    }
+                }
+                
+                return std::numeric_limits<T>::quiet_NaN();
+            }
+            
+            std::string str() const
+            {
+                return str0_node_ptr_->str();
+            }
+            
+            const char* base() const
+            {
+                return str0_node_ptr_->base();
+            }
+            
+            std::size_t size() const
+            {
+                return str0_node_ptr_->size();
+            }
+            
+            range_t& range_ref()
+            {
+                return str0_node_ptr_->range_ref();
+            }
+            
+            const range_t& range_ref() const
+            {
+                return str0_node_ptr_->range_ref();
+            }
+            
+            inline typename expression_node<T>::node_type type() const
+            {
+                return expression_node<T>::e_strass;
+            }
+            
+        private:
+            
+            bool            initialised_;
+            str_base_ptr    str0_base_ptr_;
+            str_base_ptr    str1_base_ptr_;
+            strvar_node_ptr str0_node_ptr_;
+            range_ptr       str1_range_ptr_;
+        };
+        
+        template <typename T, typename AssignmentProcess = asn_assignment>
+        class assignment_string_range_node : public binary_node     <T>,
+        public string_base_node<T>,
+        public range_interface <T>
+        {
+        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;
+            
+            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)
+            {
+                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_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);
+                    
+                    if (0 == range_ptr)
+                        return;
+                    
+                    str0_range_ptr_ = &(range_ptr->range_ref());
+                }
+                
+                if (is_generally_string_node(binary_node<T>::branch_[1].first))
+                {
+                    str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);
+                    
+                    if (0 == str1_base_ptr_)
+                        return;
+                    
+                    irange_ptr range_ptr = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
+                    
+                    if (0 == range_ptr)
+                        return;
+                    
+                    str1_range_ptr_ = &(range_ptr->range_ref());
+                }
+                
+                initialised_ = str0_base_ptr_  &&
+                str1_base_ptr_  &&
+                str0_node_ptr_  &&
+                str0_range_ptr_ &&
+                str1_range_ptr_ ;
+            }
+            
+            inline T value() const
+            {
+                if (initialised_)
+                {
+                    binary_node<T>::branch_[0].first->value();
+                    binary_node<T>::branch_[1].first->value();
+                    
+                    std::size_t s0_r0 = 0;
+                    std::size_t s0_r1 = 0;
+                    
+                    std::size_t s1_r0 = 0;
+                    std::size_t s1_r1 = 0;
+                    
+                    range_t& range0 = (*str0_range_ptr_);
+                    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;
+                        
+                        std::copy(str1_base_ptr_->base() + s1_r0,
+                                  str1_base_ptr_->base() + s1_r0 + size,
+                                  const_cast<char*>(base() + s0_r0));
+                    }
+                }
+                
+                return std::numeric_limits<T>::quiet_NaN();
+            }
+            
+            std::string str() const
             {
-               binary_node<T>::branch_[0].first->value();
-               binary_node<T>::branch_[1].first->value();
-
-               vector_holder<T>& vec0 = vec0_node_ptr_->ref();
-               vector_holder<T>& vec1 = vec1_node_ptr_->ref();
-
-               for (std::size_t i = 0; i < vec_size_; ++i)
-               {
-                  std::swap((*vec0[i]),(*vec1[i]));
-               }
-
-               return vec1_node_ptr_->value();
+                return str0_node_ptr_->str();
             }
-            else
-               return std::numeric_limits<T>::quiet_NaN();
-         }
-
-         vector_node_ptr vec() const
-         {
-            return vec0_node_ptr_;
-         }
-
-         vector_node_ptr vec()
-         {
-            return vec0_node_ptr_;
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_vecvecswap;
-         }
-
-         std::size_t size() const
-         {
-            return vec_size_;
-         }
-
-      private:
-
-         vector_node<T>* vec0_node_ptr_;
-         vector_node<T>* vec1_node_ptr_;
-         std::size_t     vec_size_;
-      };
-
-      #ifndef exprtk_disable_string_capabilities
-      template <typename T>
-      class stringvar_node : public expression_node <T>,
-                             public string_base_node<T>,
-                             public range_interface <T>
-      {
-      public:
-
-         typedef range_pack<T> range_t;
-
-         static std::string null_value;
-
-         explicit stringvar_node()
-         : value_(&null_value)
-         {}
-
-         explicit stringvar_node(std::string& v)
-         : value_(&v)
-         {
-            rp_.n0_c = std::make_pair<bool,std::size_t>(true,0);
-            rp_.n1_c = std::make_pair<bool,std::size_t>(true,v.size() - 1);
-            rp_.cache.first  = rp_.n0_c.second;
-            rp_.cache.second = rp_.n1_c.second;
-         }
-
-         inline bool operator <(const stringvar_node<T>& v) const
-         {
-            return this < (&v);
-         }
-
-         inline T value() const
-         {
-            rp_.n1_c.second  = (*value_).size() - 1;
-            rp_.cache.second = rp_.n1_c.second;
-            return std::numeric_limits<T>::quiet_NaN();
-         }
-
-         std::string str() const
-         {
-            return ref();
-         }
-
-         const char* base() const
-         {
-           return (*value_).data();
-         }
-
-         std::size_t size() const
-         {
-            return ref().size();
-         }
-
-         std::string& ref()
-         {
-            return (*value_);
-         }
-
-         const std::string& ref() const
-         {
-            return (*value_);
-         }
-
-         range_t& range_ref()
-         {
-            return rp_;
-         }
-
-         const range_t& range_ref() const
-         {
-            return rp_;
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_stringvar;
-         }
-
-      private:
-
-         std::string* value_;
-         mutable range_t rp_;
-      };
-
-      template <typename T>
-      std::string stringvar_node<T>::null_value = std::string("");
-
-      template <typename T>
-      class string_range_node :  public expression_node <T>,
-                                 public string_base_node<T>,
-                                 public range_interface <T>
-      {
-      public:
-
-         typedef range_pack<T> range_t;
-
-         static std::string null_value;
-
-         explicit string_range_node(std::string& v, range_t rp)
-         : value_(&v),
-           rp_(rp)
-         {}
-
-        ~string_range_node()
-         {
-            rp_.free();
-         }
-
-         inline bool operator <(const string_range_node<T>& v) const
-         {
-            return this < (&v);
-         }
-
-         inline T value() const
-         {
-            return std::numeric_limits<T>::quiet_NaN();
-         }
-
-         inline std::string str() const
-         {
-            return (*value_);
-         }
-
-         const char* base() const
-         {
-           return (*value_).data();
-         }
-
-         std::size_t size() const
-         {
-            return ref().size();
-         }
-
-         inline range_t range() const
-         {
-            return rp_;
-         }
-
-         inline virtual std::string& ref()
-         {
-            return (*value_);
-         }
-
-         inline virtual const std::string& ref() const
-         {
-            return (*value_);
-         }
-
-         inline range_t& range_ref()
-         {
-            return rp_;
-         }
-
-         inline const range_t& range_ref() const
-         {
-            return rp_;
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_stringvarrng;
-         }
-
-      private:
-
-         std::string* value_;
-         range_t      rp_;
-      };
-
-      template <typename T>
-      std::string string_range_node<T>::null_value = std::string("");
-
-      template <typename T>
-      class const_string_range_node : public expression_node <T>,
-                                      public string_base_node<T>,
-                                      public range_interface <T>
-      {
-      public:
-
-         typedef range_pack<T> range_t;
-
-         explicit const_string_range_node(const std::string& v, range_t rp)
-         : value_(v),
-           rp_(rp)
-         {}
-
-        ~const_string_range_node()
-         {
-            rp_.free();
-         }
-
-         inline T value() const
-         {
-            return std::numeric_limits<T>::quiet_NaN();
-         }
-
-         std::string str() const
-         {
-            return value_;
-         }
-
-         const char* base() const
-         {
-           return value_.data();
-         }
-
-         std::size_t size() const
-         {
-            return value_.size();
-         }
-
-         range_t range() const
-         {
-            return rp_;
-         }
-
-         range_t& range_ref()
-         {
-            return rp_;
-         }
-
-         const range_t& range_ref() const
-         {
-            return rp_;
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_cstringvarrng;
-         }
-
-      private:
-
-         const_string_range_node<T>& operator=(const const_string_range_node<T>&);
-
-         const std::string value_;
-         range_t rp_;
-      };
-
-      template <typename T>
-      class generic_string_range_node : public expression_node <T>,
-                                        public string_base_node<T>,
-                                        public range_interface <T>
-      {
-      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 typename range_t::cached_range_t cached_range_t;
-
-         generic_string_range_node(expression_ptr str_branch, range_t brange)
-         : initialised_(false),
-           branch_(str_branch),
-           branch_deletable_(branch_deletable(branch_)),
-           str_base_ptr_ (0),
-           str_range_ptr_(0),
-           base_range_(brange)
-         {
-            range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
-            range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
-            range_.cache.first  = range_.n0_c.second;
-            range_.cache.second = range_.n1_c.second;
-
-            if (is_generally_string_node(branch_))
+            
+            const char* base() const
             {
-               str_base_ptr_ = dynamic_cast<str_base_ptr>(branch_);
-
-               if (0 == str_base_ptr_)
-                  return;
-
-               str_range_ptr_ = dynamic_cast<irange_ptr>(branch_);
-
-               if (0 == str_range_ptr_)
-                  return;
+                return str0_node_ptr_->base();
             }
-
-            initialised_ = (str_base_ptr_ && str_range_ptr_);
-         }
-
-        ~generic_string_range_node()
-         {
-            base_range_.free();
-
-            if (branch_ && branch_deletable_)
+            
+            std::size_t size() const
             {
-               delete branch_;
-               branch_ = 0;
+                return str0_node_ptr_->size();
             }
-         }
-
-         inline T value() const
-         {
-            if (initialised_)
+            
+            range_t& range_ref()
             {
-               branch_->value();
-
-               std::size_t str_r0 = 0;
-               std::size_t str_r1 = 0;
-
-               std::size_t r0 = 0;
-               std::size_t r1 = 0;
-
-               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)
-                  )
-               {
-                  const std::size_t size = (r1 - r0) + 1;
-
-                  range_.n1_c.second  = size - 1;
-                  range_.cache.second = range_.n1_c.second;
-
-                  value_.assign(str_base_ptr_->base() + str_r0 + r0, size);
-               }
+                return str0_node_ptr_->range_ref();
             }
-
-            return std::numeric_limits<T>::quiet_NaN();
-         }
-
-         std::string str() const
-         {
-            return value_;
-         }
-
-         const char* base() const
-         {
-           return value_.data();
-         }
-
-         std::size_t size() const
-         {
-            return value_.size();
-         }
-
-         range_t& range_ref()
-         {
-            return range_;
-         }
-
-         const range_t& range_ref() const
-         {
-            return range_;
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_strgenrange;
-         }
-
-      private:
-
-         bool               initialised_;
-         expression_ptr          branch_;
-         bool          branch_deletable_;
-         str_base_ptr      str_base_ptr_;
-         irange_ptr       str_range_ptr_;
-         mutable range_t     base_range_;
-         mutable range_t          range_;
-         mutable std::string      value_;
-      };
-
-      template <typename T>
-      class string_concat_node : public binary_node     <T>,
-                                 public string_base_node<T>,
-                                 public range_interface <T>
-      {
-      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 typename range_t::cached_range_t cached_range_t;
-
-         string_concat_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_range_ptr_(0),
-           str1_range_ptr_(0)
-         {
-            range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
-            range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
-            range_.cache.first  = range_.n0_c.second;
-            range_.cache.second = range_.n1_c.second;
-
-            if (is_generally_string_node(binary_node<T>::branch_[0].first))
+            
+            const range_t& range_ref() const
             {
-               str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
-
-               if (0 == str0_base_ptr_)
-                  return;
-
-               str0_range_ptr_ = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first);
-
-               if (0 == str0_range_ptr_)
-                  return;
+                return str0_node_ptr_->range_ref();
             }
-
-            if (is_generally_string_node(binary_node<T>::branch_[1].first))
+            
+            inline typename expression_node<T>::node_type type() const
             {
-               str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);
-
-               if (0 == str1_base_ptr_)
-                  return;
-
-               str1_range_ptr_ = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
-
-               if (0 == str1_range_ptr_)
-                  return;
+                return expression_node<T>::e_strass;
             }
-
-            initialised_ = str0_base_ptr_  &&
-                           str1_base_ptr_  &&
-                           str0_range_ptr_ &&
-                           str1_range_ptr_ ;
-         }
-
-         inline T value() const
-         {
-            if (initialised_)
+            
+        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_;
+        };
+        
+        template <typename T>
+        class conditional_string_node : public trinary_node    <T>,
+        public string_base_node<T>,
+        public range_interface <T>
+        {
+        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;
+            
+            conditional_string_node(expression_ptr test,
+                                    expression_ptr consequent,
+                                    expression_ptr alternative)
+            : trinary_node<T>(details::e_default,consequent,alternative,test),
+            initialised_(false),
+            str0_base_ptr_ (0),
+            str1_base_ptr_ (0),
+            str0_range_ptr_(0),
+            str1_range_ptr_(0),
+            test_              (test),
+            consequent_  (consequent),
+            alternative_(alternative)
+            {
+                range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
+                range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
+                
+                range_.cache.first  = range_.n0_c.second;
+                range_.cache.second = range_.n1_c.second;
+                
+                if (is_generally_string_node(trinary_node<T>::branch_[0].first))
+                {
+                    str0_base_ptr_ = dynamic_cast<str_base_ptr>(trinary_node<T>::branch_[0].first);
+                    
+                    if (0 == str0_base_ptr_)
+                        return;
+                    
+                    str0_range_ptr_ = dynamic_cast<irange_ptr>(trinary_node<T>::branch_[0].first);
+                    
+                    if (0 == str0_range_ptr_)
+                        return;
+                }
+                
+                if (is_generally_string_node(trinary_node<T>::branch_[1].first))
+                {
+                    str1_base_ptr_ = dynamic_cast<str_base_ptr>(trinary_node<T>::branch_[1].first);
+                    
+                    if (0 == str1_base_ptr_)
+                        return;
+                    
+                    str1_range_ptr_ = dynamic_cast<irange_ptr>(trinary_node<T>::branch_[1].first);
+                    
+                    if (0 == str1_range_ptr_)
+                        return;
+                }
+                
+                initialised_ = str0_base_ptr_  &&
+                str1_base_ptr_  &&
+                str0_range_ptr_ &&
+                str1_range_ptr_ ;
+                
+            }
+            
+            inline T value() const
+            {
+                if (initialised_)
+                {
+                    std::size_t r0 = 0;
+                    std::size_t r1 = 0;
+                    
+                    if (is_true(test_))
+                    {
+                        consequent_->value();
+                        
+                        range_t& range = str0_range_ptr_->range_ref();
+                        
+                        if (range(r0,r1,str0_base_ptr_->size()))
+                        {
+                            const std::size_t size = (r1 - r0) + 1;
+                            
+                            value_.assign(str0_base_ptr_->base() + r0, size);
+                            
+                            range_.n1_c.second  = value_.size() - 1;
+                            range_.cache.second = range_.n1_c.second;
+                            
+                            return T(1);
+                        }
+                    }
+                    else
+                    {
+                        alternative_->value();
+                        
+                        range_t& range = str1_range_ptr_->range_ref();
+                        
+                        if (range(r0,r1,str1_base_ptr_->size()))
+                        {
+                            const std::size_t size = (r1 - r0) + 1;
+                            
+                            value_.assign(str1_base_ptr_->base() + r0, size);
+                            
+                            range_.n1_c.second  = value_.size() - 1;
+                            range_.cache.second = range_.n1_c.second;
+                            
+                            return T(0);
+                        }
+                    }
+                }
+                
+                return std::numeric_limits<T>::quiet_NaN();
+            }
+            
+            std::string str() const
             {
-               binary_node<T>::branch_[0].first->value();
-               binary_node<T>::branch_[1].first->value();
-
-               std::size_t str0_r0 = 0;
-               std::size_t str0_r1 = 0;
-
-               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();
-
-               if (
-                    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;
-                  const std::size_t size1 = (str1_r1 - str1_r0) + 1;
-
-                  value_.assign(str0_base_ptr_->base() + str0_r0, size0);
-                  value_.append(str1_base_ptr_->base() + str1_r0, size1);
-
-                  range_.n1_c.second  = value_.size() - 1;
-                  range_.cache.second = range_.n1_c.second;
-               }
+                return value_;
             }
-
-            return std::numeric_limits<T>::quiet_NaN();
-         }
-
-         std::string str() const
-         {
-            return value_;
-         }
-
-         const char* base() const
-         {
-           return value_.data();
-         }
-
-         std::size_t size() const
-         {
-            return value_.size();
-         }
-
-         range_t& range_ref()
-         {
-            return range_;
-         }
-
-         const range_t& range_ref() const
-         {
-            return range_;
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_strconcat;
-         }
-
-      private:
-
-         bool initialised_;
-         str_base_ptr str0_base_ptr_;
-         str_base_ptr str1_base_ptr_;
-         irange_ptr   str0_range_ptr_;
-         irange_ptr   str1_range_ptr_;
-         mutable range_t     range_;
-         mutable std::string value_;
-      };
-
-      template <typename T>
-      class swap_string_node : public binary_node     <T>,
-                               public string_base_node<T>,
-                               public range_interface <T>
-      {
-      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 typename range_t::cached_range_t cached_range_t;
-
-         swap_string_node(expression_ptr branch0, expression_ptr branch1)
-         : binary_node<T>(details::e_swap,branch0,branch1),
-           initialised_(false),
-           str0_node_ptr_(0),
-           str1_node_ptr_(0)
-         {
-            if (is_string_node(binary_node<T>::branch_[0].first))
+            
+            const char* base() const
             {
-               str0_node_ptr_ = static_cast<strvar_node_ptr>(binary_node<T>::branch_[0].first);
+                return &value_[0];
             }
-
-            if (is_string_node(binary_node<T>::branch_[1].first))
+            
+            std::size_t size() const
             {
-               str1_node_ptr_ = static_cast<strvar_node_ptr>(binary_node<T>::branch_[1].first);
+                return value_.size();
             }
-
-            initialised_ = (str0_node_ptr_ && str1_node_ptr_);
-         }
-
-         inline T value() const
-         {
-            if (initialised_)
+            
+            range_t& range_ref()
             {
-               binary_node<T>::branch_[0].first->value();
-               binary_node<T>::branch_[1].first->value();
-
-               std::swap(str0_node_ptr_->ref(),str1_node_ptr_->ref());
+                return range_;
             }
-
-            return std::numeric_limits<T>::quiet_NaN();
-         }
-
-         std::string str() const
-         {
-            return str0_node_ptr_->str();
-         }
-
-         const char* base() const
-         {
-           return str0_node_ptr_->base();
-         }
-
-         std::size_t size() const
-         {
-            return str0_node_ptr_->size();
-         }
-
-         range_t& range_ref()
-         {
-            return str0_node_ptr_->range_ref();
-         }
-
-         const range_t& range_ref() const
-         {
-            return str0_node_ptr_->range_ref();
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_strswap;
-         }
-
-      private:
-
-         bool initialised_;
-         strvar_node_ptr str0_node_ptr_;
-         strvar_node_ptr str1_node_ptr_;
-      };
-
-      template <typename T>
-      class stringvar_size_node : public expression_node<T>
-      {
-      public:
-
-         static std::string null_value;
-
-         explicit stringvar_size_node()
-         : value_(&null_value)
-         {}
-
-         explicit stringvar_size_node(std::string& v)
-         : value_(&v)
-         {}
-
-         inline T value() const
-         {
-            return T((*value_).size());
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_stringvarsize;
-         }
-
-      private:
-
-         std::string* value_;
-      };
-
-      template <typename T>
-      std::string stringvar_size_node<T>::null_value = std::string("");
-
-      template <typename T>
-      class string_size_node : public expression_node<T>
-      {
-      public:
-
-         typedef expression_node <T>* expression_ptr;
-         typedef string_base_node<T>*   str_base_ptr;
-
-         string_size_node(expression_ptr brnch)
-         : branch_(brnch),
-           branch_deletable_(branch_deletable(branch_)),
-           str_base_ptr_(0)
-         {
-            if (is_generally_string_node(branch_))
-            {
-               str_base_ptr_ = dynamic_cast<str_base_ptr>(branch_);
-
-               if (0 == str_base_ptr_)
-                  return;
+            
+            const range_t& range_ref() const
+            {
+                return range_;
             }
-         }
-
-        ~string_size_node()
-         {
-            if (branch_ && branch_deletable_)
+            
+            inline typename expression_node<T>::node_type type() const
             {
-               delete branch_;
-               branch_ = 0;
+                return expression_node<T>::e_strcondition;
             }
-         }
-
-         inline T value() const
-         {
-            T result = std::numeric_limits<T>::quiet_NaN();
-
-            if (str_base_ptr_)
+            
+        private:
+            
+            bool initialised_;
+            str_base_ptr str0_base_ptr_;
+            str_base_ptr str1_base_ptr_;
+            irange_ptr   str0_range_ptr_;
+            irange_ptr   str1_range_ptr_;
+            mutable range_t     range_;
+            mutable std::string value_;
+            
+            expression_ptr test_;
+            expression_ptr consequent_;
+            expression_ptr alternative_;
+        };
+        
+        template <typename T>
+        class cons_conditional_str_node : public binary_node     <T>,
+        public string_base_node<T>,
+        public range_interface <T>
+        {
+        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;
+            
+            cons_conditional_str_node(expression_ptr test,
+                                      expression_ptr consequent)
+            : binary_node<T>(details::e_default,consequent,test),
+            initialised_(false),
+            str0_base_ptr_ (0),
+            str0_range_ptr_(0),
+            test_      (test),
+            consequent_(consequent)
+            {
+                range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
+                range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
+                
+                range_.cache.first  = range_.n0_c.second;
+                range_.cache.second = range_.n1_c.second;
+                
+                if (is_generally_string_node(binary_node<T>::branch_[0].first))
+                {
+                    str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
+                    
+                    if (0 == str0_base_ptr_)
+                        return;
+                    
+                    str0_range_ptr_ = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first);
+                    
+                    if (0 == str0_range_ptr_)
+                        return;
+                }
+                
+                initialised_ = str0_base_ptr_ && str0_range_ptr_ ;
+            }
+            
+            inline T value() const
+            {
+                if (initialised_)
+                {
+                    if (is_true(test_))
+                    {
+                        consequent_->value();
+                        
+                        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()))
+                        {
+                            const std::size_t size = (r1 - r0) + 1;
+                            
+                            value_.assign(str0_base_ptr_->base() + r0, size);
+                            
+                            range_.n1_c.second  = value_.size() - 1;
+                            range_.cache.second = range_.n1_c.second;
+                            
+                            return T(1);
+                        }
+                    }
+                }
+                
+                return std::numeric_limits<T>::quiet_NaN();
+            }
+            
+            std::string str() const
             {
-               branch_->value();
-               result = T(str_base_ptr_->size());
+                return value_;
             }
-
-            return result;
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_stringsize;
-         }
-
-      private:
-
-         expression_ptr branch_;
-         bool branch_deletable_;
-         str_base_ptr str_base_ptr_;
-      };
-
-      struct asn_assignment
-      {
-         static inline void execute(std::string& s, const char* data, const std::size_t size)
-         { s.assign(data,size); }
-      };
-
-      struct asn_addassignment
-      {
-         static inline void execute(std::string& s, const char* data, const std::size_t size)
-         { s.append(data,size); }
-      };
-
-      template <typename T, typename AssignmentProcess = asn_assignment>
-      class assignment_string_node : public binary_node     <T>,
-                                     public string_base_node<T>,
-                                     public range_interface <T>
-      {
-      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 typename range_t::cached_range_t cached_range_t;
-
-         assignment_string_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),
-           str1_range_ptr_(0)
-         {
-            if (is_string_node(binary_node<T>::branch_[0].first))
-            {
-               str0_node_ptr_ = static_cast<strvar_node_ptr>(binary_node<T>::branch_[0].first);
-
-               str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
+            
+            const char* base() const
+            {
+                return &value_[0];
             }
-
-            if (is_generally_string_node(binary_node<T>::branch_[1].first))
+            
+            std::size_t size() const
             {
-               str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);
-
-               if (0 == str1_base_ptr_)
-                  return;
-
-               irange_ptr range_ptr = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
-
-               if (0 == range_ptr)
-                  return;
-
-               str1_range_ptr_ = &(range_ptr->range_ref());
+                return value_.size();
             }
-
-            initialised_ = str0_base_ptr_  &&
-                           str1_base_ptr_  &&
-                           str0_node_ptr_  &&
-                           str1_range_ptr_ ;
-         }
-
-         inline T value() const
-         {
-            if (initialised_)
+            
+            range_t& range_ref()
             {
-               binary_node<T>::branch_[1].first->value();
-
-               std::size_t r0 = 0;
-               std::size_t r1 = 0;
-
-               range_t& range = (*str1_range_ptr_);
-
-               if (range(r0,r1,str1_base_ptr_->size()))
-               {
-                  AssignmentProcess::execute(str0_node_ptr_->ref(),
-                                             str1_base_ptr_->base() + r0,
-                                             (r1 - r0) + 1);
-
-                  binary_node<T>::branch_[0].first->value();
-               }
+                return range_;
             }
-
-            return std::numeric_limits<T>::quiet_NaN();
-         }
-
-         std::string str() const
-         {
-            return str0_node_ptr_->str();
-         }
-
-         const char* base() const
-         {
-           return str0_node_ptr_->base();
-         }
-
-         std::size_t size() const
-         {
-            return str0_node_ptr_->size();
-         }
-
-         range_t& range_ref()
-         {
-            return str0_node_ptr_->range_ref();
-         }
-
-         const range_t& range_ref() const
-         {
-            return str0_node_ptr_->range_ref();
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_strass;
-         }
-
-      private:
-
-         bool            initialised_;
-         str_base_ptr    str0_base_ptr_;
-         str_base_ptr    str1_base_ptr_;
-         strvar_node_ptr str0_node_ptr_;
-         range_ptr       str1_range_ptr_;
-      };
-
-      template <typename T, typename AssignmentProcess = asn_assignment>
-      class assignment_string_range_node : public binary_node     <T>,
-                                           public string_base_node<T>,
-                                           public range_interface <T>
-      {
-      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 typename range_t::cached_range_t cached_range_t;
-
-         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)
-         {
-            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_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);
-
-               if (0 == range_ptr)
-                  return;
-
-               str0_range_ptr_ = &(range_ptr->range_ref());
+            
+            const range_t& range_ref() const
+            {
+                return range_;
             }
-
-            if (is_generally_string_node(binary_node<T>::branch_[1].first))
+            
+            inline typename expression_node<T>::node_type type() const
             {
-               str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);
-
-               if (0 == str1_base_ptr_)
-                  return;
-
-               irange_ptr range_ptr = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
-
-               if (0 == range_ptr)
-                  return;
-
-               str1_range_ptr_ = &(range_ptr->range_ref());
+                return expression_node<T>::e_strccondition;
             }
-
-            initialised_ = str0_base_ptr_  &&
-                           str1_base_ptr_  &&
-                           str0_node_ptr_  &&
-                           str0_range_ptr_ &&
-                           str1_range_ptr_ ;
-         }
-
-         inline T value() const
-         {
-            if (initialised_)
+            
+        private:
+            
+            bool initialised_;
+            str_base_ptr str0_base_ptr_;
+            irange_ptr   str0_range_ptr_;
+            mutable range_t     range_;
+            mutable std::string value_;
+            
+            expression_ptr test_;
+            expression_ptr consequent_;
+        };
+#endif
+        
+        template <typename T, std::size_t N>
+        inline T axn(T a, T x)
+        {
+            // a*x^n
+            return a * exprtk::details::numeric::fast_exp<T,N>::result(x);
+        }
+        
+        template <typename T, std::size_t N>
+        inline T axnb(T a, T x, T b)
+        {
+            // a*x^n+b
+            return a * exprtk::details::numeric::fast_exp<T,N>::result(x) + b;
+        }
+        
+        template <typename T>
+        struct sf_base
+        {
+            typedef typename details::functor_t<T>::Type Type;
+            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;
+        };
+        
+#define define_sfop3(NN,OP0,OP1)                   \
+template <typename T>                              \
+struct sf##NN##_op : public sf_base<T>             \
+{                                                  \
+typedef typename sf_base<T>::Type Type;         \
+static inline T process(Type x, Type y, Type z) \
+{                                               \
+return (OP0);                                \
+}                                               \
+static inline std::string id()                  \
+{                                               \
+return OP1;                                  \
+}                                               \
+};                                                 \
+
+        define_sfop3(00,(x + y) / z       ,"(t+t)/t")
+        define_sfop3(01,(x + y) * z       ,"(t+t)*t")
+        define_sfop3(02,(x + y) - z       ,"(t+t)-t")
+        define_sfop3(03,(x + y) + z       ,"(t+t)+t")
+        define_sfop3(04,(x - y) + z       ,"(t-t)+t")
+        define_sfop3(05,(x - y) / z       ,"(t-t)/t")
+        define_sfop3(06,(x - y) * z       ,"(t-t)*t")
+        define_sfop3(07,(x * y) + z       ,"(t*t)+t")
+        define_sfop3(08,(x * y) - z       ,"(t*t)-t")
+        define_sfop3(09,(x * y) / z       ,"(t*t)/t")
+        define_sfop3(10,(x * y) * z       ,"(t*t)*t")
+        define_sfop3(11,(x / y) + z       ,"(t/t)+t")
+        define_sfop3(12,(x / y) - z       ,"(t/t)-t")
+        define_sfop3(13,(x / y) / z       ,"(t/t)/t")
+        define_sfop3(14,(x / y) * z       ,"(t/t)*t")
+        define_sfop3(15,x / (y + z)       ,"t/(t+t)")
+        define_sfop3(16,x / (y - z)       ,"t/(t-t)")
+        define_sfop3(17,x / (y * z)       ,"t/(t*t)")
+        define_sfop3(18,x / (y / z)       ,"t/(t/t)")
+        define_sfop3(19,x * (y + z)       ,"t*(t+t)")
+        define_sfop3(20,x * (y - z)       ,"t*(t-t)")
+        define_sfop3(21,x * (y * z)       ,"t*(t*t)")
+        define_sfop3(22,x * (y / z)       ,"t*(t/t)")
+        define_sfop3(23,x - (y + z)       ,"t-(t+t)")
+        define_sfop3(24,x - (y - z)       ,"t-(t-t)")
+        define_sfop3(25,x - (y / z)       ,"t-(t/t)")
+        define_sfop3(26,x - (y * z)       ,"t-(t*t)")
+        define_sfop3(27,x + (y * z)       ,"t+(t*t)")
+        define_sfop3(28,x + (y / z)       ,"t+(t/t)")
+        define_sfop3(29,x + (y + z)       ,"t+(t+t)")
+        define_sfop3(30,x + (y - z)       ,"t+(t-t)")
+        define_sfop3(31,(axnb<T,2>(x,y,z)),"       ")
+        define_sfop3(32,(axnb<T,3>(x,y,z)),"       ")
+        define_sfop3(33,(axnb<T,4>(x,y,z)),"       ")
+        define_sfop3(34,(axnb<T,5>(x,y,z)),"       ")
+        define_sfop3(35,(axnb<T,6>(x,y,z)),"       ")
+        define_sfop3(36,(axnb<T,7>(x,y,z)),"       ")
+        define_sfop3(37,(axnb<T,8>(x,y,z)),"       ")
+        define_sfop3(38,(axnb<T,9>(x,y,z)),"       ")
+        define_sfop3(39,x * numeric::log(y)   + z,"")
+        define_sfop3(40,x * numeric::log(y)   - z,"")
+        define_sfop3(41,x * numeric::log10(y) + z,"")
+        define_sfop3(42,x * numeric::log10(y) - z,"")
+        define_sfop3(43,x * numeric::sin(y) + z  ,"")
+        define_sfop3(44,x * numeric::sin(y) - z  ,"")
+        define_sfop3(45,x * numeric::cos(y) + z  ,"")
+        define_sfop3(46,x * numeric::cos(y) - z  ,"")
+        define_sfop3(47,details::is_true(x) ? y : z,"")
+        
+#define define_sfop4(NN,OP0,OP1)                           \
+template <typename T>                                      \
+struct sf##NN##_op : public sf_base<T>                     \
+{                                                          \
+typedef typename sf_base<T>::Type Type;                 \
+static inline T process(Type x, Type y, Type z, Type w) \
+{                                                       \
+return (OP0);                                        \
+}                                                       \
+static inline std::string id() { return OP1; }          \
+};                                                         \
+
+        define_sfop4(48,(x + ((y + z) / w)),"t+((t+t)/t)")
+        define_sfop4(49,(x + ((y + z) * w)),"t+((t+t)*t)")
+        define_sfop4(50,(x + ((y - z) / w)),"t+((t-t)/t)")
+        define_sfop4(51,(x + ((y - z) * w)),"t+((t-t)*t)")
+        define_sfop4(52,(x + ((y * z) / w)),"t+((t*t)/t)")
+        define_sfop4(53,(x + ((y * z) * w)),"t+((t*t)*t)")
+        define_sfop4(54,(x + ((y / z) + w)),"t+((t/t)+t)")
+        define_sfop4(55,(x + ((y / z) / w)),"t+((t/t)/t)")
+        define_sfop4(56,(x + ((y / z) * w)),"t+((t/t)*t)")
+        define_sfop4(57,(x - ((y + z) / w)),"t-((t+t)/t)")
+        define_sfop4(58,(x - ((y + z) * w)),"t-((t+t)*t)")
+        define_sfop4(59,(x - ((y - z) / w)),"t-((t-t)/t)")
+        define_sfop4(60,(x - ((y - z) * w)),"t-((t-t)*t)")
+        define_sfop4(61,(x - ((y * z) / w)),"t-((t*t)/t)")
+        define_sfop4(62,(x - ((y * z) * w)),"t-((t*t)*t)")
+        define_sfop4(63,(x - ((y / z) / w)),"t-((t/t)/t)")
+        define_sfop4(64,(x - ((y / z) * w)),"t-((t/t)*t)")
+        define_sfop4(65,(((x + y) * z) - w),"((t+t)*t)-t")
+        define_sfop4(66,(((x - y) * z) - w),"((t-t)*t)-t")
+        define_sfop4(67,(((x * y) * z) - w),"((t*t)*t)-t")
+        define_sfop4(68,(((x / y) * z) - w),"((t/t)*t)-t")
+        define_sfop4(69,(((x + y) / z) - w),"((t+t)/t)-t")
+        define_sfop4(70,(((x - y) / z) - w),"((t-t)/t)-t")
+        define_sfop4(71,(((x * y) / z) - w),"((t*t)/t)-t")
+        define_sfop4(72,(((x / y) / z) - w),"((t/t)/t)-t")
+        define_sfop4(73,((x * y) + (z * w)),"(t*t)+(t*t)")
+        define_sfop4(74,((x * y) - (z * w)),"(t*t)-(t*t)")
+        define_sfop4(75,((x * y) + (z / w)),"(t*t)+(t/t)")
+        define_sfop4(76,((x * y) - (z / w)),"(t*t)-(t/t)")
+        define_sfop4(77,((x / y) + (z / w)),"(t/t)+(t/t)")
+        define_sfop4(78,((x / y) - (z / w)),"(t/t)-(t/t)")
+        define_sfop4(79,((x / y) - (z * w)),"(t/t)-(t*t)")
+        define_sfop4(80,(x / (y + (z * w))),"t/(t+(t*t))")
+        define_sfop4(81,(x / (y - (z * w))),"t/(t-(t*t))")
+        define_sfop4(82,(x * (y + (z * w))),"t*(t+(t*t))")
+        define_sfop4(83,(x * (y - (z * w))),"t*(t-(t*t))")
+        
+        define_sfop4(84,(axn<T,2>(x,y) + axn<T,2>(z,w)),"")
+        define_sfop4(85,(axn<T,3>(x,y) + axn<T,3>(z,w)),"")
+        define_sfop4(86,(axn<T,4>(x,y) + axn<T,4>(z,w)),"")
+        define_sfop4(87,(axn<T,5>(x,y) + axn<T,5>(z,w)),"")
+        define_sfop4(88,(axn<T,6>(x,y) + axn<T,6>(z,w)),"")
+        define_sfop4(89,(axn<T,7>(x,y) + axn<T,7>(z,w)),"")
+        define_sfop4(90,(axn<T,8>(x,y) + axn<T,8>(z,w)),"")
+        define_sfop4(91,(axn<T,9>(x,y) + axn<T,9>(z,w)),"")
+        define_sfop4(92,((details::is_true(x) && details::is_true(y)) ? z : w),"")
+        define_sfop4(93,((details::is_true(x) || details::is_true(y)) ? z : w),"")
+        define_sfop4(94,((x <  y) ? z : w),"")
+        define_sfop4(95,((x <= y) ? z : w),"")
+        define_sfop4(96,((x >  y) ? z : w),"")
+        define_sfop4(97,((x >= y) ? z : w),"")
+        define_sfop4(98,(details::is_true(numeric::equal(x,y)) ? z : w),"")
+        define_sfop4(99,(x * numeric::sin(y) + z * numeric::cos(w)),"")
+        
+        define_sfop4(ext00,((x + y) - (z * w)),"(t+t)-(t*t)")
+        define_sfop4(ext01,((x + y) - (z / w)),"(t+t)-(t/t)")
+        define_sfop4(ext02,((x + y) + (z * w)),"(t+t)+(t*t)")
+        define_sfop4(ext03,((x + y) + (z / w)),"(t+t)+(t/t)")
+        define_sfop4(ext04,((x - y) + (z * w)),"(t-t)+(t*t)")
+        define_sfop4(ext05,((x - y) + (z / w)),"(t-t)+(t/t)")
+        define_sfop4(ext06,((x - y) - (z * w)),"(t-t)-(t*t)")
+        define_sfop4(ext07,((x - y) - (z / w)),"(t-t)-(t/t)")
+        define_sfop4(ext08,((x + y) - (z - w)),"(t+t)-(t-t)")
+        define_sfop4(ext09,((x + y) + (z - w)),"(t+t)+(t-t)")
+        define_sfop4(ext10,((x + y) * (z - w)),"(t+t)*(t-t)")
+        define_sfop4(ext11,((x + y) / (z - w)),"(t+t)/(t-t)")
+        define_sfop4(ext12,((x - y) - (z + w)),"(t-t)-(t+t)")
+        define_sfop4(ext13,((x - y) + (z + w)),"(t-t)+(t+t)")
+        define_sfop4(ext14,((x - y) * (z + w)),"(t-t)*(t+t)")
+        define_sfop4(ext15,((x - y) / (z + w)),"(t-t)/(t+t)")
+        define_sfop4(ext16,((x * y) - (z + w)),"(t*t)-(t+t)")
+        define_sfop4(ext17,((x / y) - (z + w)),"(t/t)-(t+t)")
+        define_sfop4(ext18,((x * y) + (z + w)),"(t*t)+(t+t)")
+        define_sfop4(ext19,((x / y) + (z + w)),"(t/t)+(t+t)")
+        define_sfop4(ext20,((x * y) + (z - w)),"(t*t)+(t-t)")
+        define_sfop4(ext21,((x / y) + (z - w)),"(t/t)+(t-t)")
+        define_sfop4(ext22,((x * y) - (z - w)),"(t*t)-(t-t)")
+        define_sfop4(ext23,((x / y) - (z - w)),"(t/t)-(t-t)")
+        define_sfop4(ext24,((x + y) * (z * w)),"(t+t)*(t*t)")
+        define_sfop4(ext25,((x + y) * (z / w)),"(t+t)*(t/t)")
+        define_sfop4(ext26,((x + y) / (z * w)),"(t+t)/(t*t)")
+        define_sfop4(ext27,((x + y) / (z / w)),"(t+t)/(t/t)")
+        define_sfop4(ext28,((x - y) / (z * w)),"(t-t)/(t*t)")
+        define_sfop4(ext29,((x - y) / (z / w)),"(t-t)/(t/t)")
+        define_sfop4(ext30,((x - y) * (z * w)),"(t-t)*(t*t)")
+        define_sfop4(ext31,((x - y) * (z / w)),"(t-t)*(t/t)")
+        define_sfop4(ext32,((x * y) * (z + w)),"(t*t)*(t+t)")
+        define_sfop4(ext33,((x / y) * (z + w)),"(t/t)*(t+t)")
+        define_sfop4(ext34,((x * y) / (z + w)),"(t*t)/(t+t)")
+        define_sfop4(ext35,((x / y) / (z + w)),"(t/t)/(t+t)")
+        define_sfop4(ext36,((x * y) / (z - w)),"(t*t)/(t-t)")
+        define_sfop4(ext37,((x / y) / (z - w)),"(t/t)/(t-t)")
+        define_sfop4(ext38,((x * y) * (z - w)),"(t*t)*(t-t)")
+        define_sfop4(ext39,((x * y) / (z * w)),"(t*t)/(t*t)")
+        define_sfop4(ext40,((x / y) * (z / w)),"(t/t)*(t/t)")
+        define_sfop4(ext41,((x / y) * (z - w)),"(t/t)*(t-t)")
+        define_sfop4(ext42,((x * y) * (z * w)),"(t*t)*(t*t)")
+        define_sfop4(ext43,(x + (y * (z / w))),"t+(t*(t/t))")
+        define_sfop4(ext44,(x - (y * (z / w))),"t-(t*(t/t))")
+        define_sfop4(ext45,(x + (y / (z * w))),"t+(t/(t*t))")
+        define_sfop4(ext46,(x - (y / (z * w))),"t-(t/(t*t))")
+        define_sfop4(ext47,(((x - y) - z) * w),"((t-t)-t)*t")
+        define_sfop4(ext48,(((x - y) - z) / w),"((t-t)-t)/t")
+        define_sfop4(ext49,(((x - y) + z) * w),"((t-t)+t)*t")
+        define_sfop4(ext50,(((x - y) + z) / w),"((t-t)+t)/t")
+        define_sfop4(ext51,((x + (y - z)) * w),"(t+(t-t))*t")
+        define_sfop4(ext52,((x + (y - z)) / w),"(t+(t-t))/t")
+        define_sfop4(ext53,((x + y) / (z + w)),"(t+t)/(t+t)")
+        define_sfop4(ext54,((x - y) / (z - w)),"(t-t)/(t-t)")
+        define_sfop4(ext55,((x + y) * (z + w)),"(t+t)*(t+t)")
+        define_sfop4(ext56,((x - y) * (z - w)),"(t-t)*(t-t)")
+        define_sfop4(ext57,((x - y) + (z - w)),"(t-t)+(t-t)")
+        define_sfop4(ext58,((x - y) - (z - w)),"(t-t)-(t-t)")
+        define_sfop4(ext59,((x / y) + (z * w)),"(t/t)+(t*t)")
+        define_sfop4(ext60,(((x * y) * z) / w),"((t*t)*t)/t")
+        
+#undef define_sfop3
+#undef define_sfop4
+        
+        template <typename T, typename SpecialFunction>
+        class sf3_node : public trinary_node<T>
+        {
+        public:
+            
+            typedef expression_node<T>* expression_ptr;
+            
+            sf3_node(const operator_type& opr,
+                     expression_ptr branch0,
+                     expression_ptr branch1,
+                     expression_ptr branch2)
+            : trinary_node<T>(opr,branch0,branch1,branch2)
+            {}
+            
+            inline T value() const
             {
-               binary_node<T>::branch_[0].first->value();
-               binary_node<T>::branch_[1].first->value();
-
-               std::size_t s0_r0 = 0;
-               std::size_t s0_r1 = 0;
-
-               std::size_t s1_r0 = 0;
-               std::size_t s1_r1 = 0;
-
-               range_t& range0 = (*str0_range_ptr_);
-               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;
-
-                  std::copy(str1_base_ptr_->base() + s1_r0,
-                            str1_base_ptr_->base() + s1_r0 + size,
-                            const_cast<char*>(base() + s0_r0));
-               }
+                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();
+                
+                return SpecialFunction::process(x,y,z);
             }
-
-            return std::numeric_limits<T>::quiet_NaN();
-         }
-
-         std::string str() const
-         {
-            return str0_node_ptr_->str();
-         }
-
-         const char* base() const
-         {
-           return str0_node_ptr_->base();
-         }
-
-         std::size_t size() const
-         {
-            return str0_node_ptr_->size();
-         }
-
-         range_t& range_ref()
-         {
-            return str0_node_ptr_->range_ref();
-         }
-
-         const range_t& range_ref() const
-         {
-            return str0_node_ptr_->range_ref();
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_strass;
-         }
-
-      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_;
-      };
-      #endif
-
-      template <typename T, std::size_t N>
-      inline T axn(T a, T x)
-      {
-         // a*x^n
-         return a * exprtk::details::numeric::fast_exp<T,N>::result(x);
-      }
-
-      template <typename T, std::size_t N>
-      inline T axnb(T a, T x, T b)
-      {
-         // a*x^n+b
-         return a * exprtk::details::numeric::fast_exp<T,N>::result(x) + b;
-      }
-
-      template <typename T>
-      struct sf_base
-      {
-         typedef typename details::functor_t<T>::Type Type;
-         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;
-      };
-
-      #define define_sfop3(NN,OP0,OP1)                   \
-      template <typename T>                              \
-      struct sf##NN##_op : public sf_base<T>             \
-      {                                                  \
-         typedef typename sf_base<T>::Type Type;         \
-         static inline T process(Type x, Type y, Type z) \
-         {                                               \
-            return (OP0);                                \
-         }                                               \
-         static inline std::string id()                  \
-         {                                               \
-            return OP1;                                  \
-         }                                               \
-      };                                                 \
-
-      define_sfop3(00,(x + y) / z       ,"(t+t)/t")
-      define_sfop3(01,(x + y) * z       ,"(t+t)*t")
-      define_sfop3(02,(x + y) - z       ,"(t+t)-t")
-      define_sfop3(03,(x + y) + z       ,"(t+t)+t")
-      define_sfop3(04,(x - y) + z       ,"(t-t)+t")
-      define_sfop3(05,(x - y) / z       ,"(t-t)/t")
-      define_sfop3(06,(x - y) * z       ,"(t-t)*t")
-      define_sfop3(07,(x * y) + z       ,"(t*t)+t")
-      define_sfop3(08,(x * y) - z       ,"(t*t)-t")
-      define_sfop3(09,(x * y) / z       ,"(t*t)/t")
-      define_sfop3(10,(x * y) * z       ,"(t*t)*t")
-      define_sfop3(11,(x / y) + z       ,"(t/t)+t")
-      define_sfop3(12,(x / y) - z       ,"(t/t)-t")
-      define_sfop3(13,(x / y) / z       ,"(t/t)/t")
-      define_sfop3(14,(x / y) * z       ,"(t/t)*t")
-      define_sfop3(15,x / (y + z)       ,"t/(t+t)")
-      define_sfop3(16,x / (y - z)       ,"t/(t-t)")
-      define_sfop3(17,x / (y * z)       ,"t/(t*t)")
-      define_sfop3(18,x / (y / z)       ,"t/(t/t)")
-      define_sfop3(19,x * (y + z)       ,"t*(t+t)")
-      define_sfop3(20,x * (y - z)       ,"t*(t-t)")
-      define_sfop3(21,x * (y * z)       ,"t*(t*t)")
-      define_sfop3(22,x * (y / z)       ,"t*(t/t)")
-      define_sfop3(23,x - (y + z)       ,"t-(t+t)")
-      define_sfop3(24,x - (y - z)       ,"t-(t-t)")
-      define_sfop3(25,x - (y / z)       ,"t-(t/t)")
-      define_sfop3(26,x - (y * z)       ,"t-(t*t)")
-      define_sfop3(27,x + (y * z)       ,"t+(t*t)")
-      define_sfop3(28,x + (y / z)       ,"t+(t/t)")
-      define_sfop3(29,x + (y + z)       ,"t+(t+t)")
-      define_sfop3(30,x + (y - z)       ,"t+(t-t)")
-      define_sfop3(31,(axnb<T,2>(x,y,z)),"       ")
-      define_sfop3(32,(axnb<T,3>(x,y,z)),"       ")
-      define_sfop3(33,(axnb<T,4>(x,y,z)),"       ")
-      define_sfop3(34,(axnb<T,5>(x,y,z)),"       ")
-      define_sfop3(35,(axnb<T,6>(x,y,z)),"       ")
-      define_sfop3(36,(axnb<T,7>(x,y,z)),"       ")
-      define_sfop3(37,(axnb<T,8>(x,y,z)),"       ")
-      define_sfop3(38,(axnb<T,9>(x,y,z)),"       ")
-      define_sfop3(39,x * numeric::log(y)   + z,"")
-      define_sfop3(40,x * numeric::log(y)   - z,"")
-      define_sfop3(41,x * numeric::log10(y) + z,"")
-      define_sfop3(42,x * numeric::log10(y) - z,"")
-      define_sfop3(43,x * numeric::sin(y) + z  ,"")
-      define_sfop3(44,x * numeric::sin(y) - z  ,"")
-      define_sfop3(45,x * numeric::cos(y) + z  ,"")
-      define_sfop3(46,x * numeric::cos(y) - z  ,"")
-      define_sfop3(47,details::is_true(x) ? y : z,"")
-
-      #define define_sfop4(NN,OP0,OP1)                           \
-      template <typename T>                                      \
-      struct sf##NN##_op : public sf_base<T>                     \
-      {                                                          \
-         typedef typename sf_base<T>::Type Type;                 \
-         static inline T process(Type x, Type y, Type z, Type w) \
-         {                                                       \
-            return (OP0);                                        \
-         }                                                       \
-         static inline std::string id() { return OP1; }          \
-      };                                                         \
-
-      define_sfop4(48,(x + ((y + z) / w)),"t+((t+t)/t)")
-      define_sfop4(49,(x + ((y + z) * w)),"t+((t+t)*t)")
-      define_sfop4(50,(x + ((y - z) / w)),"t+((t-t)/t)")
-      define_sfop4(51,(x + ((y - z) * w)),"t+((t-t)*t)")
-      define_sfop4(52,(x + ((y * z) / w)),"t+((t*t)/t)")
-      define_sfop4(53,(x + ((y * z) * w)),"t+((t*t)*t)")
-      define_sfop4(54,(x + ((y / z) + w)),"t+((t/t)+t)")
-      define_sfop4(55,(x + ((y / z) / w)),"t+((t/t)/t)")
-      define_sfop4(56,(x + ((y / z) * w)),"t+((t/t)*t)")
-      define_sfop4(57,(x - ((y + z) / w)),"t-((t+t)/t)")
-      define_sfop4(58,(x - ((y + z) * w)),"t-((t+t)*t)")
-      define_sfop4(59,(x - ((y - z) / w)),"t-((t-t)/t)")
-      define_sfop4(60,(x - ((y - z) * w)),"t-((t-t)*t)")
-      define_sfop4(61,(x - ((y * z) / w)),"t-((t*t)/t)")
-      define_sfop4(62,(x - ((y * z) * w)),"t-((t*t)*t)")
-      define_sfop4(63,(x - ((y / z) / w)),"t-((t/t)/t)")
-      define_sfop4(64,(x - ((y / z) * w)),"t-((t/t)*t)")
-      define_sfop4(65,(((x + y) * z) - w),"((t+t)*t)-t")
-      define_sfop4(66,(((x - y) * z) - w),"((t-t)*t)-t")
-      define_sfop4(67,(((x * y) * z) - w),"((t*t)*t)-t")
-      define_sfop4(68,(((x / y) * z) - w),"((t/t)*t)-t")
-      define_sfop4(69,(((x + y) / z) - w),"((t+t)/t)-t")
-      define_sfop4(70,(((x - y) / z) - w),"((t-t)/t)-t")
-      define_sfop4(71,(((x * y) / z) - w),"((t*t)/t)-t")
-      define_sfop4(72,(((x / y) / z) - w),"((t/t)/t)-t")
-      define_sfop4(73,((x * y) + (z * w)),"(t*t)+(t*t)")
-      define_sfop4(74,((x * y) - (z * w)),"(t*t)-(t*t)")
-      define_sfop4(75,((x * y) + (z / w)),"(t*t)+(t/t)")
-      define_sfop4(76,((x * y) - (z / w)),"(t*t)-(t/t)")
-      define_sfop4(77,((x / y) + (z / w)),"(t/t)+(t/t)")
-      define_sfop4(78,((x / y) - (z / w)),"(t/t)-(t/t)")
-      define_sfop4(79,((x / y) - (z * w)),"(t/t)-(t*t)")
-      define_sfop4(80,(x / (y + (z * w))),"t/(t+(t*t))")
-      define_sfop4(81,(x / (y - (z * w))),"t/(t-(t*t))")
-      define_sfop4(82,(x * (y + (z * w))),"t*(t+(t*t))")
-      define_sfop4(83,(x * (y - (z * w))),"t*(t-(t*t))")
-
-      define_sfop4(84,(axn<T,2>(x,y) + axn<T,2>(z,w)),"")
-      define_sfop4(85,(axn<T,3>(x,y) + axn<T,3>(z,w)),"")
-      define_sfop4(86,(axn<T,4>(x,y) + axn<T,4>(z,w)),"")
-      define_sfop4(87,(axn<T,5>(x,y) + axn<T,5>(z,w)),"")
-      define_sfop4(88,(axn<T,6>(x,y) + axn<T,6>(z,w)),"")
-      define_sfop4(89,(axn<T,7>(x,y) + axn<T,7>(z,w)),"")
-      define_sfop4(90,(axn<T,8>(x,y) + axn<T,8>(z,w)),"")
-      define_sfop4(91,(axn<T,9>(x,y) + axn<T,9>(z,w)),"")
-      define_sfop4(92,((details::is_true(x) && details::is_true(y)) ? z : w),"")
-      define_sfop4(93,((details::is_true(x) || details::is_true(y)) ? z : w),"")
-      define_sfop4(94,((x <  y) ? z : w),"")
-      define_sfop4(95,((x <= y) ? z : w),"")
-      define_sfop4(96,((x >  y) ? z : w),"")
-      define_sfop4(97,((x >= y) ? z : w),"")
-      define_sfop4(98,(details::is_true(numeric::equal(x,y)) ? z : w),"")
-      define_sfop4(99,(x * numeric::sin(y) + z * numeric::cos(w)),"")
-
-      define_sfop4(ext00,((x + y) - (z * w)),"(t+t)-(t*t)")
-      define_sfop4(ext01,((x + y) - (z / w)),"(t+t)-(t/t)")
-      define_sfop4(ext02,((x + y) + (z * w)),"(t+t)+(t*t)")
-      define_sfop4(ext03,((x + y) + (z / w)),"(t+t)+(t/t)")
-      define_sfop4(ext04,((x - y) + (z * w)),"(t-t)+(t*t)")
-      define_sfop4(ext05,((x - y) + (z / w)),"(t-t)+(t/t)")
-      define_sfop4(ext06,((x - y) - (z * w)),"(t-t)-(t*t)")
-      define_sfop4(ext07,((x - y) - (z / w)),"(t-t)-(t/t)")
-      define_sfop4(ext08,((x + y) - (z - w)),"(t+t)-(t-t)")
-      define_sfop4(ext09,((x + y) + (z - w)),"(t+t)+(t-t)")
-      define_sfop4(ext10,((x + y) * (z - w)),"(t+t)*(t-t)")
-      define_sfop4(ext11,((x + y) / (z - w)),"(t+t)/(t-t)")
-      define_sfop4(ext12,((x - y) - (z + w)),"(t-t)-(t+t)")
-      define_sfop4(ext13,((x - y) + (z + w)),"(t-t)+(t+t)")
-      define_sfop4(ext14,((x - y) * (z + w)),"(t-t)*(t+t)")
-      define_sfop4(ext15,((x - y) / (z + w)),"(t-t)/(t+t)")
-      define_sfop4(ext16,((x * y) - (z + w)),"(t*t)-(t+t)")
-      define_sfop4(ext17,((x / y) - (z + w)),"(t/t)-(t+t)")
-      define_sfop4(ext18,((x * y) + (z + w)),"(t*t)+(t+t)")
-      define_sfop4(ext19,((x / y) + (z + w)),"(t/t)+(t+t)")
-      define_sfop4(ext20,((x * y) + (z - w)),"(t*t)+(t-t)")
-      define_sfop4(ext21,((x / y) + (z - w)),"(t/t)+(t-t)")
-      define_sfop4(ext22,((x * y) - (z - w)),"(t*t)-(t-t)")
-      define_sfop4(ext23,((x / y) - (z - w)),"(t/t)-(t-t)")
-      define_sfop4(ext24,((x + y) * (z * w)),"(t+t)*(t*t)")
-      define_sfop4(ext25,((x + y) * (z / w)),"(t+t)*(t/t)")
-      define_sfop4(ext26,((x + y) / (z * w)),"(t+t)/(t*t)")
-      define_sfop4(ext27,((x + y) / (z / w)),"(t+t)/(t/t)")
-      define_sfop4(ext28,((x - y) / (z * w)),"(t-t)/(t*t)")
-      define_sfop4(ext29,((x - y) / (z / w)),"(t-t)/(t/t)")
-      define_sfop4(ext30,((x - y) * (z * w)),"(t-t)*(t*t)")
-      define_sfop4(ext31,((x - y) * (z / w)),"(t-t)*(t/t)")
-      define_sfop4(ext32,((x * y) * (z + w)),"(t*t)*(t+t)")
-      define_sfop4(ext33,((x / y) * (z + w)),"(t/t)*(t+t)")
-      define_sfop4(ext34,((x * y) / (z + w)),"(t*t)/(t+t)")
-      define_sfop4(ext35,((x / y) / (z + w)),"(t/t)/(t+t)")
-      define_sfop4(ext36,((x * y) / (z - w)),"(t*t)/(t-t)")
-      define_sfop4(ext37,((x / y) / (z - w)),"(t/t)/(t-t)")
-      define_sfop4(ext38,((x * y) * (z - w)),"(t*t)*(t-t)")
-      define_sfop4(ext39,((x * y) / (z * w)),"(t*t)/(t*t)")
-      define_sfop4(ext40,((x / y) * (z / w)),"(t/t)*(t/t)")
-      define_sfop4(ext41,((x / y) * (z - w)),"(t/t)*(t-t)")
-      define_sfop4(ext42,((x * y) * (z * w)),"(t*t)*(t*t)")
-      define_sfop4(ext43,(x + (y * (z / w))),"t+(t*(t/t))")
-      define_sfop4(ext44,(x - (y * (z / w))),"t-(t*(t/t))")
-      define_sfop4(ext45,(x + (y / (z * w))),"t+(t/(t*t))")
-      define_sfop4(ext46,(x - (y / (z * w))),"t-(t/(t*t))")
-      define_sfop4(ext47,(((x - y) - z) * w),"((t-t)-t)*t")
-      define_sfop4(ext48,(((x - y) - z) / w),"((t-t)-t)/t")
-      define_sfop4(ext49,(((x - y) + z) * w),"((t-t)+t)*t")
-      define_sfop4(ext50,(((x - y) + z) / w),"((t-t)+t)/t")
-      define_sfop4(ext51,((x + (y - z)) * w),"(t+(t-t))*t")
-      define_sfop4(ext52,((x + (y - z)) / w),"(t+(t-t))/t")
-      define_sfop4(ext53,((x + y) / (z + w)),"(t+t)/(t+t)")
-      define_sfop4(ext54,((x - y) / (z - w)),"(t-t)/(t-t)")
-      define_sfop4(ext55,((x + y) * (z + w)),"(t+t)*(t+t)")
-      define_sfop4(ext56,((x - y) * (z - w)),"(t-t)*(t-t)")
-      define_sfop4(ext57,((x - y) + (z - w)),"(t-t)+(t-t)")
-      define_sfop4(ext58,((x - y) - (z - w)),"(t-t)-(t-t)")
-      define_sfop4(ext59,((x / y) + (z * w)),"(t/t)+(t*t)")
-
-      #undef define_sfop3
-      #undef define_sfop4
-
-      template <typename T, typename SpecialFunction>
-      class sf3_node : public trinary_node<T>
-      {
-      public:
-
-         typedef expression_node<T>* expression_ptr;
-
-         sf3_node(const operator_type& opr,
-                  expression_ptr branch0,
-                  expression_ptr branch1,
-                  expression_ptr branch2)
-         : trinary_node<T>(opr,branch0,branch1,branch2)
-         {}
-
-         inline T value() const
-         {
-            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();
-
-            return SpecialFunction::process(x,y,z);
-         }
-      };
-
-      template <typename T, typename SpecialFunction>
-      class sf4_node : public quaternary_node<T>
-      {
-      public:
-
-         typedef expression_node<T>* expression_ptr;
-
-         sf4_node(const operator_type& opr,
-                  expression_ptr branch0,
-                  expression_ptr branch1,
-                  expression_ptr branch2,
-                  expression_ptr branch3)
-         : quaternary_node<T>(opr,branch0,branch1,branch2,branch3)
-         {}
-
-         inline T value() const
-         {
-            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();
-            const T w = quaternary_node<T>::branch_[3].first->value();
-
-            return SpecialFunction::process(x,y,z,w);
-         }
-      };
-
-      template <typename T, typename SpecialFunction>
-      class sf3_var_node : public expression_node<T>
-      {
-      public:
-
-         typedef expression_node<T>* expression_ptr;
-
-         sf3_var_node(const T& v0, const T& v1, const T& v2)
-         : v0_(v0),
-           v1_(v1),
-           v2_(v2)
-         {}
-
-         inline T value() const
-         {
-            return SpecialFunction::process(v0_,v1_,v2_);
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_trinary;
-         }
-
-      private:
-
-         sf3_var_node(sf3_var_node<T,SpecialFunction>&);
-         sf3_var_node<T,SpecialFunction>& operator=(sf3_var_node<T,SpecialFunction>&);
-
-         const T& v0_;
-         const T& v1_;
-         const T& v2_;
-      };
-
-      template <typename T, typename SpecialFunction>
-      class sf4_var_node : public expression_node<T>
-      {
-      public:
-
-         typedef expression_node<T>* expression_ptr;
-
-         sf4_var_node(const T& v0, const T& v1, const T& v2, const T& v3)
-         : v0_(v0),
-           v1_(v1),
-           v2_(v2),
-           v3_(v3)
-         {}
-
-         inline T value() const
-         {
-            return SpecialFunction::process(v0_,v1_,v2_,v3_);
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_trinary;
-         }
-
-      private:
-
-         sf4_var_node(sf4_var_node<T,SpecialFunction>&);
-         sf4_var_node<T,SpecialFunction>& operator=(sf4_var_node<T,SpecialFunction>&);
-
-         const T& v0_;
-         const T& v1_;
-         const T& v2_;
-         const T& v3_;
-      };
-
-      template <typename T, typename VarArgFunction>
-      class vararg_node : public expression_node<T>
-      {
-      public:
-
-         typedef expression_node<T>* expression_ptr;
-
-         template <typename Allocator,
-                   template <typename,typename> class Sequence>
-         vararg_node(const Sequence<expression_ptr,Allocator>& arg_list)
-         {
-            arg_list_.resize(arg_list.size());
-            delete_branch_.resize(arg_list.size());
-
-            for (std::size_t i = 0; i < arg_list.size(); ++i)
+        };
+        
+        template <typename T, typename SpecialFunction>
+        class sf4_node : public quaternary_node<T>
+        {
+        public:
+            
+            typedef expression_node<T>* expression_ptr;
+            
+            sf4_node(const operator_type& opr,
+                     expression_ptr branch0,
+                     expression_ptr branch1,
+                     expression_ptr branch2,
+                     expression_ptr branch3)
+            : quaternary_node<T>(opr,branch0,branch1,branch2,branch3)
+            {}
+            
+            inline T value() const
             {
-               if (arg_list[i])
-               {
-                       arg_list_[i] = arg_list[i];
-                  delete_branch_[i] = static_cast<unsigned char>(branch_deletable(arg_list_[i]) ? 1 : 0);
-               }
-               else
-               {
-                  arg_list_.clear();
-                  delete_branch_.clear();
-                  return;
-               }
-            }
-         }
-
-        ~vararg_node()
-         {
-            for (std::size_t i = 0; i < arg_list_.size(); ++i)
+                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();
+                const T w = quaternary_node<T>::branch_[3].first->value();
+                
+                return SpecialFunction::process(x,y,z,w);
+            }
+        };
+        
+        template <typename T, typename SpecialFunction>
+        class sf3_var_node : public expression_node<T>
+        {
+        public:
+            
+            typedef expression_node<T>* expression_ptr;
+            
+            sf3_var_node(const T& v0, const T& v1, const T& v2)
+            : v0_(v0),
+            v1_(v1),
+            v2_(v2)
+            {}
+            
+            inline T value() const
             {
-               if (arg_list_[i] && delete_branch_[i])
-               {
-                  delete arg_list_[i];
-                  arg_list_[i] = 0;
-               }
+                return SpecialFunction::process(v0_,v1_,v2_);
             }
-         }
-
-         inline T value() const
-         {
-            if (!arg_list_.empty())
-               return VarArgFunction::process(arg_list_);
-            else
-               return std::numeric_limits<T>::quiet_NaN();
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_vararg;
-         }
-
-      private:
-
-         std::vector<expression_ptr> arg_list_;
-         std::vector<unsigned char> delete_branch_;
-      };
-
-      template <typename T, typename VarArgFunction>
-      class vararg_varnode : public expression_node<T>
-      {
-      public:
-
-         typedef expression_node<T>* expression_ptr;
-
-         template <typename Allocator,
-                   template <typename,typename> class Sequence>
-         vararg_varnode(const Sequence<expression_ptr,Allocator>& arg_list)
-         {
-            arg_list_.resize(arg_list.size());
-
-            for (std::size_t i = 0; i < arg_list.size(); ++i)
+            
+            inline typename expression_node<T>::node_type type() const
             {
-               if (arg_list[i] && is_variable_node(arg_list[i]))
-               {
-                  variable_node<T>* var_node_ptr = static_cast<variable_node<T>*>(arg_list[i]);
-                  arg_list_[i] = (&var_node_ptr->ref());
-               }
-               else
-               {
-                  arg_list_.clear();
-                  return;
-               }
-            }
-         }
-
-         inline T value() const
-         {
-            if (!arg_list_.empty())
-               return VarArgFunction::process(arg_list_);
-            else
-               return std::numeric_limits<T>::quiet_NaN();
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_vararg;
-         }
-
-      private:
-
-         std::vector<const T*> arg_list_;
-      };
-
-      template <typename T, typename VecFunction>
-      class vectorize_node : public expression_node<T>
-      {
-      public:
-
-         typedef expression_node<T>* expression_ptr;
-
-         vectorize_node(const expression_ptr v)
-         : ivec_ptr_(0),
-           v_(v),
-           v_deletable_(branch_deletable(v_))
-         {
-            if (is_ivector_node(v))
+                return expression_node<T>::e_trinary;
+            }
+            
+        private:
+            
+            sf3_var_node(sf3_var_node<T,SpecialFunction>&);
+            sf3_var_node<T,SpecialFunction>& operator=(sf3_var_node<T,SpecialFunction>&);
+            
+            const T& v0_;
+            const T& v1_;
+            const T& v2_;
+        };
+        
+        template <typename T, typename SpecialFunction>
+        class sf4_var_node : public expression_node<T>
+        {
+        public:
+            
+            typedef expression_node<T>* expression_ptr;
+            
+            sf4_var_node(const T& v0, const T& v1, const T& v2, const T& v3)
+            : v0_(v0),
+            v1_(v1),
+            v2_(v2),
+            v3_(v3)
+            {}
+            
+            inline T value() const
+            {
+                return SpecialFunction::process(v0_,v1_,v2_,v3_);
+            }
+            
+            inline typename expression_node<T>::node_type type() const
+            {
+                return expression_node<T>::e_trinary;
+            }
+            
+        private:
+            
+            sf4_var_node(sf4_var_node<T,SpecialFunction>&);
+            sf4_var_node<T,SpecialFunction>& operator=(sf4_var_node<T,SpecialFunction>&);
+            
+            const T& v0_;
+            const T& v1_;
+            const T& v2_;
+            const T& v3_;
+        };
+        
+        template <typename T, typename VarArgFunction>
+        class vararg_node : public expression_node<T>
+        {
+        public:
+            
+            typedef expression_node<T>* expression_ptr;
+            
+            template <typename Allocator,
+            template <typename,typename> class Sequence>
+            vararg_node(const Sequence<expression_ptr,Allocator>& arg_list)
+            {
+                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);
+                    }
+                    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])
+                    {
+                        delete arg_list_[i];
+                        arg_list_[i] = 0;
+                    }
+                }
+            }
+            
+            inline T value() const
+            {
+                if (!arg_list_.empty())
+                    return VarArgFunction::process(arg_list_);
+                else
+                    return std::numeric_limits<T>::quiet_NaN();
+            }
+            
+            inline typename expression_node<T>::node_type type() const
+            {
+                return expression_node<T>::e_vararg;
+            }
+            
+        private:
+            
+            std::vector<expression_ptr> arg_list_;
+            std::vector<unsigned char> delete_branch_;
+        };
+        
+        template <typename T, typename VarArgFunction>
+        class vararg_varnode : public expression_node<T>
+        {
+        public:
+            
+            typedef expression_node<T>* expression_ptr;
+            
+            template <typename Allocator,
+            template <typename,typename> class Sequence>
+            vararg_varnode(const Sequence<expression_ptr,Allocator>& arg_list)
+            {
+                arg_list_.resize(arg_list.size());
+                
+                for (std::size_t i = 0; i < arg_list.size(); ++i)
+                {
+                    if (arg_list[i] && is_variable_node(arg_list[i]))
+                    {
+                        variable_node<T>* var_node_ptr = static_cast<variable_node<T>*>(arg_list[i]);
+                        arg_list_[i] = (&var_node_ptr->ref());
+                    }
+                    else
+                    {
+                        arg_list_.clear();
+                        return;
+                    }
+                }
+            }
+            
+            inline T value() const
             {
-               ivec_ptr_ = dynamic_cast<vector_interface<T>*>(v);
+                if (!arg_list_.empty())
+                    return VarArgFunction::process(arg_list_);
+                else
+                    return std::numeric_limits<T>::quiet_NaN();
             }
-            else
-               ivec_ptr_ = 0;
-         }
-
-        ~vectorize_node()
-         {
-            if (v_ && v_deletable_)
+            
+            inline typename expression_node<T>::node_type type() const
             {
-               delete v_;
+                return expression_node<T>::e_vararg;
             }
-         }
-
-         inline T value() const
-         {
-            if (ivec_ptr_)
+            
+        private:
+            
+            std::vector<const T*> arg_list_;
+        };
+        
+        template <typename T, typename VecFunction>
+        class vectorize_node : public expression_node<T>
+        {
+        public:
+            
+            typedef expression_node<T>* expression_ptr;
+            
+            vectorize_node(const expression_ptr v)
+            : ivec_ptr_(0),
+            v_(v),
+            v_deletable_(branch_deletable(v_))
+            {
+                if (is_ivector_node(v))
+                {
+                    ivec_ptr_ = dynamic_cast<vector_interface<T>*>(v);
+                }
+                else
+                    ivec_ptr_ = 0;
+            }
+            
+            ~vectorize_node()
+            {
+                if (v_ && v_deletable_)
+                {
+                    delete v_;
+                }
+            }
+            
+            inline T value() const
+            {
+                if (ivec_ptr_)
+                {
+                    v_->value();
+                    return VecFunction::process(ivec_ptr_);
+                }
+                else
+                    return std::numeric_limits<T>::quiet_NaN();
+            }
+            
+            inline typename expression_node<T>::node_type type() const
+            {
+                return expression_node<T>::e_vecfunc;
+            }
+            
+        private:
+            
+            vector_interface<T>* ivec_ptr_;
+            expression_ptr v_;
+            bool v_deletable_;
+        };
+        
+        template <typename T>
+        class assignment_node : public binary_node<T>
+        {
+        public:
+            
+            typedef expression_node<T>* expression_ptr;
+            
+            assignment_node(const operator_type& opr,
+                            expression_ptr branch0,
+                            expression_ptr branch1)
+            : binary_node<T>(opr,branch0,branch1),
+            var_node_ptr_(0)
+            {
+                if (is_variable_node(binary_node<T>::branch_[0].first))
+                {
+                    var_node_ptr_ = static_cast<variable_node<T>*>(binary_node<T>::branch_[0].first);
+                }
+            }
+            
+            inline T value() const
+            {
+                if (var_node_ptr_)
+                {
+                    T& result = var_node_ptr_->ref();
+                    
+                    result = binary_node<T>::branch_[1].first->value();
+                    
+                    return result;
+                }
+                else
+                    return std::numeric_limits<T>::quiet_NaN();
+            }
+            
+        private:
+            
+            variable_node<T>* var_node_ptr_;
+        };
+        
+        template <typename T>
+        class assignment_vec_elem_node : public binary_node<T>
+        {
+        public:
+            
+            typedef expression_node<T>* expression_ptr;
+            
+            assignment_vec_elem_node(const operator_type& opr,
+                                     expression_ptr branch0,
+                                     expression_ptr branch1)
+            : binary_node<T>(opr,branch0,branch1),
+            vec_node_ptr_(0)
+            {
+                if (is_vector_elem_node(binary_node<T>::branch_[0].first))
+                {
+                    vec_node_ptr_ = static_cast<vector_elem_node<T>*>(binary_node<T>::branch_[0].first);
+                }
+            }
+            
+            inline T value() const
+            {
+                if (vec_node_ptr_)
+                {
+                    T& result = vec_node_ptr_->ref();
+                    
+                    result = binary_node<T>::branch_[1].first->value();
+                    
+                    return result;
+                }
+                else
+                    return std::numeric_limits<T>::quiet_NaN();
+            }
+            
+        private:
+            
+            vector_elem_node<T>* vec_node_ptr_;
+        };
+        
+        template <typename T>
+        class assignment_rebasevec_elem_node : public binary_node<T>
+        {
+        public:
+            
+            typedef expression_node<T>* expression_ptr;
+            
+            assignment_rebasevec_elem_node(const operator_type& opr,
+                                           expression_ptr branch0,
+                                           expression_ptr branch1)
+            : binary_node<T>(opr,branch0,branch1),
+            rbvec_node_ptr_(0)
+            {
+                if (is_rebasevector_elem_node(binary_node<T>::branch_[0].first))
+                {
+                    rbvec_node_ptr_ = static_cast<rebasevector_elem_node<T>*>(binary_node<T>::branch_[0].first);
+                }
+            }
+            
+            inline T value() const
+            {
+                if (rbvec_node_ptr_)
+                {
+                    T& result = rbvec_node_ptr_->ref();
+                    
+                    result = binary_node<T>::branch_[1].first->value();
+                    
+                    return result;
+                }
+                else
+                    return std::numeric_limits<T>::quiet_NaN();
+            }
+            
+        private:
+            
+            rebasevector_elem_node<T>* rbvec_node_ptr_;
+        };
+        
+        template <typename T>
+        class assignment_rebasevec_celem_node : public binary_node<T>
+        {
+        public:
+            
+            typedef expression_node<T>* expression_ptr;
+            
+            assignment_rebasevec_celem_node(const operator_type& opr,
+                                            expression_ptr branch0,
+                                            expression_ptr branch1)
+            : binary_node<T>(opr,branch0,branch1),
+            rbvec_node_ptr_(0)
+            {
+                if (is_rebasevector_celem_node(binary_node<T>::branch_[0].first))
+                {
+                    rbvec_node_ptr_ = static_cast<rebasevector_celem_node<T>*>(binary_node<T>::branch_[0].first);
+                }
+            }
+            
+            inline T value() const
+            {
+                if (rbvec_node_ptr_)
+                {
+                    T& result = rbvec_node_ptr_->ref();
+                    
+                    result = binary_node<T>::branch_[1].first->value();
+                    
+                    return result;
+                }
+                else
+                    return std::numeric_limits<T>::quiet_NaN();
+            }
+            
+        private:
+            
+            rebasevector_celem_node<T>* rbvec_node_ptr_;
+        };
+        
+        template <typename T>
+        class assignment_vec_node : public binary_node     <T>,
+        public vector_interface<T>
+        {
+        public:
+            
+            typedef expression_node<T>* expression_ptr;
+            typedef vector_node<T>*    vector_node_ptr;
+            typedef vec_data_store<T>            vds_t;
+            
+            assignment_vec_node(const operator_type& opr,
+                                expression_ptr branch0,
+                                expression_ptr branch1)
+            : binary_node<T>(opr,branch0,branch1),
+            vec_node_ptr_(0)
+            {
+                if (is_vector_node(binary_node<T>::branch_[0].first))
+                {
+                    vec_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);
+                    vds()         = vec_node_ptr_->vds();
+                }
+            }
+            
+            inline T value() const
+            {
+                if (vec_node_ptr_)
+                {
+                    const T v = binary_node<T>::branch_[1].first->value();
+                    
+                    T* vec = vds().data();
+                    
+                    loop_unroll::details lud(size());
+                    const T* upper_bound = vec + lud.upper_bound;
+                    
+                    while (vec < upper_bound)
+                    {
+#define exprtk_loop(N) \
+vec[N] = v;           \
+
+                        exprtk_loop( 0) exprtk_loop( 1)
+                        exprtk_loop( 2) exprtk_loop( 3)
+#ifndef exprtk_disable_superscalar_unroll
+                        exprtk_loop( 4) exprtk_loop( 5)
+                        exprtk_loop( 6) exprtk_loop( 7)
+                        exprtk_loop( 8) exprtk_loop( 9)
+                        exprtk_loop(10) exprtk_loop(11)
+                        exprtk_loop(12) exprtk_loop(13)
+                        exprtk_loop(14) exprtk_loop(15)
+#endif
+                        
+                        vec += lud.batch_size;
+                    }
+                    
+                    switch (lud.remainder)
+                    {
+#define case_stmt(N) \
+case N : *vec++ = v; \
+
+#ifndef exprtk_disable_superscalar_unroll
+                            case_stmt(15) case_stmt(14)
+                            case_stmt(13) case_stmt(12)
+                            case_stmt(11) case_stmt(10)
+                            case_stmt( 9) case_stmt( 8)
+                            case_stmt( 7) case_stmt( 6)
+                            case_stmt( 5) case_stmt( 4)
+#endif
+                            case_stmt( 3) case_stmt( 2)
+                            case_stmt( 1)
+                    }
+                    
+#undef exprtk_loop
+#undef case_stmt
+                    
+                    return vec_node_ptr_->value();
+                }
+                else
+                    return std::numeric_limits<T>::quiet_NaN();
+            }
+            
+            vector_node_ptr vec() const
             {
-               v_->value();
-               return VecFunction::process(ivec_ptr_);
+                return vec_node_ptr_;
             }
-            else
-               return std::numeric_limits<T>::quiet_NaN();
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_vecfunc;
-         }
-
-      private:
-
-         vector_interface<T>* ivec_ptr_;
-         expression_ptr v_;
-         bool v_deletable_;
-      };
-
-      template <typename T>
-      class assignment_node : public binary_node<T>
-      {
-      public:
-
-         typedef expression_node<T>* expression_ptr;
-
-         assignment_node(const operator_type& opr,
-                         expression_ptr branch0,
-                         expression_ptr branch1)
-         : binary_node<T>(opr,branch0,branch1),
-           var_node_ptr_(0)
-         {
-            if (is_variable_node(binary_node<T>::branch_[0].first))
+            
+            vector_node_ptr vec()
             {
-               var_node_ptr_ = static_cast<variable_node<T>*>(binary_node<T>::branch_[0].first);
+                return vec_node_ptr_;
             }
-         }
-
-         inline T value() const
-         {
-            if (var_node_ptr_)
+            
+            inline typename expression_node<T>::node_type type() const
             {
-               T& result = var_node_ptr_->ref();
-               result = binary_node<T>::branch_[1].first->value();
-
-               return result;
+                return expression_node<T>::e_vecvalass;
             }
-            else
-               return std::numeric_limits<T>::quiet_NaN();
-         }
-
-      private:
-
-         variable_node<T>* var_node_ptr_;
-      };
-
-      template <typename T>
-      class assignment_vec_elem_node : public binary_node<T>
-      {
-      public:
-
-         typedef expression_node<T>* expression_ptr;
-
-         assignment_vec_elem_node(const operator_type& opr,
-                                  expression_ptr branch0,
-                                  expression_ptr branch1)
-         : binary_node<T>(opr,branch0,branch1),
-           vec_node_ptr_(0)
-         {
-            if (is_vector_elem_node(binary_node<T>::branch_[0].first))
+            
+            std::size_t size() const
             {
-               vec_node_ptr_ = static_cast<vector_elem_node<T>*>(binary_node<T>::branch_[0].first);
+                return vds().size();
             }
-         }
-
-         inline T value() const
-         {
-            if (vec_node_ptr_)
+            
+            vds_t& vds()
             {
-               T& result = vec_node_ptr_->ref();
-               result = binary_node<T>::branch_[1].first->value();
-
-               return result;
+                return vds_;
             }
-            else
-               return std::numeric_limits<T>::quiet_NaN();
-         }
-
-      private:
-
-         vector_elem_node<T>* vec_node_ptr_;
-      };
-
-      template <typename T>
-      class assignment_vec_node : public binary_node<T>,
-                                  public vector_interface<T>
-      {
-      public:
-
-         typedef expression_node<T>* expression_ptr;
-         typedef vector_node<T>*    vector_node_ptr;
-
-         assignment_vec_node(const operator_type& opr,
-                             expression_ptr branch0,
-                             expression_ptr branch1)
-         : binary_node<T>(opr,branch0,branch1),
-           vec_node_ptr_(0),
-           vec_size_    (0)
-         {
-            if (is_vector_node(binary_node<T>::branch_[0].first))
+            
+            const vds_t& vds() const
             {
-               vec_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);
-               vec_size_     = vec_node_ptr_->ref().size();
+                return vds_;
             }
-         }
-
-         inline T value() const
-         {
-            if (vec_node_ptr_)
+            
+        private:
+            
+            vector_node<T>* vec_node_ptr_;
+            vds_t           vds_;
+        };
+        
+        template <typename T>
+        class assignment_vecvec_node : public binary_node     <T>,
+        public vector_interface<T>
+        {
+        public:
+            
+            typedef expression_node<T>*  expression_ptr;
+            typedef vector_node<T>*     vector_node_ptr;
+            typedef vec_data_store<T>             vds_t;
+            
+            assignment_vecvec_node(const operator_type& opr,
+                                   expression_ptr branch0,
+                                   expression_ptr branch1)
+            : binary_node<T>(opr,branch0,branch1),
+            vec0_node_ptr_(0),
+            vec1_node_ptr_(0),
+            initialised_(false),
+            src_is_ivec_(false)
+            {
+                if (is_vector_node(binary_node<T>::branch_[0].first))
+                {
+                    vec0_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);
+                    vds()          = vec0_node_ptr_->vds();
+                }
+                
+                if (is_vector_node(binary_node<T>::branch_[1].first))
+                {
+                    vec1_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[1].first);
+                    vds_t::match_sizes(vds(),vec1_node_ptr_->vds());
+                }
+                else if (is_ivector_node(binary_node<T>::branch_[1].first))
+                {
+                    vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
+                    
+                    if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
+                    {
+                        vec1_node_ptr_ = vi->vec();
+                        
+                        if (!vi->side_effect())
+                        {
+                            vi->vds()    = vds();
+                            src_is_ivec_ = true;
+                        }
+                        else
+                            vds_t::match_sizes(vds(),vi->vds());
+                    }
+                }
+                
+                initialised_ = (vec0_node_ptr_ && vec1_node_ptr_);
+            }
+            
+            inline T value() const
+            {
+                if (initialised_)
+                {
+                    binary_node<T>::branch_[1].first->value();
+                    
+                    if (src_is_ivec_)
+                        return vec0_node_ptr_->value();
+                    
+                    T* vec0 = vec0_node_ptr_->vds().data();
+                    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] = vec1[N];     \
+
+                        exprtk_loop( 0) exprtk_loop( 1)
+                        exprtk_loop( 2) exprtk_loop( 3)
+#ifndef exprtk_disable_superscalar_unroll
+                        exprtk_loop( 4) exprtk_loop( 5)
+                        exprtk_loop( 6) exprtk_loop( 7)
+                        exprtk_loop( 8) exprtk_loop( 9)
+                        exprtk_loop(10) exprtk_loop(11)
+                        exprtk_loop(12) exprtk_loop(13)
+                        exprtk_loop(14) exprtk_loop(15)
+#endif
+                        
+                        vec0 += lud.batch_size;
+                        vec1 += lud.batch_size;
+                    }
+                    
+                    switch (lud.remainder)
+                    {
+#define case_stmt(N)        \
+case N : *vec0++ = *vec1++; \
+
+#ifndef exprtk_disable_superscalar_unroll
+                            case_stmt(15) case_stmt(14)
+                            case_stmt(13) case_stmt(12)
+                            case_stmt(11) case_stmt(10)
+                            case_stmt( 9) case_stmt( 8)
+                            case_stmt( 7) case_stmt( 6)
+                            case_stmt( 5) case_stmt( 4)
+#endif
+                            case_stmt( 3) case_stmt( 2)
+                            case_stmt( 1)
+                    }
+                    
+#undef exprtk_loop
+#undef case_stmt
+                    
+                    return vec0_node_ptr_->value();
+                }
+                else
+                    return std::numeric_limits<T>::quiet_NaN();
+            }
+            
+            vector_node_ptr vec() const
             {
-               vector_holder<T>& vec_hldr = vec_node_ptr_->ref();
-               const T v = binary_node<T>::branch_[1].first->value();
-
-               for (std::size_t i = 0; i < vec_size_; ++i)
-               {
-                  (*vec_hldr[i]) = v;
-               }
-
-               return vec_node_ptr_->value();
+                return vec0_node_ptr_;
             }
-            else
-               return std::numeric_limits<T>::quiet_NaN();
-         }
-
-         vector_node_ptr vec() const
-         {
-            return vec_node_ptr_;
-         }
-
-         vector_node_ptr vec()
-         {
-            return vec_node_ptr_;
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_vecvalass;
-         }
-
-         std::size_t size() const
-         {
-            return vec_size_;
-         }
-
-      private:
-
-         vector_node<T>* vec_node_ptr_;
-         std::size_t     vec_size_;
-      };
-
-      template <typename T>
-      class assignment_vecvec_node : public binary_node<T>,
-                                     public vector_interface<T>
-      {
-      public:
-
-         typedef expression_node<T>* expression_ptr;
-         typedef vector_node<T>*     vector_node_ptr;
-
-         assignment_vecvec_node(const operator_type& opr,
-                                expression_ptr branch0,
-                                expression_ptr branch1)
-         : binary_node<T>(opr,branch0,branch1),
-           vec0_node_ptr_(0),
-           vec1_node_ptr_(0),
-           vec_size_     (0)
-         {
-            if (is_vector_node(binary_node<T>::branch_[0].first))
+            
+            vector_node_ptr vec()
             {
-               vec0_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);
+                return vec0_node_ptr_;
             }
-
-            if (is_vector_node(binary_node<T>::branch_[1].first))
+            
+            inline typename expression_node<T>::node_type type() const
             {
-               vec1_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[1].first);
+                return expression_node<T>::e_vecvecass;
             }
-            else if (is_ivector_node(binary_node<T>::branch_[1].first))
+            
+            std::size_t size() const
             {
-               vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
-
-               if ((vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
-               {
-                  vec1_node_ptr_ = vi->vec();
-               }
+                return vds().size();
             }
-
-            if (vec0_node_ptr_ && vec1_node_ptr_)
+            
+            vds_t& vds()
             {
-               vec_size_ = std::min(vec0_node_ptr_->ref().size(),
-                                    vec1_node_ptr_->ref().size());
+                return vds_;
             }
-         }
-
-         inline T value() const
-         {
-            binary_node<T>::branch_[1].first->value();
-
-            if (vec0_node_ptr_ && vec1_node_ptr_)
+            
+            const vds_t& vds() const
             {
-               vector_holder<T>& vec0 = vec0_node_ptr_->ref();
-               vector_holder<T>& vec1 = vec1_node_ptr_->ref();
-
-               for (std::size_t i = 0; i < vec_size_; ++i)
-               {
-                  (*vec0[i]) = (*vec1[i]);
-               }
-
-               return vec0_node_ptr_->value();
+                return vds_;
             }
-            else
-               return std::numeric_limits<T>::quiet_NaN();
-         }
-
-         vector_node_ptr vec() const
-         {
-            return vec0_node_ptr_;
-         }
-
-         vector_node_ptr vec()
-         {
-            return vec0_node_ptr_;
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_vecvecass;
-         }
-
-         std::size_t size() const
-         {
-            return vec_size_;
-         }
-
-      private:
-
-         vector_node<T>* vec0_node_ptr_;
-         vector_node<T>* vec1_node_ptr_;
-         std::size_t     vec_size_;
-      };
-
-      template <typename T, typename Operation>
-      class assignment_op_node : public binary_node<T>
-      {
-      public:
-
-         typedef expression_node<T>* expression_ptr;
-
-         assignment_op_node(const operator_type& opr,
-                            expression_ptr branch0,
-                            expression_ptr branch1)
-         : binary_node<T>(opr,branch0,branch1),
-           var_node_ptr_(0)
-         {
-            if (is_variable_node(binary_node<T>::branch_[0].first))
-            {
-               var_node_ptr_ = static_cast<variable_node<T>*>(binary_node<T>::branch_[0].first);
+            
+        private:
+            
+            vector_node<T>* vec0_node_ptr_;
+            vector_node<T>* vec1_node_ptr_;
+            bool            initialised_;
+            bool            src_is_ivec_;
+            vds_t           vds_;
+        };
+        
+        template <typename T, typename Operation>
+        class assignment_op_node : public binary_node<T>
+        {
+        public:
+            
+            typedef expression_node<T>* expression_ptr;
+            
+            assignment_op_node(const operator_type& opr,
+                               expression_ptr branch0,
+                               expression_ptr branch1)
+            : binary_node<T>(opr,branch0,branch1),
+            var_node_ptr_(0)
+            {
+                if (is_variable_node(binary_node<T>::branch_[0].first))
+                {
+                    var_node_ptr_ = static_cast<variable_node<T>*>(binary_node<T>::branch_[0].first);
+                }
+            }
+            
+            inline T value() const
+            {
+                if (var_node_ptr_)
+                {
+                    T& v = var_node_ptr_->ref();
+                    v = Operation::process(v,binary_node<T>::branch_[1].first->value());
+                    
+                    return v;
+                }
+                else
+                    return std::numeric_limits<T>::quiet_NaN();
+            }
+            
+        private:
+            
+            variable_node<T>* var_node_ptr_;
+        };
+        
+        template <typename T, typename Operation>
+        class assignment_vec_elem_op_node : public binary_node<T>
+        {
+        public:
+            
+            typedef expression_node<T>* expression_ptr;
+            
+            assignment_vec_elem_op_node(const operator_type& opr,
+                                        expression_ptr branch0,
+                                        expression_ptr branch1)
+            : binary_node<T>(opr,branch0,branch1),
+            vec_node_ptr_(0)
+            {
+                if (is_vector_elem_node(binary_node<T>::branch_[0].first))
+                {
+                    vec_node_ptr_ = static_cast<vector_elem_node<T>*>(binary_node<T>::branch_[0].first);
+                }
+            }
+            
+            inline T value() const
+            {
+                if (vec_node_ptr_)
+                {
+                    T& v = vec_node_ptr_->ref();
+                    v = Operation::process(v,binary_node<T>::branch_[1].first->value());
+                    
+                    return v;
+                }
+                else
+                    return std::numeric_limits<T>::quiet_NaN();
+            }
+            
+        private:
+            
+            vector_elem_node<T>* vec_node_ptr_;
+        };
+        
+        template <typename T, typename Operation>
+        class assignment_rebasevec_elem_op_node : public binary_node<T>
+        {
+        public:
+            
+            typedef expression_node<T>* expression_ptr;
+            
+            assignment_rebasevec_elem_op_node(const operator_type& opr,
+                                              expression_ptr branch0,
+                                              expression_ptr branch1)
+            : binary_node<T>(opr,branch0,branch1),
+            rbvec_node_ptr_(0)
+            {
+                if (is_rebasevector_elem_node(binary_node<T>::branch_[0].first))
+                {
+                    rbvec_node_ptr_ = static_cast<rebasevector_elem_node<T>*>(binary_node<T>::branch_[0].first);
+                }
+            }
+            
+            inline T value() const
+            {
+                if (rbvec_node_ptr_)
+                {
+                    T& v = rbvec_node_ptr_->ref();
+                    v = Operation::process(v,binary_node<T>::branch_[1].first->value());
+                    
+                    return v;
+                }
+                else
+                    return std::numeric_limits<T>::quiet_NaN();
+            }
+            
+        private:
+            
+            rebasevector_elem_node<T>* rbvec_node_ptr_;
+        };
+        
+        template <typename T, typename Operation>
+        class assignment_rebasevec_celem_op_node : public binary_node<T>
+        {
+        public:
+            
+            typedef expression_node<T>* expression_ptr;
+            
+            assignment_rebasevec_celem_op_node(const operator_type& opr,
+                                               expression_ptr branch0,
+                                               expression_ptr branch1)
+            : binary_node<T>(opr,branch0,branch1),
+            rbvec_node_ptr_(0)
+            {
+                if (is_rebasevector_celem_node(binary_node<T>::branch_[0].first))
+                {
+                    rbvec_node_ptr_ = static_cast<rebasevector_celem_node<T>*>(binary_node<T>::branch_[0].first);
+                }
+            }
+            
+            inline T value() const
+            {
+                if (rbvec_node_ptr_)
+                {
+                    T& v = rbvec_node_ptr_->ref();
+                    v = Operation::process(v,binary_node<T>::branch_[1].first->value());
+                    
+                    return v;
+                }
+                else
+                    return std::numeric_limits<T>::quiet_NaN();
+            }
+            
+        private:
+            
+            rebasevector_celem_node<T>* rbvec_node_ptr_;
+        };
+        
+        template <typename T, typename Operation>
+        class assignment_vec_op_node : public binary_node     <T>,
+        public vector_interface<T>
+        {
+        public:
+            
+            typedef expression_node<T>*  expression_ptr;
+            typedef vector_node<T>*     vector_node_ptr;
+            typedef vec_data_store<T>             vds_t;
+            
+            assignment_vec_op_node(const operator_type& opr,
+                                   expression_ptr branch0,
+                                   expression_ptr branch1)
+            : binary_node<T>(opr,branch0,branch1),
+            vec_node_ptr_(0)
+            {
+                if (is_vector_node(binary_node<T>::branch_[0].first))
+                {
+                    vec_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);
+                    vds()         = vec_node_ptr_->vds();
+                }
+            }
+            
+            inline T value() const
+            {
+                if (vec_node_ptr_)
+                {
+                    const T v = binary_node<T>::branch_[1].first->value();
+                    
+                    T* vec = vds().data();
+                    
+                    loop_unroll::details lud(size());
+                    const T* upper_bound = vec + lud.upper_bound;
+                    
+                    while (vec < upper_bound)
+                    {
+#define exprtk_loop(N)       \
+Operation::assign(vec[N],v); \
+
+                        exprtk_loop( 0) exprtk_loop( 1)
+                        exprtk_loop( 2) exprtk_loop( 3)
+#ifndef exprtk_disable_superscalar_unroll
+                        exprtk_loop( 4) exprtk_loop( 5)
+                        exprtk_loop( 6) exprtk_loop( 7)
+                        exprtk_loop( 8) exprtk_loop( 9)
+                        exprtk_loop(10) exprtk_loop(11)
+                        exprtk_loop(12) exprtk_loop(13)
+                        exprtk_loop(14) exprtk_loop(15)
+#endif
+                        
+                        vec += lud.batch_size;
+                    }
+                    
+                    switch (lud.remainder)
+                    {
+#define case_stmt(N)                  \
+case N : Operation::assign(*vec++,v); \
+
+#ifndef exprtk_disable_superscalar_unroll
+                            case_stmt(15) case_stmt(14)
+                            case_stmt(13) case_stmt(12)
+                            case_stmt(11) case_stmt(10)
+                            case_stmt( 9) case_stmt( 8)
+                            case_stmt( 7) case_stmt( 6)
+                            case_stmt( 5) case_stmt( 4)
+#endif
+                            case_stmt( 3) case_stmt( 2)
+                            case_stmt( 1)
+                    }
+                    
+#undef exprtk_loop
+#undef case_stmt
+                    
+                    return vec_node_ptr_->value();
+                }
+                else
+                    return std::numeric_limits<T>::quiet_NaN();
             }
-         }
-
-         inline T value() const
-         {
-            if (var_node_ptr_)
+            
+            vector_node_ptr vec() const
             {
-               T& v = var_node_ptr_->ref();
-               v = Operation::process(v,binary_node<T>::branch_[1].first->value());
-
-               return v;
+                return vec_node_ptr_;
             }
-            else
-               return std::numeric_limits<T>::quiet_NaN();
-         }
-
-      private:
-
-         variable_node<T>* var_node_ptr_;
-      };
-
-      template <typename T, typename Operation>
-      class assignment_vec_elem_op_node : public binary_node<T>
-      {
-      public:
-
-         typedef expression_node<T>* expression_ptr;
-
-         assignment_vec_elem_op_node(const operator_type& opr,
-                                     expression_ptr branch0,
-                                     expression_ptr branch1)
-         : binary_node<T>(opr,branch0,branch1),
-           vec_node_ptr_(0)
-         {
-            if (is_vector_elem_node(binary_node<T>::branch_[0].first))
+            
+            vector_node_ptr vec()
             {
-               vec_node_ptr_ = static_cast<vector_elem_node<T>*>(binary_node<T>::branch_[0].first);
+                return vec_node_ptr_;
             }
-         }
-
-         inline T value() const
-         {
-            if (vec_node_ptr_)
+            
+            inline typename expression_node<T>::node_type type() const
             {
-               T& v = vec_node_ptr_->ref();
-                  v = Operation::process(v,binary_node<T>::branch_[1].first->value());
-
-               return v;
+                return expression_node<T>::e_vecopvalass;
             }
-            else
-               return std::numeric_limits<T>::quiet_NaN();
-         }
-
-      private:
-
-         vector_elem_node<T>* vec_node_ptr_;
-      };
-
-      template <typename T, typename Operation>
-      class assignment_vec_op_node : public binary_node<T>,
-                                     public vector_interface<T>
-      {
-      public:
-
-         typedef expression_node<T>* expression_ptr;
-         typedef vector_node<T>*     vector_node_ptr;
-
-         assignment_vec_op_node(const operator_type& opr,
-                                expression_ptr branch0,
-                                expression_ptr branch1)
-         : binary_node<T>(opr,branch0,branch1),
-           vec_node_ptr_(0),
-           vec_size_    (0)
-         {
-            if (is_vector_node(binary_node<T>::branch_[0].first))
+            
+            std::size_t size() const
             {
-               vec_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);
-               vec_size_     = vec_node_ptr_->ref().size();
+                return vds().size();
             }
-         }
-
-         inline T value() const
-         {
-            if (vec_node_ptr_)
+            
+            vds_t& vds()
             {
-               vector_holder<T>& vec_hldr = vec_node_ptr_->ref();
-               const T v = binary_node<T>::branch_[1].first->value();
-
-               for (std::size_t i = 0; i < vec_size_; ++i)
-               {
-                  T& vec_i = *vec_hldr[i];
-                     vec_i = Operation::process(vec_i,v);
-               }
-
-               return vec_node_ptr_->value();
+                return vds_;
             }
-            else
-               return std::numeric_limits<T>::quiet_NaN();
-         }
-
-         vector_node_ptr vec() const
-         {
-            return vec_node_ptr_;
-         }
-
-         vector_node_ptr vec()
-         {
-            return vec_node_ptr_;
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_vecopvalass;
-         }
-
-         std::size_t size() const
-         {
-            return vec_size_;
-         }
-
-      private:
-
-         vector_node<T>* vec_node_ptr_;
-         std::size_t     vec_size_;
-      };
-
-      template <typename T, typename Operation>
-      class assignment_vecvec_op_node : public binary_node<T>,
-                                        public vector_interface<T>
-      {
-      public:
-
-         typedef expression_node<T>* expression_ptr;
-         typedef vector_node<T>*     vector_node_ptr;
-
-         assignment_vecvec_op_node(const operator_type& opr,
-                                expression_ptr branch0,
-                                expression_ptr branch1)
-         : binary_node<T>(opr,branch0,branch1),
-           vec0_node_ptr_(0),
-           vec1_node_ptr_(0),
-           vec_size_     (0)
-         {
-            if (is_vector_node(binary_node<T>::branch_[0].first))
+            
+            const vds_t& vds() const
             {
-               vec0_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);
+                return vds_;
             }
-
-            if (is_vector_node(binary_node<T>::branch_[1].first))
+            
+            bool side_effect() const
             {
-               vec1_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[1].first);
+                return true;
+            }
+            
+        private:
+            
+            vector_node<T>* vec_node_ptr_;
+            vds_t           vds_;
+        };
+        
+        template <typename T, typename Operation>
+        class assignment_vecvec_op_node : public binary_node     <T>,
+        public vector_interface<T>
+        {
+        public:
+            
+            typedef expression_node<T>*  expression_ptr;
+            typedef vector_node<T>*     vector_node_ptr;
+            typedef vec_data_store<T>             vds_t;
+            
+            assignment_vecvec_op_node(const operator_type& opr,
+                                      expression_ptr branch0,
+                                      expression_ptr branch1)
+            : binary_node<T>(opr,branch0,branch1),
+            vec0_node_ptr_(0),
+            vec1_node_ptr_(0),
+            initialised_(false)
+            {
+                if (is_vector_node(binary_node<T>::branch_[0].first))
+                {
+                    vec0_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);
+                    vds()          = vec0_node_ptr_->vds();
+                }
+                
+                if (is_vector_node(binary_node<T>::branch_[1].first))
+                {
+                    vec1_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[1].first);
+                    vec1_node_ptr_->vds() = vds();
+                }
+                else if (is_ivector_node(binary_node<T>::branch_[1].first))
+                {
+                    vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
+                    
+                    if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
+                    {
+                        vec1_node_ptr_ = vi->vec();
+                        vec1_node_ptr_->vds() = vds();
+                    }
+                    else
+                        vds_t::match_sizes(vds(),vec1_node_ptr_->vds());
+                }
+                
+                initialised_ = (vec0_node_ptr_ && vec1_node_ptr_);
+            }
+            
+            inline T value() const
+            {
+                if (initialised_)
+                {
+                    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();
+                    
+                    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]); \
+
+                        exprtk_loop( 0) exprtk_loop( 1)
+                        exprtk_loop( 2) exprtk_loop( 3)
+#ifndef exprtk_disable_superscalar_unroll
+                        exprtk_loop( 4) exprtk_loop( 5)
+                        exprtk_loop( 6) exprtk_loop( 7)
+                        exprtk_loop( 8) exprtk_loop( 9)
+                        exprtk_loop(10) exprtk_loop(11)
+                        exprtk_loop(12) exprtk_loop(13)
+                        exprtk_loop(14) exprtk_loop(15)
+#endif
+                        
+                        vec0 += lud.batch_size;
+                        vec1 += lud.batch_size;
+                    }
+                    
+                    int i = 0;
+                    
+                    switch (lud.remainder)
+                    {
+#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)
+                            case_stmt(13) case_stmt(12)
+                            case_stmt(11) case_stmt(10)
+                            case_stmt( 9) case_stmt( 8)
+                            case_stmt( 7) case_stmt( 6)
+                            case_stmt( 5) case_stmt( 4)
+#endif
+                            case_stmt( 3) case_stmt( 2)
+                            case_stmt( 1)
+                    }
+                    
+#undef exprtk_loop
+#undef case_stmt
+                    
+                    return vec0_node_ptr_->value();
+                }
+                else
+                    return std::numeric_limits<T>::quiet_NaN();
             }
-            else if (is_ivector_node(binary_node<T>::branch_[1].first))
+            
+            vector_node_ptr vec() const
             {
-               vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
-
-               if ((vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
-               {
-                  vec1_node_ptr_ = vi->vec();
-               }
+                return vec0_node_ptr_;
             }
-
-            if (vec0_node_ptr_ && vec1_node_ptr_)
+            
+            vector_node_ptr vec()
             {
-               vec_size_ = std::min(vec0_node_ptr_->ref().size(),
-                                    vec1_node_ptr_->ref().size());
+                return vec0_node_ptr_;
             }
-         }
-
-         inline T value() const
-         {
-            if (vec0_node_ptr_ && vec1_node_ptr_)
+            
+            inline typename expression_node<T>::node_type type() const
             {
-               binary_node<T>::branch_[0].first->value();
-               binary_node<T>::branch_[1].first->value();
-
-               vector_holder<T>& vec0 = vec0_node_ptr_->ref();
-               vector_holder<T>& vec1 = vec1_node_ptr_->ref();
-
-               for (std::size_t i = 0; i < vec_size_; ++i)
-               {
-                  T& vec0_i = *vec0[i];
-                  T& vec1_i = *vec1[i];
-                  vec0_i = Operation::process(vec0_i,vec1_i);
-               }
-
-               return vec0_node_ptr_->value();
+                return expression_node<T>::e_vecopvecass;
             }
-            else
-               return std::numeric_limits<T>::quiet_NaN();
-         }
-
-         vector_node_ptr vec() const
-         {
-            return vec0_node_ptr_;
-         }
-
-         vector_node_ptr vec()
-         {
-            return vec0_node_ptr_;
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_vecopvecass;
-         }
-
-         std::size_t size() const
-         {
-            return vec_size_;
-         }
-
-      private:
-
-         vector_node<T>* vec0_node_ptr_;
-         vector_node<T>* vec1_node_ptr_;
-         std::size_t     vec_size_;
-      };
-
-      template <typename T, typename Operation>
-      class eqineq_vecvec_node : public binary_node<T>,
-                                 public vector_interface<T>
-      {
-      public:
-
-         typedef expression_node<T>*  expression_ptr;
-         typedef vector_node<T>*     vector_node_ptr;
-
-         eqineq_vecvec_node(const operator_type& opr,
-                            expression_ptr branch0,
-                            expression_ptr branch1)
-         : binary_node<T>(opr,branch0,branch1),
-           vec0_node_ptr_(0),
-           vec1_node_ptr_(0),
-           vec_size_     (0)
-         {
-
-            if (is_vector_node(binary_node<T>::branch_[0].first))
+            
+            std::size_t size() const
             {
-               vec0_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);
+                return vds().size();
             }
-            else if (is_ivector_node(binary_node<T>::branch_[0].first))
+            
+            vds_t& vds()
             {
-               vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
-
-               if ((vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[0].first)))
-               {
-                  vec0_node_ptr_ = vi->vec();
-               }
+                return vds_;
             }
-
-            if (is_vector_node(binary_node<T>::branch_[1].first))
+            
+            const vds_t& vds() const
             {
-               vec1_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[1].first);
+                return vds_;
             }
-            else if (is_ivector_node(binary_node<T>::branch_[1].first))
+            
+            bool side_effect() const
             {
-               vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
-
-               if ((vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
-               {
-                  vec1_node_ptr_ = vi->vec();
-               }
+                return true;
             }
-
-            if (vec0_node_ptr_ && vec1_node_ptr_)
+            
+        private:
+            
+            vector_node<T>* vec0_node_ptr_;
+            vector_node<T>* vec1_node_ptr_;
+            bool            initialised_;
+            vds_t           vds_;
+        };
+        
+        template <typename T, typename Operation>
+        class vec_binop_vecvec_node : public binary_node     <T>,
+        public vector_interface<T>
+        {
+        public:
+            
+            typedef expression_node<T>*    expression_ptr;
+            typedef vector_node<T>*       vector_node_ptr;
+            typedef vector_holder<T>*   vector_holder_ptr;
+            typedef vec_data_store<T>               vds_t;
+            
+            vec_binop_vecvec_node(const operator_type& opr,
+                                  expression_ptr branch0,
+                                  expression_ptr branch1)
+            : binary_node<T>(opr,branch0,branch1),
+            vec0_node_ptr_(0),
+            vec1_node_ptr_(0),
+            temp_         (0),
+            temp_vec_node_(0),
+            initialised_(false)
+            {
+                bool v0_is_ivec = false;
+                bool v1_is_ivec = false;
+                
+                if (is_vector_node(binary_node<T>::branch_[0].first))
+                {
+                    vec0_node_ptr_ = static_cast<vector_node_ptr>(binary_node<T>::branch_[0].first);
+                }
+                else if (is_ivector_node(binary_node<T>::branch_[0].first))
+                {
+                    vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
+                    
+                    if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[0].first)))
+                    {
+                        vec0_node_ptr_ = vi->vec();
+                        v0_is_ivec     = true;
+                    }
+                }
+                
+                if (is_vector_node(binary_node<T>::branch_[1].first))
+                {
+                    vec1_node_ptr_ = static_cast<vector_node_ptr>(binary_node<T>::branch_[1].first);
+                }
+                else if (is_ivector_node(binary_node<T>::branch_[1].first))
+                {
+                    vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
+                    
+                    if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
+                    {
+                        vec1_node_ptr_ = vi->vec();
+                        v1_is_ivec     = true;
+                    }
+                }
+                
+                if (vec0_node_ptr_ && vec1_node_ptr_)
+                {
+                    vector_holder<T>& vec0 = vec0_node_ptr_->vec_holder();
+                    vector_holder<T>& vec1 = vec1_node_ptr_->vec_holder();
+                    
+                    if (v0_is_ivec && (vec0.size() <= vec1.size()))
+                        vds_ = vds_t(vec0_node_ptr_->vds());
+                    else if (v1_is_ivec && (vec1.size() <= vec0.size()))
+                        vds_ = vds_t(vec1_node_ptr_->vds());
+                    else
+                        vds_ = vds_t(std::min(vec0.size(),vec1.size()));
+                    
+                    temp_          = new vector_holder<T>(vds().data(),vds().size());
+                    temp_vec_node_ = new vector_node<T>  (vds(),temp_);
+                    
+                    initialised_ = true;
+                }
+            }
+            
+            ~vec_binop_vecvec_node()
+            {
+                delete temp_;
+                delete temp_vec_node_;
+            }
+            
+            inline T value() const
+            {
+                if (initialised_)
+                {
+                    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();
+                    
+                    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]); \
+
+                        exprtk_loop( 0) exprtk_loop( 1)
+                        exprtk_loop( 2) exprtk_loop( 3)
+#ifndef exprtk_disable_superscalar_unroll
+                        exprtk_loop( 4) exprtk_loop( 5)
+                        exprtk_loop( 6) exprtk_loop( 7)
+                        exprtk_loop( 8) exprtk_loop( 9)
+                        exprtk_loop(10) exprtk_loop(11)
+                        exprtk_loop(12) exprtk_loop(13)
+                        exprtk_loop(14) exprtk_loop(15)
+#endif
+                        
+                        vec0 += lud.batch_size;
+                        vec1 += lud.batch_size;
+                        vec2 += lud.batch_size;
+                    }
+                    
+                    int i = 0;
+                    
+                    switch (lud.remainder)
+                    {
+#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)
+                            case_stmt(13) case_stmt(12)
+                            case_stmt(11) case_stmt(10)
+                            case_stmt( 9) case_stmt( 8)
+                            case_stmt( 7) case_stmt( 6)
+                            case_stmt( 5) case_stmt( 4)
+#endif
+                            case_stmt( 3) case_stmt( 2)
+                            case_stmt( 1)
+                    }
+                    
+#undef exprtk_loop
+#undef case_stmt
+                    
+                    return (vds().data())[0];
+                }
+                else
+                    return std::numeric_limits<T>::quiet_NaN();
+            }
+            
+            vector_node_ptr vec() const
             {
-               vec_size_ = std::min(vec0_node_ptr_->ref().size(),
-                                    vec1_node_ptr_->ref().size());
+                return temp_vec_node_;
             }
-         }
-
-         inline T value() const
-         {
-            if (vec0_node_ptr_ && vec1_node_ptr_)
+            
+            vector_node_ptr vec()
             {
-               binary_node<T>::branch_[0].first->value();
-               binary_node<T>::branch_[1].first->value();
-
-               vector_holder<T>& vec0 = vec0_node_ptr_->ref();
-               vector_holder<T>& vec1 = vec1_node_ptr_->ref();
-
-               for (std::size_t i = 0; i < vec_size_; ++i)
-               {
-                  if (std::equal_to<T>()(T(0),Operation::process(*vec0[i],*vec1[i])))
-                  {
-                     return T(0);
-                  }
-               }
-
-               return T(1);
+                return temp_vec_node_;
             }
-            else
-               return std::numeric_limits<T>::quiet_NaN();
-         }
-
-         vector_node_ptr vec() const
-         {
-            return vec0_node_ptr_;
-         }
-
-         vector_node_ptr vec()
-         {
-            return vec0_node_ptr_;
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_vecvecineq;
-         }
-
-         std::size_t size() const
-         {
-            return vec_size_;
-         }
-
-      private:
-
-         vector_node<T>* vec0_node_ptr_;
-         vector_node<T>* vec1_node_ptr_;
-         std::size_t     vec_size_;
-      };
-
-      template <typename T, typename Operation>
-      class eqineq_vecval_node : public binary_node<T>,
-                                 public vector_interface<T>
-      {
-      public:
-
-         typedef expression_node<T>*  expression_ptr;
-         typedef vector_node<T>*     vector_node_ptr;
-
-         eqineq_vecval_node(const operator_type& opr,
-                            expression_ptr branch0,
-                            expression_ptr branch1)
-         : binary_node<T>(opr,branch0,branch1),
-           vec_node_ptr_(0),
-           vec_size_    (0)
-         {
-            if (is_vector_node(binary_node<T>::branch_[0].first))
+            
+            inline typename expression_node<T>::node_type type() const
             {
-               vec_node_ptr_ = static_cast<vector_node_ptr>(binary_node<T>::branch_[0].first);
+                return expression_node<T>::e_vecvecarith;
             }
-            else if (is_ivector_node(binary_node<T>::branch_[0].first))
+            
+            std::size_t size() const
             {
-               vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
-
-               if ((vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[0].first)))
-               {
-                  vec_node_ptr_ = vi->vec();
-               }
+                return vds_.size();
             }
-
-            if (vec_node_ptr_)
+            
+            vds_t& vds()
             {
-               vec_size_ = vec_node_ptr_->ref().size();
+                return vds_;
             }
-         }
-
-         inline T value() const
-         {
-            if (vec_node_ptr_)
+            
+            const vds_t& vds() const
             {
-                     binary_node<T>::branch_[0].first->value();
-               T v = binary_node<T>::branch_[1].first->value();
-
-               vector_holder<T>& vec_hldr = vec_node_ptr_->ref();
-
-               for (std::size_t i = 0; i < vec_size_; ++i)
-               {
-                  if (std::equal_to<T>()(T(0),Operation::process(*vec_hldr[i],v)))
-                  {
-                     return T(0);
-                  }
-               }
-
-               return T(1);
+                return vds_;
             }
-            else
-               return std::numeric_limits<T>::quiet_NaN();
-         }
-
-         vector_node_ptr vec() const
-         {
-            return vec_node_ptr_;
-         }
-
-         vector_node_ptr vec()
-         {
-            return vec_node_ptr_;
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_vecvalineq;
-         }
-
-         std::size_t size() const
-         {
-            return vec_size_;
-         }
-
-      private:
-
-         vector_node<T>* vec_node_ptr_;
-         std::size_t     vec_size_;
-      };
-
-      template <typename T, typename Operation>
-      class eqineq_valvec_node : public binary_node<T>,
-                                 public vector_interface<T>
-      {
-      public:
-
-         typedef expression_node<T>*  expression_ptr;
-         typedef vector_node<T>*     vector_node_ptr;
-
-         eqineq_valvec_node(const operator_type& opr,
-                            expression_ptr branch0,
-                            expression_ptr branch1)
-         : binary_node<T>(opr,branch0,branch1),
-           vec_node_ptr_(0),
-           vec_size_    (0)
-         {
-            if (is_vector_node(binary_node<T>::branch_[1].first))
+            
+        private:
+            
+            vector_node_ptr   vec0_node_ptr_;
+            vector_node_ptr   vec1_node_ptr_;
+            vector_holder_ptr temp_;
+            vector_node_ptr   temp_vec_node_;
+            bool              initialised_;
+            vds_t             vds_;
+        };
+        
+        template <typename T, typename Operation>
+        class vec_binop_vecval_node : public binary_node     <T>,
+        public vector_interface<T>
+        {
+        public:
+            
+            typedef expression_node<T>*    expression_ptr;
+            typedef vector_node<T>*       vector_node_ptr;
+            typedef vector_holder<T>*   vector_holder_ptr;
+            typedef vec_data_store<T>               vds_t;
+            
+            vec_binop_vecval_node(const operator_type& opr,
+                                  expression_ptr branch0,
+                                  expression_ptr branch1)
+            : binary_node<T>(opr,branch0,branch1),
+            vec0_node_ptr_(0),
+            temp_         (0),
+            temp_vec_node_(0)
+            {
+                bool v0_is_ivec = false;
+                
+                if (is_vector_node(binary_node<T>::branch_[0].first))
+                {
+                    vec0_node_ptr_ = static_cast<vector_node_ptr>(binary_node<T>::branch_[0].first);
+                }
+                else if (is_ivector_node(binary_node<T>::branch_[0].first))
+                {
+                    vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
+                    
+                    if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[0].first)))
+                    {
+                        vec0_node_ptr_ = vi->vec();
+                        v0_is_ivec     = true;
+                    }
+                }
+                
+                if (vec0_node_ptr_)
+                {
+                    if (v0_is_ivec)
+                        vds() = vec0_node_ptr_->vds();
+                    else
+                        vds() = vds_t(vec0_node_ptr_->size());
+                    
+                    temp_          = new vector_holder<T>(vds());
+                    temp_vec_node_ = new vector_node<T>  (vds(),temp_);
+                }
+            }
+            
+            ~vec_binop_vecval_node()
+            {
+                delete temp_;
+                delete temp_vec_node_;
+            }
+            
+            inline T value() const
+            {
+                if (vec0_node_ptr_)
+                {
+                    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();
+                    
+                    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); \
+
+                        exprtk_loop( 0) exprtk_loop( 1)
+                        exprtk_loop( 2) exprtk_loop( 3)
+#ifndef exprtk_disable_superscalar_unroll
+                        exprtk_loop( 4) exprtk_loop( 5)
+                        exprtk_loop( 6) exprtk_loop( 7)
+                        exprtk_loop( 8) exprtk_loop( 9)
+                        exprtk_loop(10) exprtk_loop(11)
+                        exprtk_loop(12) exprtk_loop(13)
+                        exprtk_loop(14) exprtk_loop(15)
+#endif
+                        
+                        vec0 += lud.batch_size;
+                        vec1 += lud.batch_size;
+                    }
+                    
+                    int i = 0;
+                    
+                    switch (lud.remainder)
+                    {
+#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)
+                            case_stmt(13) case_stmt(12)
+                            case_stmt(11) case_stmt(10)
+                            case_stmt( 9) case_stmt( 8)
+                            case_stmt( 7) case_stmt( 6)
+                            case_stmt( 5) case_stmt( 4)
+#endif
+                            case_stmt( 3) case_stmt( 2)
+                            case_stmt( 1)
+                    }
+                    
+#undef exprtk_loop
+#undef case_stmt
+                    
+                    return (vds().data())[0];
+                }
+                else
+                    return std::numeric_limits<T>::quiet_NaN();
+            }
+            
+            vector_node_ptr vec() const
             {
-               vec_node_ptr_ = static_cast<vector_node_ptr>(binary_node<T>::branch_[1].first);
+                return temp_vec_node_;
             }
-            else if (is_ivector_node(binary_node<T>::branch_[1].first))
+            
+            vector_node_ptr vec()
             {
-               vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
-
-               if ((vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
-               {
-                  vec_node_ptr_ = vi->vec();
-               }
+                return temp_vec_node_;
             }
-
-            if (vec_node_ptr_)
+            
+            inline typename expression_node<T>::node_type type() const
             {
-               vec_size_ = vec_node_ptr_->ref().size();
+                return expression_node<T>::e_vecvalarith;
             }
-         }
-
-         inline T value() const
-         {
-            if (vec_node_ptr_)
+            
+            std::size_t size() const
             {
-               T v = binary_node<T>::branch_[0].first->value();
-                     binary_node<T>::branch_[1].first->value();
-
-               vector_holder<T>& vec_hldr = vec_node_ptr_->ref();
-
-               for (std::size_t i = 0; i < vec_size_; ++i)
-               {
-                  if (std::equal_to<T>()(T(0),Operation::process(v,*vec_hldr[i])))
-                  {
-                     return T(0);
-                  }
-               }
-
-               return T(1);
+                return vds().size();
             }
-            else
-               return std::numeric_limits<T>::quiet_NaN();
-         }
-
-         vector_node_ptr vec() const
-         {
-            return vec_node_ptr_;
-         }
-
-         vector_node_ptr vec()
-         {
-            return vec_node_ptr_;
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_valvecineq;
-         }
-
-         std::size_t size() const
-         {
-            return vec_size_;
-         }
-
-      private:
-
-         vector_node<T>* vec_node_ptr_;
-         std::size_t     vec_size_;
-      };
-
-      template <typename T, typename Operation>
-      class vecarith_vecvec_node : public binary_node<T>,
-                                   public vector_interface<T>
-      {
-      public:
-
-         typedef expression_node<T>*    expression_ptr;
-         typedef vector_node<T>*       vector_node_ptr;
-         typedef vector_holder<T>*   vector_holder_ptr;
-
-         vecarith_vecvec_node(const operator_type& opr,
-                              expression_ptr branch0,
-                              expression_ptr branch1)
-         : binary_node<T>(opr,branch0,branch1),
-           vec0_node_ptr_(0),
-           vec1_node_ptr_(0),
-           vec_size_     (0),
-           data_         (0),
-           temp_         (0),
-           temp_vec_node_(0)
-         {
-            if (is_vector_node(binary_node<T>::branch_[0].first))
-            {
-               vec0_node_ptr_ = static_cast<vector_node_ptr>(binary_node<T>::branch_[0].first);
-            }
-            else if (is_ivector_node(binary_node<T>::branch_[0].first))
-            {
-               vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
-
-               if ((vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[0].first)))
-               {
-                  vec0_node_ptr_ = vi->vec();
-               }
+            
+            vds_t& vds()
+            {
+                return vds_;
             }
-
-            if (is_vector_node(binary_node<T>::branch_[1].first))
+            
+            const vds_t& vds() const
             {
-               vec1_node_ptr_ = static_cast<vector_node_ptr>(binary_node<T>::branch_[1].first);
+                return vds_;
+            }
+            
+        private:
+            
+            vector_node_ptr   vec0_node_ptr_;
+            vector_holder_ptr temp_;
+            vector_node_ptr   temp_vec_node_;
+            vds_t             vds_;
+        };
+        
+        template <typename T, typename Operation>
+        class vec_binop_valvec_node : public binary_node     <T>,
+        public vector_interface<T>
+        {
+        public:
+            
+            typedef expression_node<T>*    expression_ptr;
+            typedef vector_node<T>*       vector_node_ptr;
+            typedef vector_holder<T>*   vector_holder_ptr;
+            typedef vec_data_store<T>               vds_t;
+            
+            vec_binop_valvec_node(const operator_type& opr,
+                                  expression_ptr branch0,
+                                  expression_ptr branch1)
+            : binary_node<T>(opr,branch0,branch1),
+            vec1_node_ptr_(0),
+            temp_         (0),
+            temp_vec_node_(0)
+            {
+                bool v1_is_ivec = false;
+                
+                if (is_vector_node(binary_node<T>::branch_[1].first))
+                {
+                    vec1_node_ptr_ = static_cast<vector_node_ptr>(binary_node<T>::branch_[1].first);
+                }
+                else if (is_ivector_node(binary_node<T>::branch_[1].first))
+                {
+                    vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
+                    
+                    if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
+                    {
+                        vec1_node_ptr_ = vi->vec();
+                        v1_is_ivec     = true;
+                    }
+                }
+                
+                if (vec1_node_ptr_)
+                {
+                    if (v1_is_ivec)
+                        vds() = vec1_node_ptr_->vds();
+                    else
+                        vds() = vds_t(vec1_node_ptr_->size());
+                    
+                    temp_          = new vector_holder<T>(vds());
+                    temp_vec_node_ = new vector_node<T>  (vds(),temp_);
+                }
+            }
+            
+            ~vec_binop_valvec_node()
+            {
+                delete temp_;
+                delete temp_vec_node_;
+            }
+            
+            inline T value() const
+            {
+                if (vec1_node_ptr_)
+                {
+                    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();
+                    
+                    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]); \
+
+                        exprtk_loop( 0) exprtk_loop( 1)
+                        exprtk_loop( 2) exprtk_loop( 3)
+#ifndef exprtk_disable_superscalar_unroll
+                        exprtk_loop( 4) exprtk_loop( 5)
+                        exprtk_loop( 6) exprtk_loop( 7)
+                        exprtk_loop( 8) exprtk_loop( 9)
+                        exprtk_loop(10) exprtk_loop(11)
+                        exprtk_loop(12) exprtk_loop(13)
+                        exprtk_loop(14) exprtk_loop(15)
+#endif
+                        
+                        vec0 += lud.batch_size;
+                        vec1 += lud.batch_size;
+                    }
+                    
+                    int i = 0;
+                    
+                    switch (lud.remainder)
+                    {
+#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)
+                            case_stmt(13) case_stmt(12)
+                            case_stmt(11) case_stmt(10)
+                            case_stmt( 9) case_stmt( 8)
+                            case_stmt( 7) case_stmt( 6)
+                            case_stmt( 5) case_stmt( 4)
+#endif
+                            case_stmt( 3) case_stmt( 2)
+                            case_stmt( 1)
+                    }
+                    
+#undef exprtk_loop
+#undef case_stmt
+                    
+                    return (vds().data())[0];
+                }
+                else
+                    return std::numeric_limits<T>::quiet_NaN();
             }
-            else if (is_ivector_node(binary_node<T>::branch_[1].first))
+            
+            vector_node_ptr vec() const
             {
-               vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
-
-               if ((vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
-               {
-                  vec1_node_ptr_ = vi->vec();
-               }
+                return temp_vec_node_;
             }
-
-            if (vec0_node_ptr_ && vec1_node_ptr_)
+            
+            vector_node_ptr vec()
             {
-               vector_holder<T>& vec0 = vec0_node_ptr_->ref();
-               vector_holder<T>& vec1 = vec1_node_ptr_->ref();
-
-               vec_size_      = std::min(vec0.size(),vec1.size());
-               data_          = new T[vec_size_];
-               temp_          = new vector_holder<T>(data_,vec_size_);
-               temp_vec_node_ = new vector_node<T>  (temp_);
+                return temp_vec_node_;
             }
-         }
-
-        ~vecarith_vecvec_node()
-         {
-            delete[] data_;
-            delete   temp_;
-            delete   temp_vec_node_;
-         }
-
-         inline T value() const
-         {
-            if (vec0_node_ptr_ && vec1_node_ptr_)
+            
+            inline typename expression_node<T>::node_type type() const
             {
-               binary_node<T>::branch_[0].first->value();
-               binary_node<T>::branch_[1].first->value();
-
-               vector_holder<T>& vec0 = vec0_node_ptr_->ref();
-               vector_holder<T>& vec1 = vec1_node_ptr_->ref();
-               vector_holder<T>& vec2 = *temp_;
-
-               for (std::size_t i = 0; i < vec_size_; ++i)
-               {
-
-                  T& vec0_i = *vec0[i];
-                  T& vec1_i = *vec1[i];
-                  T& vec2_i = *vec2[i];
-
-                  vec2_i = Operation::process(vec0_i,vec1_i);
-               }
-
-               return *vec2[0];
+                return expression_node<T>::e_vecvalarith;
             }
-            else
-               return std::numeric_limits<T>::quiet_NaN();
-         }
-
-         vector_node_ptr vec() const
-         {
-            return temp_vec_node_;
-         }
-
-         vector_node_ptr vec()
-         {
-            return temp_vec_node_;
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_vecvecarith;
-         }
-
-         std::size_t size() const
-         {
-            return vec_size_;
-         }
-
-      private:
-
-         vector_node_ptr   vec0_node_ptr_;
-         vector_node_ptr   vec1_node_ptr_;
-         std::size_t       vec_size_;
-         T*                data_;
-         vector_holder_ptr temp_;
-         vector_node_ptr   temp_vec_node_;
-      };
-
-      template <typename T, typename Operation>
-      class vecarith_vecval_node : public binary_node<T>,
-                                   public vector_interface<T>
-      {
-      public:
-
-         typedef expression_node<T>*    expression_ptr;
-         typedef vector_node<T>*       vector_node_ptr;
-         typedef vector_holder<T>*   vector_holder_ptr;
-
-         vecarith_vecval_node(const operator_type& opr,
-                              expression_ptr branch0,
-                              expression_ptr branch1)
-         : binary_node<T>(opr,branch0,branch1),
-           vec0_node_ptr_(0),
-           vec_size_     (0),
-           data_         (0),
-           temp_         (0),
-           temp_vec_node_(0)
-         {
-            if (is_vector_node(binary_node<T>::branch_[0].first))
-            {
-               vec0_node_ptr_ = static_cast<vector_node_ptr>(binary_node<T>::branch_[0].first);
-            }
-            else if (is_ivector_node(binary_node<T>::branch_[0].first))
-            {
-               vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
-
-               if ((vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[0].first)))
-               {
-                  vec0_node_ptr_ = vi->vec();
-               }
+            
+            std::size_t size() const
+            {
+                return vds().size();
             }
-
-            if (vec0_node_ptr_)
+            
+            vds_t& vds()
             {
-               vector_holder<T>& vec0 = vec0_node_ptr_->ref();
-
-               vec_size_      = vec0.size();
-               data_          = new T[vec_size_];
-               temp_          = new vector_holder<T>(data_,vec_size_);
-               temp_vec_node_ = new vector_node<T>  (temp_);
+                return vds_;
             }
-         }
-
-        ~vecarith_vecval_node()
-         {
-            delete[] data_;
-            delete   temp_;
-            delete   temp_vec_node_;
-         }
-
-         inline T value() const
-         {
-            if (vec0_node_ptr_)
+            
+            const vds_t& vds() const
             {
-                           binary_node<T>::branch_[0].first->value();
-               const T v = binary_node<T>::branch_[1].first->value();
-
-               vector_holder<T>& vec0 = vec0_node_ptr_->ref();
-               vector_holder<T>& vec1 = *temp_;
-
-               for (std::size_t i = 0; i < vec_size_; ++i)
-               {
-                  T& vec0_i = *vec0[i];
-                  T& vec1_i = *vec1[i];
-
-                  vec1_i = Operation::process(vec0_i,v);
-               }
-
-               return *vec1[0];
+                return vds_;
             }
-            else
-               return std::numeric_limits<T>::quiet_NaN();
-         }
-
-         vector_node_ptr vec() const
-         {
-            return temp_vec_node_;
-         }
-
-         vector_node_ptr vec()
-         {
-            return temp_vec_node_;
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_vecvalarith;
-         }
-
-         std::size_t size() const
-         {
-            return vec_size_;
-         }
-
-      private:
-
-         vector_node_ptr   vec0_node_ptr_;
-         std::size_t       vec_size_;
-         T*                data_;
-         vector_holder_ptr temp_;
-         vector_node_ptr   temp_vec_node_;
-      };
-
-      template <typename T, typename Operation>
-      class vecarith_valvec_node : public binary_node<T>,
-                                   public vector_interface<T>
-      {
-      public:
-
-         typedef expression_node<T>*    expression_ptr;
-         typedef vector_node<T>*       vector_node_ptr;
-         typedef vector_holder<T>*   vector_holder_ptr;
-
-         vecarith_valvec_node(const operator_type& opr,
-                              expression_ptr branch0,
-                              expression_ptr branch1)
-         : binary_node<T>(opr,branch0,branch1),
-           vec1_node_ptr_(0),
-           vec_size_     (0),
-           data_         (0),
-           temp_         (0),
-           temp_vec_node_(0)
-         {
-            if (is_vector_node(binary_node<T>::branch_[1].first))
-            {
-               vec1_node_ptr_ = static_cast<vector_node_ptr>(binary_node<T>::branch_[1].first);
-            }
-            else if (is_ivector_node(binary_node<T>::branch_[1].first))
-            {
-               vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
-
-               if ((vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
-               {
-                  vec1_node_ptr_ = vi->vec();
-               }
+            
+        private:
+            
+            vector_node_ptr   vec1_node_ptr_;
+            vector_holder_ptr temp_;
+            vector_node_ptr   temp_vec_node_;
+            vds_t             vds_;
+        };
+        
+        template <typename T, typename Operation>
+        class unary_vector_node : public unary_node      <T>,
+        public vector_interface<T>
+        {
+        public:
+            
+            typedef expression_node<T>*    expression_ptr;
+            typedef vector_node<T>*       vector_node_ptr;
+            typedef vector_holder<T>*   vector_holder_ptr;
+            typedef vec_data_store<T>               vds_t;
+            
+            unary_vector_node(const operator_type& opr, expression_ptr branch0)
+            : unary_node<T>(opr,branch0),
+            vec0_node_ptr_(0),
+            temp_         (0),
+            temp_vec_node_(0)
+            {
+                bool vec0_is_ivec = false;
+                
+                if (is_vector_node(unary_node<T>::branch_))
+                {
+                    vec0_node_ptr_ = static_cast<vector_node_ptr>(unary_node<T>::branch_);
+                }
+                else if (is_ivector_node(unary_node<T>::branch_))
+                {
+                    vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
+                    
+                    if (0 != (vi = dynamic_cast<vector_interface<T>*>(unary_node<T>::branch_)))
+                    {
+                        vec0_node_ptr_ = vi->vec();
+                        vec0_is_ivec   = true;
+                    }
+                }
+                
+                if (vec0_node_ptr_)
+                {
+                    if (vec0_is_ivec)
+                        vds_ = vec0_node_ptr_->vds();
+                    else
+                        vds_ = vds_t(vec0_node_ptr_->size());
+                    
+                    temp_          = new vector_holder<T>(vds());
+                    temp_vec_node_ = new vector_node<T>  (vds(),temp_);
+                }
+            }
+            
+            ~unary_vector_node()
+            {
+                delete temp_;
+                delete temp_vec_node_;
+            }
+            
+            inline T value() const
+            {
+                unary_node<T>::branch_->value();
+                
+                if (vec0_node_ptr_)
+                {
+                    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]); \
+
+                        exprtk_loop( 0) exprtk_loop( 1)
+                        exprtk_loop( 2) exprtk_loop( 3)
+#ifndef exprtk_disable_superscalar_unroll
+                        exprtk_loop( 4) exprtk_loop( 5)
+                        exprtk_loop( 6) exprtk_loop( 7)
+                        exprtk_loop( 8) exprtk_loop( 9)
+                        exprtk_loop(10) exprtk_loop(11)
+                        exprtk_loop(12) exprtk_loop(13)
+                        exprtk_loop(14) exprtk_loop(15)
+#endif
+                        
+                        vec0 += lud.batch_size;
+                        vec1 += lud.batch_size;
+                    }
+                    
+                    int i = 0;
+                    
+                    switch (lud.remainder)
+                    {
+#define case_stmt(N)                                     \
+case N : { vec1[i] = Operation::process(vec0[i]); ++i; } \
+
+#ifndef exprtk_disable_superscalar_unroll
+                            case_stmt(15) case_stmt(14)
+                            case_stmt(13) case_stmt(12)
+                            case_stmt(11) case_stmt(10)
+                            case_stmt( 9) case_stmt( 8)
+                            case_stmt( 7) case_stmt( 6)
+                            case_stmt( 5) case_stmt( 4)
+#endif
+                            case_stmt( 3) case_stmt( 2)
+                            case_stmt( 1)
+                    }
+                    
+#undef exprtk_loop
+#undef case_stmt
+                    
+                    return (vds().data())[0];
+                }
+                else
+                    return std::numeric_limits<T>::quiet_NaN();
             }
-
-            if (vec1_node_ptr_)
+            
+            vector_node_ptr vec() const
             {
-               vector_holder<T>& vec0 = vec1_node_ptr_->ref();
-
-               vec_size_      = vec0.size();
-               data_          = new T[vec_size_];
-               temp_          = new vector_holder<T>(data_,vec_size_);
-               temp_vec_node_ = new vector_node<T>  (temp_);
+                return temp_vec_node_;
             }
-         }
-
-        ~vecarith_valvec_node()
-         {
-            delete[] data_;
-            delete   temp_;
-            delete   temp_vec_node_;
-         }
-
-         inline T value() const
-         {
-            if (vec1_node_ptr_)
+            
+            vector_node_ptr vec()
             {
-               const T v = binary_node<T>::branch_[0].first->value();
-                           binary_node<T>::branch_[1].first->value();
-
-               vector_holder<T>& vec1 = vec1_node_ptr_->ref();
-               vector_holder<T>& vec2 = *temp_;
-
-               for (std::size_t i = 0; i < vec_size_; ++i)
-               {
-                  T& vec1_i = *vec1[i];
-                  T& vec2_i = *vec2[i];
-
-                  vec2_i = Operation::process(v,vec1_i);
-               }
-
-               return *vec2[0];
+                return temp_vec_node_;
             }
-            else
-               return std::numeric_limits<T>::quiet_NaN();
-         }
-
-         vector_node_ptr vec() const
-         {
-            return temp_vec_node_;
-         }
-
-         vector_node_ptr vec()
-         {
-            return temp_vec_node_;
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_vecvalarith;
-         }
-
-         std::size_t size() const
-         {
-            return vec_size_;
-         }
-
-      private:
-
-         vector_node_ptr   vec1_node_ptr_;
-         std::size_t       vec_size_;
-         T*                data_;
-         vector_holder_ptr temp_;
-         vector_node_ptr   temp_vec_node_;
-      };
-
-      template <typename T, typename Operation>
-      class unary_vector_node : public unary_node<T>,
-                                public vector_interface<T>
-      {
-      public:
-
-         typedef expression_node<T>*    expression_ptr;
-         typedef vector_node<T>*       vector_node_ptr;
-         typedef vector_holder<T>*   vector_holder_ptr;
-
-         unary_vector_node(const operator_type& opr, expression_ptr branch0)
-         : unary_node<T>(opr,branch0),
-           vec0_node_ptr_(0),
-           vec_size_     (0),
-           data_         (0),
-           temp_         (0),
-           temp_vec_node_(0)
-         {
-            if (is_vector_node(unary_node<T>::branch_))
+            
+            inline typename expression_node<T>::node_type type() const
             {
-               vec0_node_ptr_ = static_cast<vector_node_ptr>(unary_node<T>::branch_);
+                return expression_node<T>::e_vecunaryop;
             }
-            else if (is_ivector_node(unary_node<T>::branch_))
+            
+            std::size_t size() const
             {
-               vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
-
-               if ((vi = dynamic_cast<vector_interface<T>*>(unary_node<T>::branch_)))
-               {
-                  vec0_node_ptr_ = vi->vec();
-               }
+                return vds().size();
             }
-
-            if (vec0_node_ptr_)
+            
+            vds_t& vds()
             {
-               vector_holder<T>& vec0 = vec0_node_ptr_->ref();
-
-               vec_size_      = vec0.size();
-               data_          = new T[vec_size_];
-               temp_          = new vector_holder<T>(data_,vec_size_);
-               temp_vec_node_ = new vector_node<T>  (temp_);
+                return vds_;
             }
-         }
-
-        ~unary_vector_node()
-         {
-            delete[] data_;
-            delete   temp_;
-            delete   temp_vec_node_;
-         }
-
-         inline T value() const
-         {
-            unary_node<T>::branch_->value();
-
-            if (vec0_node_ptr_)
+            
+            const vds_t& vds() const
             {
-               vector_holder<T>& vec0 = vec0_node_ptr_->ref();
-               vector_holder<T>& vec1 = *temp_;
-
-               for (std::size_t i = 0; i < vec_size_; ++i)
-               {
-                  T& vec0_i = *vec0[i];
-                  T& vec1_i = *vec1[i];
-
-                  vec1_i = Operation::process(vec0_i);
-               }
-
-               return *vec1[0];
+                return vds_;
             }
-            else
-               return std::numeric_limits<T>::quiet_NaN();
-         }
-
-         vector_node_ptr vec() const
-         {
-            return temp_vec_node_;
-         }
-
-         vector_node_ptr vec()
-         {
-            return temp_vec_node_;
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_vecunaryop;
-         }
-
-         std::size_t size() const
-         {
-            return vec_size_;
-         }
-
-      private:
-
-         vector_node_ptr   vec0_node_ptr_;
-         std::size_t       vec_size_;
-         T*                data_;
-         vector_holder_ptr temp_;
-         vector_node_ptr   temp_vec_node_;
-      };
-
-      template <typename T>
-      class scand_node : public binary_node<T>
-      {
-      public:
-
-         typedef expression_node<T>* expression_ptr;
-
-         scand_node(const operator_type& opr,
-                    expression_ptr branch0,
-                    expression_ptr branch1)
-         : binary_node<T>(opr,branch0,branch1)
-         {}
-
-         inline T value() const
-         {
-            return (
-                     std::not_equal_to<T>()
+            
+        private:
+            
+            vector_node_ptr   vec0_node_ptr_;
+            vector_holder_ptr temp_;
+            vector_node_ptr   temp_vec_node_;
+            vds_t             vds_;
+        };
+        
+        template <typename T>
+        class scand_node : public binary_node<T>
+        {
+        public:
+            
+            typedef expression_node<T>* expression_ptr;
+            
+            scand_node(const operator_type& opr,
+                       expression_ptr branch0,
+                       expression_ptr branch1)
+            : binary_node<T>(opr,branch0,branch1)
+            {}
+            
+            inline T value() const
+            {
+                return (
+                        std::not_equal_to<T>()
                         (T(0),binary_node<T>::branch_[0].first->value()) &&
-                     std::not_equal_to<T>()
+                        std::not_equal_to<T>()
                         (T(0),binary_node<T>::branch_[1].first->value())
-                   ) ? T(1) : T(0);
-         }
-      };
-
-      template <typename T>
-      class scor_node : public binary_node<T>
-      {
-      public:
-
-         typedef expression_node<T>* expression_ptr;
-
-         scor_node(const operator_type& opr,
-                   expression_ptr branch0,
-                   expression_ptr branch1)
-         : binary_node<T>(opr,branch0,branch1)
-         {}
-
-         inline T value() const
-         {
-            return (
-                     std::not_equal_to<T>()
+                        ) ? T(1) : T(0);
+            }
+        };
+        
+        template <typename T>
+        class scor_node : public binary_node<T>
+        {
+        public:
+            
+            typedef expression_node<T>* expression_ptr;
+            
+            scor_node(const operator_type& opr,
+                      expression_ptr branch0,
+                      expression_ptr branch1)
+            : binary_node<T>(opr,branch0,branch1)
+            {}
+            
+            inline T value() const
+            {
+                return (
+                        std::not_equal_to<T>()
                         (T(0),binary_node<T>::branch_[0].first->value()) ||
-                     std::not_equal_to<T>()
+                        std::not_equal_to<T>()
                         (T(0),binary_node<T>::branch_[1].first->value())
-                   ) ? T(1) : T(0);
-         }
-      };
-
-      template <typename T, typename IFunction, std::size_t N>
-      class function_N_node : public expression_node<T>
-      {
-      public:
-
-         // Function of N paramters.
-         typedef expression_node<T>* expression_ptr;
-         typedef std::pair<expression_ptr,bool> branch_t;
-         typedef IFunction ifunction;
-
-         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])
-         {
-            // Needed for incompetent and broken msvc compiler versions
-            #ifdef _MSC_VER
-             #pragma warning(push)
-             #pragma warning(disable: 4127)
-            #endif
-            if (N != NumBranches)
-               return false;
-            else
+                        ) ? T(1) : T(0);
+            }
+        };
+        
+        template <typename T, typename IFunction, std::size_t N>
+        class function_N_node : public expression_node<T>
+        {
+        public:
+            
+            // Function of N paramters.
+            typedef expression_node<T>* expression_ptr;
+            typedef std::pair<expression_ptr,bool> branch_t;
+            typedef IFunction ifunction;
+            
+            function_N_node(ifunction* func)
+            : function_((N == func->param_count) ? func : reinterpret_cast<ifunction*>(0)),
+            parameter_count_(func->param_count)
+            {}
+            
+            ~function_N_node()
             {
-               for (std::size_t i = 0; i < NumBranches; ++i)
-               {
-                  if (b[i])
-                     branch_[i] = std::make_pair(b[i],branch_deletable(b[i]));
-                  else
-                     return false;
-               }
-               return true;
-            }
-            #ifdef _MSC_VER
-             #pragma warning(pop)
-            #endif
-         }
-
-         inline bool operator <(const function_N_node<T,IFunction,N>& fn) const
-         {
-            return this < (&fn);
-         }
-
-         inline T value() const
-         {
-            // Needed for incompetent and broken msvc compiler versions
-            #ifdef _MSC_VER
-             #pragma warning(push)
-             #pragma warning(disable: 4127)
-            #endif
-            if ((0 == function_) || (0 == N))
-               return std::numeric_limits<T>::quiet_NaN();
-            else
+                cleanup_branches::execute<T,N>(branch_);
+            }
+            
+            template <std::size_t NumBranches>
+            bool init_branches(expression_ptr (&b)[NumBranches])
             {
-               T v[N];
-               evaluate_branches<T,N>::execute(v,branch_);
-               return invoke<T,N>::execute(*function_,v);
+                // Needed for incompetent and broken msvc compiler versions
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable: 4127)
+#endif
+                if (N != NumBranches)
+                    return false;
+                else
+                {
+                    for (std::size_t i = 0; i < NumBranches; ++i)
+                    {
+                        if (b[i])
+                            branch_[i] = std::make_pair(b[i],branch_deletable(b[i]));
+                        else
+                            return false;
+                    }
+                    return true;
+                }
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
             }
-            #ifdef _MSC_VER
-             #pragma warning(pop)
-            #endif
-         }
-
-         template <typename T_, std::size_t BranchCount>
-         struct evaluate_branches
-         {
-            static inline void execute(T_ (&v)[BranchCount], const branch_t (&b)[BranchCount])
+            
+            inline bool operator <(const function_N_node<T,IFunction,N>& fn) const
             {
-               for (std::size_t i = 0; i < BranchCount; ++i)
-               {
-                  v[i] = b[i].first->value();
-               }
+                return this < (&fn);
             }
-         };
-
-         template <typename T_>
-         struct evaluate_branches <T_,5>
-         {
-            static inline void execute(T_ (&v)[5], const branch_t (&b)[5])
-            {
-               v[0] = b[0].first->value();
-               v[1] = b[1].first->value();
-               v[2] = b[2].first->value();
-               v[3] = b[3].first->value();
-               v[4] = b[4].first->value();
-            }
-         };
-
-         template <typename T_>
-         struct evaluate_branches <T_,4>
-         {
-            static inline void execute(T_ (&v)[4], const branch_t (&b)[4])
+            
+            inline T value() const
             {
-               v[0] = b[0].first->value();
-               v[1] = b[1].first->value();
-               v[2] = b[2].first->value();
-               v[3] = b[3].first->value();
+                // Needed for incompetent and broken msvc compiler versions
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable: 4127)
+#endif
+                if ((0 == function_) || (0 == N))
+                    return std::numeric_limits<T>::quiet_NaN();
+                else
+                {
+                    T v[N];
+                    evaluate_branches<T,N>::execute(v,branch_);
+                    return invoke<T,N>::execute(*function_,v);
+                }
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
             }
-         };
-
-         template <typename T_>
-         struct evaluate_branches <T_,3>
-         {
-            static inline void execute(T_ (&v)[3], const branch_t (&b)[3])
+            
+            template <typename T_, std::size_t BranchCount>
+            struct evaluate_branches
+            {
+                static inline void execute(T_ (&v)[BranchCount], const branch_t (&b)[BranchCount])
+                {
+                    for (std::size_t i = 0; i < BranchCount; ++i)
+                    {
+                        v[i] = b[i].first->value();
+                    }
+                }
+            };
+            
+            template <typename T_>
+            struct evaluate_branches <T_,5>
+            {
+                static inline void execute(T_ (&v)[5], const branch_t (&b)[5])
+                {
+                    v[0] = b[0].first->value();
+                    v[1] = b[1].first->value();
+                    v[2] = b[2].first->value();
+                    v[3] = b[3].first->value();
+                    v[4] = b[4].first->value();
+                }
+            };
+            
+            template <typename T_>
+            struct evaluate_branches <T_,4>
+            {
+                static inline void execute(T_ (&v)[4], const branch_t (&b)[4])
+                {
+                    v[0] = b[0].first->value();
+                    v[1] = b[1].first->value();
+                    v[2] = b[2].first->value();
+                    v[3] = b[3].first->value();
+                }
+            };
+            
+            template <typename T_>
+            struct evaluate_branches <T_,3>
+            {
+                static inline void execute(T_ (&v)[3], const branch_t (&b)[3])
+                {
+                    v[0] = b[0].first->value();
+                    v[1] = b[1].first->value();
+                    v[2] = b[2].first->value();
+                }
+            };
+            
+            template <typename T_>
+            struct evaluate_branches <T_,2>
+            {
+                static inline void execute(T_ (&v)[2], const branch_t (&b)[2])
+                {
+                    v[0] = b[0].first->value();
+                    v[1] = b[1].first->value();
+                }
+            };
+            
+            template <typename T_>
+            struct evaluate_branches <T_,1>
+            {
+                static inline void execute(T_ (&v)[1], const branch_t (&b)[1])
+                {
+                    v[0] = b[0].first->value();
+                }
+            };
+            
+            template <typename T_, std::size_t ParamCount>
+            struct invoke { static inline T execute(ifunction&, branch_t (&)[ParamCount]) { return std::numeric_limits<T_>::quiet_NaN(); } };
+            
+            template <typename T_>
+            struct invoke<T_,20>
+            {
+                static inline T_ execute(ifunction& f, T_ (&v)[20])
+                { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15],v[16],v[17],v[18],v[19]); }
+            };
+            
+            template <typename T_>
+            struct invoke<T_,19>
+            {
+                static inline T_ execute(ifunction& f, T_ (&v)[19])
+                { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15],v[16],v[17],v[18]); }
+            };
+            
+            template <typename T_>
+            struct invoke<T_,18>
+            {
+                static inline T_ execute(ifunction& f, T_ (&v)[18])
+                { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15],v[16],v[17]); }
+            };
+            
+            template <typename T_>
+            struct invoke<T_,17>
+            {
+                static inline T_ execute(ifunction& f, T_ (&v)[17])
+                { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15],v[16]); }
+            };
+            
+            template <typename T_>
+            struct invoke<T_,16>
+            {
+                static inline T_ execute(ifunction& f, T_ (&v)[16])
+                { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15]); }
+            };
+            
+            template <typename T_>
+            struct invoke<T_,15>
             {
-               v[0] = b[0].first->value();
-               v[1] = b[1].first->value();
-               v[2] = b[2].first->value();
+                static inline T_ execute(ifunction& f, T_ (&v)[15])
+                { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14]); }
+            };
+            
+            template <typename T_>
+            struct invoke<T_,14>
+            {
+                static inline T_ execute(ifunction& f, T_ (&v)[14])
+                { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13]); }
+            };
+            
+            template <typename T_>
+            struct invoke<T_,13>
+            {
+                static inline T_ execute(ifunction& f, T_ (&v)[13])
+                { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12]); }
+            };
+            
+            template <typename T_>
+            struct invoke<T_,12>
+            {
+                static inline T_ execute(ifunction& f, T_ (&v)[12])
+                { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11]); }
+            };
+            
+            template <typename T_>
+            struct invoke<T_,11>
+            {
+                static inline T_ execute(ifunction& f, T_ (&v)[11])
+                { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10]); }
+            };
+            
+            template <typename T_>
+            struct invoke<T_,10>
+            {
+                static inline T_ execute(ifunction& f, T_ (&v)[10])
+                { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9]); }
+            };
+            
+            template <typename T_>
+            struct invoke<T_,9>
+            {
+                static inline T_ execute(ifunction& f, T_ (&v)[9])
+                { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8]); }
+            };
+            
+            template <typename T_>
+            struct invoke<T_,8>
+            {
+                static inline T_ execute(ifunction& f, T_ (&v)[8])
+                { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7]); }
+            };
+            
+            template <typename T_>
+            struct invoke<T_,7>
+            {
+                static inline T_ execute(ifunction& f, T_ (&v)[7])
+                { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6]); }
+            };
+            
+            template <typename T_>
+            struct invoke<T_,6>
+            {
+                static inline T_ execute(ifunction& f, T_ (&v)[6])
+                { return f(v[0],v[1],v[2],v[3],v[4],v[5]); }
+            };
+            
+            template <typename T_>
+            struct invoke<T_,5>
+            {
+                static inline T_ execute(ifunction& f, T_ (&v)[5])
+                { return f(v[0],v[1],v[2],v[3],v[4]); }
+            };
+            
+            template <typename T_>
+            struct invoke<T_,4>
+            {
+                static inline T_ execute(ifunction& f, T_ (&v)[4])
+                { return f(v[0],v[1],v[2],v[3]); }
+            };
+            
+            template <typename T_>
+            struct invoke<T_,3>
+            {
+                static inline T_ execute(ifunction& f, T_ (&v)[3])
+                { return f(v[0],v[1],v[2]); }
+            };
+            
+            template <typename T_>
+            struct invoke<T_,2>
+            {
+                static inline T_ execute(ifunction& f, T_ (&v)[2])
+                { return f(v[0],v[1]); }
+            };
+            
+            template <typename T_>
+            struct invoke<T_,1>
+            {
+                static inline T_ execute(ifunction& f, T_ (&v)[1])
+                { return f(v[0]); }
+            };
+            
+            inline typename expression_node<T>::node_type type() const
+            {
+                return expression_node<T>::e_function;
             }
-         };
-
-         template <typename T_>
-         struct evaluate_branches <T_,2>
-         {
-            static inline void execute(T_ (&v)[2], const branch_t (&b)[2])
+            
+        private:
+            
+            ifunction* function_;
+            std::size_t parameter_count_;
+            branch_t branch_[N];
+        };
+        
+        template <typename T, typename IFunction>
+        class function_N_node<T,IFunction,0> : public expression_node<T>
+        {
+        public:
+            
+            typedef expression_node<T>* expression_ptr;
+            typedef IFunction ifunction;
+            
+            function_N_node(ifunction* func)
+            : function_((0 == func->param_count) ? func : reinterpret_cast<ifunction*>(0))
+            {}
+            
+            inline bool operator <(const function_N_node<T,IFunction,0>& fn) const
             {
-               v[0] = b[0].first->value();
-               v[1] = b[1].first->value();
+                return this < (&fn);
             }
-         };
-
-         template <typename T_>
-         struct evaluate_branches <T_,1>
-         {
-            static inline void execute(T_ (&v)[1], const branch_t (&b)[1])
+            
+            inline T value() const
             {
-               v[0] = b[0].first->value();
+                if (function_)
+                    return (*function_)();
+                else
+                    return std::numeric_limits<T>::quiet_NaN();
             }
-         };
-
-         template <typename T_, std::size_t ParamCount>
-         struct invoke { static inline T execute(ifunction&, branch_t (&)[ParamCount]) { return std::numeric_limits<T_>::quiet_NaN(); } };
-
-         template <typename T_>
-         struct invoke<T_,20>
-         {
-            static inline T_ execute(ifunction& f, T_ (&v)[20])
-            { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15],v[16],v[17],v[18],v[19]); }
-         };
-
-         template <typename T_>
-         struct invoke<T_,19>
-         {
-            static inline T_ execute(ifunction& f, T_ (&v)[19])
-            { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15],v[16],v[17],v[18]); }
-         };
-
-         template <typename T_>
-         struct invoke<T_,18>
-         {
-            static inline T_ execute(ifunction& f, T_ (&v)[18])
-            { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15],v[16],v[17]); }
-         };
-
-         template <typename T_>
-         struct invoke<T_,17>
-         {
-            static inline T_ execute(ifunction& f, T_ (&v)[17])
-            { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15],v[16]); }
-         };
-
-         template <typename T_>
-         struct invoke<T_,16>
-         {
-            static inline T_ execute(ifunction& f, T_ (&v)[16])
-            { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15]); }
-         };
-
-         template <typename T_>
-         struct invoke<T_,15>
-         {
-            static inline T_ execute(ifunction& f, T_ (&v)[15])
-            { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14]); }
-         };
-
-         template <typename T_>
-         struct invoke<T_,14>
-         {
-            static inline T_ execute(ifunction& f, T_ (&v)[14])
-            { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13]); }
-         };
-
-         template <typename T_>
-         struct invoke<T_,13>
-         {
-            static inline T_ execute(ifunction& f, T_ (&v)[13])
-            { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12]); }
-         };
-
-         template <typename T_>
-         struct invoke<T_,12>
-         {
-            static inline T_ execute(ifunction& f, T_ (&v)[12])
-            { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11]); }
-         };
-
-         template <typename T_>
-         struct invoke<T_,11>
-         {
-            static inline T_ execute(ifunction& f, T_ (&v)[11])
-            { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10]); }
-         };
-
-         template <typename T_>
-         struct invoke<T_,10>
-         {
-            static inline T_ execute(ifunction& f, T_ (&v)[10])
-            { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9]); }
-         };
-
-         template <typename T_>
-         struct invoke<T_,9>
-         {
-            static inline T_ execute(ifunction& f, T_ (&v)[9])
-            { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8]); }
-         };
-
-         template <typename T_>
-         struct invoke<T_,8>
-         {
-            static inline T_ execute(ifunction& f, T_ (&v)[8])
-            { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7]); }
-         };
-
-         template <typename T_>
-         struct invoke<T_,7>
-         {
-            static inline T_ execute(ifunction& f, T_ (&v)[7])
-            { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6]); }
-         };
-
-         template <typename T_>
-         struct invoke<T_,6>
-         {
-            static inline T_ execute(ifunction& f, T_ (&v)[6])
-            { return f(v[0],v[1],v[2],v[3],v[4],v[5]); }
-         };
-
-         template <typename T_>
-         struct invoke<T_,5>
-         {
-            static inline T_ execute(ifunction& f, T_ (&v)[5])
-            { return f(v[0],v[1],v[2],v[3],v[4]); }
-         };
-
-         template <typename T_>
-         struct invoke<T_,4>
-         {
-            static inline T_ execute(ifunction& f, T_ (&v)[4])
-            { return f(v[0],v[1],v[2],v[3]); }
-         };
-
-         template <typename T_>
-         struct invoke<T_,3>
-         {
-            static inline T_ execute(ifunction& f, T_ (&v)[3])
-            { return f(v[0],v[1],v[2]); }
-         };
-
-         template <typename T_>
-         struct invoke<T_,2>
-         {
-            static inline T_ execute(ifunction& f, T_ (&v)[2])
-            { return f(v[0],v[1]); }
-         };
-
-         template <typename T_>
-         struct invoke<T_,1>
-         {
-            static inline T_ execute(ifunction& f, T_ (&v)[1])
-            { return f(v[0]); }
-         };
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_function;
-         }
-
-      private:
-
-         ifunction* function_;
-         std::size_t parameter_count_;
-         branch_t branch_[N];
-      };
-
-      template <typename T, typename IFunction>
-      class function_N_node<T,IFunction,0> : public expression_node<T>
-      {
-      public:
-
-         typedef expression_node<T>* expression_ptr;
-         typedef IFunction ifunction;
-
-         function_N_node(ifunction* func)
-         : function_((0 == func->param_count) ? func : reinterpret_cast<ifunction*>(0))
-         {}
-
-         inline bool operator <(const function_N_node<T,IFunction,0>& fn) const
-         {
-            return this < (&fn);
-         }
-
-         inline T value() const
-         {
-            if (function_)
-               return (*function_)();
-            else
-               return std::numeric_limits<T>::quiet_NaN();
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_function;
-         }
-
-      private:
-
-         ifunction* function_;
-      };
-
-      template <typename T, typename VarArgFunction>
-      class vararg_function_node : public expression_node<T>
-      {
-      public:
-
-         typedef expression_node<T>* expression_ptr;
-
-         vararg_function_node(VarArgFunction*  func,
-                              const std::vector<expression_ptr>& arg_list)
-         : function_(func),
-           arg_list_(arg_list)
-         {
-            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)
+            
+            inline typename expression_node<T>::node_type type() const
             {
-               if (arg_list_[i] && !details::is_variable_node(arg_list_[i]))
-               {
-                  delete arg_list_[i];
-                  arg_list_[i] = 0;
-               }
+                return expression_node<T>::e_function;
             }
-         }
-
-         inline bool operator <(const vararg_function_node<T,VarArgFunction>& fn) const
-         {
-            return this < (&fn);
-         }
-
-         inline T value() const
-         {
-            if (function_)
+            
+        private:
+            
+            ifunction* function_;
+        };
+        
+        template <typename T, typename VarArgFunction>
+        class vararg_function_node : public expression_node<T>
+        {
+        public:
+            
+            typedef expression_node<T>* expression_ptr;
+            
+            vararg_function_node(VarArgFunction*  func,
+                                 const std::vector<expression_ptr>& arg_list)
+            : function_(func),
+            arg_list_(arg_list)
+            {
+                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]))
+                    {
+                        delete arg_list_[i];
+                        arg_list_[i] = 0;
+                    }
+                }
+            }
+            
+            inline bool operator <(const vararg_function_node<T,VarArgFunction>& fn) const
+            {
+                return this < (&fn);
+            }
+            
+            inline T value() const
+            {
+                if (function_)
+                {
+                    populate_value_list();
+                    return (*function_)(value_list_);
+                }
+                else
+                    return std::numeric_limits<T>::quiet_NaN();
+            }
+            
+            inline typename expression_node<T>::node_type type() const
+            {
+                return expression_node<T>::e_vafunction;
+            }
+            
+        private:
+            
+            inline void populate_value_list() const
+            {
+                for (std::size_t i = 0; i < arg_list_.size(); ++i)
+                {
+                    value_list_[i] = arg_list_[i]->value();
+                }
+            }
+            
+            VarArgFunction* function_;
+            std::vector<expression_ptr> arg_list_;
+            mutable std::vector<T> value_list_;
+        };
+        
+        template <typename T, typename GenericFunction>
+        class generic_function_node : public expression_node<T>
+        {
+        public:
+            
+            typedef type_store<T>                         type_store_t;
+            typedef expression_node<T>*                 expression_ptr;
+            typedef variable_node<T>                   variable_node_t;
+            typedef vector_node<T>                       vector_node_t;
+            typedef variable_node_t*               variable_node_ptr_t;
+            typedef vector_node_t*                   vector_node_ptr_t;
+            typedef range_interface<T>               range_interface_t;
+            typedef range_data_type<T>               range_data_type_t;
+            typedef range_pack<T>                              range_t;
+            typedef std::pair<expression_ptr,bool>            branch_t;
+            typedef std::pair<void*,std::size_t>                void_t;
+            typedef std::vector<T>                            tmp_vs_t;
+            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))
+            : function_(func),
+            arg_list_(arg_list)
+            {}
+            
+            virtual ~generic_function_node()
+            {
+                cleanup_branches::execute(branch_);
+            }
+            
+            virtual bool init_branches()
+            {
+                expr_as_vec1_store_.resize(arg_list_.size(),T(0)               );
+                typestore_list_    .resize(arg_list_.size(),type_store_t()     );
+                range_list_        .resize(arg_list_.size(),range_data_type_t());
+                branch_            .resize(arg_list_.size(),branch_t((expression_ptr)0,false));
+                
+                for (std::size_t i = 0; i < arg_list_.size(); ++i)
+                {
+                    type_store_t& ts = typestore_list_[i];
+                    
+                    if (0 == arg_list_[i])
+                        return false;
+                    else if (is_ivector_node(arg_list_[i]))
+                    {
+                        vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
+                        
+                        if (0 == (vi = dynamic_cast<vector_interface<T>*>(arg_list_[i])))
+                            return false;
+                        
+                        ts.size = vi->size();
+                        ts.data = vi->vds().data();
+                        ts.type = type_store_t::e_vector;
+                    }
+                    else if (is_generally_string_node(arg_list_[i]))
+                    {
+                        string_base_node<T>* sbn = reinterpret_cast<string_base_node<T>*>(0);
+                        
+                        if (0 == (sbn = dynamic_cast<string_base_node<T>*>(arg_list_[i])))
+                            return false;
+                        
+                        ts.size = sbn->size();
+                        ts.data = reinterpret_cast<void*>(const_cast<char*>(sbn->base()));
+                        ts.type = type_store_t::e_string;
+                        
+                        range_list_[i].data      = ts.data;
+                        range_list_[i].size      = ts.size;
+                        range_list_[i].type_size = sizeof(char);
+                        range_list_[i].str_node  = sbn;
+                        
+                        range_interface_t* ri = reinterpret_cast<range_interface_t*>(0);
+                        
+                        if (0 == (ri = dynamic_cast<range_interface_t*>(arg_list_[i])))
+                            return false;
+                        
+                        range_t& rp = ri->range_ref();
+                        
+                        if (
+                            rp.const_range() &&
+                            is_const_string_range_node(arg_list_[i])
+                            )
+                        {
+                            ts.size = rp.const_size();
+                            ts.data = static_cast<char*>(ts.data) + rp.n0_c.second;
+                            range_list_[i].range = reinterpret_cast<range_t*>(0);
+                        }
+                        else
+                            range_list_[i].range = &(ri->range_ref());
+                    }
+                    else if (is_variable_node(arg_list_[i]))
+                    {
+                        variable_node_ptr_t var = variable_node_ptr_t(0);
+                        
+                        if (0 == (var = dynamic_cast<variable_node_ptr_t>(arg_list_[i])))
+                            return false;
+                        
+                        ts.size = 1;
+                        ts.data = &var->ref();
+                        ts.type = type_store_t::e_scalar;
+                    }
+                    else
+                    {
+                        ts.size = 1;
+                        ts.data = reinterpret_cast<void*>(&expr_as_vec1_store_[i]);
+                        ts.type = type_store_t::e_scalar;
+                    }
+                    
+                    branch_[i] = std::make_pair(arg_list_[i],branch_deletable(arg_list_[i]));
+                }
+                
+                return true;
+            }
+            
+            inline bool operator <(const generic_function_node<T,GenericFunction>& fn) const
+            {
+                return this < (&fn);
+            }
+            
+            inline T value() const
+            {
+                if (function_)
+                {
+                    if (populate_value_list())
+                    {
+                        typedef typename GenericFunction::parameter_list_t parameter_list_t;
+                        
+                        return (*function_)(parameter_list_t(typestore_list_));
+                    }
+                }
+                
+                return std::numeric_limits<T>::quiet_NaN();
+            }
+            
+            inline typename expression_node<T>::node_type type() const
+            {
+                return expression_node<T>::e_genfunction;
+            }
+            
+        protected:
+            
+            inline virtual bool populate_value_list() const
+            {
+                for (std::size_t i = 0; i < branch_.size(); ++i)
+                {
+                    expr_as_vec1_store_[i] = branch_[i].first->value();
+                }
+                
+                for (std::size_t i = 0; i < branch_.size(); ++i)
+                {
+                    range_data_type_t& rdt = range_list_[i];
+                    
+                    if (rdt.range)
+                    {
+                        range_t&    rp = (*rdt.range);
+                        std::size_t r0 = 0;
+                        std::size_t r1 = 0;
+                        
+                        if (rp(r0,r1,rdt.size))
+                        {
+                            type_store_t& ts = typestore_list_[i];
+                            
+                            ts.size = rp.cache_size();
+                            
+                            if (ts.type == type_store_t::e_string)
+                                ts.data = const_cast<char*>(rdt.str_node->base()) + rp.cache.first;
+                            else
+                                ts.data = static_cast<char*>(rdt.data) + (rp.cache.first * rdt.type_size);
+                        }
+                        else
+                            return false;
+                    }
+                }
+                
+                return true;
+            }
+            
+            GenericFunction* function_;
+            mutable typestore_list_t typestore_list_;
+            
+        private:
+            
+            std::vector<expression_ptr> arg_list_;
+            std::vector<branch_t> branch_;
+            mutable tmp_vs_t expr_as_vec1_store_;
+            mutable range_list_t range_list_;
+        };
+        
+        template <typename T, typename StringFunction>
+        class string_function_node : public generic_function_node<T,StringFunction>,
+        public string_base_node<T>,
+        public range_interface <T>
+        {
+        public:
+            
+            typedef generic_function_node<T,StringFunction> gen_function_t;
+            typedef range_pack<T> range_t;
+            
+            string_function_node(StringFunction* func,
+                                 const std::vector<typename gen_function_t::expression_ptr>& arg_list)
+            : gen_function_t(arg_list,func)
+            {
+                range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
+                range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
+                range_.cache.first  = range_.n0_c.second;
+                range_.cache.second = range_.n1_c.second;
+            }
+            
+            inline bool operator <(const string_function_node<T,StringFunction>& fn) const
+            {
+                return this < (&fn);
+            }
+            
+            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_));
+                        
+                        range_.n1_c.second  = ret_string_.size() - 1;
+                        range_.cache.second = range_.n1_c.second;
+                        
+                        return result;
+                    }
+                }
+                
+                return result;
+            }
+            
+            inline typename expression_node<T>::node_type type() const
+            {
+                return expression_node<T>::e_strfunction;
+            }
+            
+            std::string str() const
+            {
+                return ret_string_;
+            }
+            
+            const char* base() const
+            {
+                return &ret_string_[0];
+            }
+            
+            std::size_t size() const
+            {
+                return ret_string_.size();
+            }
+            
+            range_t& range_ref()
+            {
+                return range_;
+            }
+            
+            const range_t& range_ref() const
+            {
+                return range_;
+            }
+            
+        protected:
+            
+            mutable range_t     range_;
+            mutable std::string ret_string_;
+        };
+        
+        template <typename T, typename GenericFunction>
+        class multimode_genfunction_node : public generic_function_node<T,GenericFunction>
+        {
+        public:
+            
+            typedef generic_function_node<T,GenericFunction> gen_function_t;
+            typedef range_pack<T> range_t;
+            
+            multimode_genfunction_node(GenericFunction* func,
+                                       const std::size_t& param_seq_index,
+                                       const std::vector<typename gen_function_t::expression_ptr>& arg_list)
+            : gen_function_t(arg_list,func),
+            param_seq_index_(param_seq_index)
+            {}
+            
+            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 result;
+            }
+            
+            inline typename expression_node<T>::node_type type() const
+            {
+                return expression_node<T>::e_genfunction;
+            }
+            
+        private:
+            
+            std::size_t param_seq_index_;
+        };
+        
+        template <typename T, typename StringFunction>
+        class multimode_strfunction_node : public string_function_node<T,StringFunction>
+        {
+        public:
+            
+            typedef string_function_node<T,StringFunction> str_function_t;
+            typedef range_pack<T> range_t;
+            
+            multimode_strfunction_node(StringFunction* func,
+                                       const std::size_t& param_seq_index,
+                                       const std::vector<typename str_function_t::expression_ptr>& arg_list)
+            : str_function_t(func,arg_list),
+            param_seq_index_(param_seq_index)
+            {}
+            
+            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_));
+                        
+                        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;
+                        
+                        return result;
+                    }
+                }
+                
+                return result;
+            }
+            
+            inline typename expression_node<T>::node_type type() const
+            {
+                return expression_node<T>::e_strfunction;
+            }
+            
+        private:
+            
+            std::size_t param_seq_index_;
+        };
+        
+        class return_exception
+        {};
+        
+        template <typename T>
+        class null_igenfunc
+        {
+        public:
+            
+            virtual ~null_igenfunc()
+            {}
+            
+            typedef type_store<T> generic_type;
+            typedef typename generic_type::parameter_list parameter_list_t;
+            
+            inline virtual T operator()(parameter_list_t)
             {
-               populate_value_list();
-               return (*function_)(value_list_);
+                return std::numeric_limits<T>::quiet_NaN();
             }
-            else
-               return std::numeric_limits<T>::quiet_NaN();
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_vafunction;
-         }
-
-      private:
-
-         inline void populate_value_list() const
-         {
-            for (std::size_t i = 0; i < arg_list_.size(); ++i)
+        };
+        
+        template <typename T>
+        class return_node : public generic_function_node<T,null_igenfunc<T> >
+        {
+        public:
+            
+            typedef null_igenfunc<T> igeneric_function_t;
+            typedef igeneric_function_t* igeneric_function_ptr;
+            typedef generic_function_node<T,igeneric_function_t> gen_function_t;
+            typedef results_context<T> results_context_t;
+            
+            return_node(const std::vector<typename gen_function_t::expression_ptr>& arg_list,
+                        results_context_t& rc)
+            : gen_function_t  (arg_list),
+            results_context_(&rc)
+            {}
+            
+            inline T value() const
             {
-               value_list_[i] = arg_list_[i]->value();
+                if (
+                    (0 != results_context_) &&
+                    gen_function_t::populate_value_list()
+                    )
+                {
+                    typedef typename type_store<T>::parameter_list parameter_list_t;
+                    
+                    results_context_->
+                    assign(parameter_list_t(gen_function_t::typestore_list_));
+                    
+                    throw return_exception();
+                }
+                
+                return std::numeric_limits<T>::quiet_NaN();
+            }
+            
+            inline typename expression_node<T>::node_type type() const
+            {
+                return expression_node<T>::e_return;
+            }
+            
+        private:
+            
+            results_context_t* results_context_;
+        };
+        
+        template <typename T>
+        class return_envelope_node : public expression_node<T>
+        {
+        public:
+            
+            typedef expression_node<T>* expression_ptr;
+            typedef results_context<T>  results_context_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()
+            {
+                if (body_ && body_deletable_)
+                {
+                    delete body_;
+                }
+            }
+            
+            inline T value() const
+            {
+                try
+                {
+                    return_invoked_ = false;
+                    results_context_->clear();
+                    
+                    return body_->value();
+                }
+                catch(const return_exception&)
+                {
+                    return_invoked_ = true;
+                    return std::numeric_limits<T>::quiet_NaN();
+                }
+            }
+            
+            inline typename expression_node<T>::node_type type() const
+            {
+                return expression_node<T>::e_retenv;
+            }
+            
+            inline bool* retinvk_ptr()
+            {
+                return &return_invoked_;
+            }
+            
+        private:
+            
+            results_context_t* results_context_;
+            mutable bool       return_invoked_;
+            expression_ptr     body_;
+            bool               body_deletable_;
+        };
+        
+#define exprtk_define_unary_op(OpName)                    \
+template <typename T>                                     \
+struct OpName##_op                                        \
+{                                                         \
+typedef typename functor_t<T>::Type Type;              \
+typedef typename expression_node<T>::node_type node_t; \
+\
+static inline T process(Type v)                        \
+{                                                      \
+return numeric:: OpName (v);                        \
+}                                                      \
+\
+static inline node_t type()                            \
+{                                                      \
+return expression_node<T>::e_##OpName;              \
+}                                                      \
+\
+static inline details::operator_type operation()       \
+{                                                      \
+return details::e_##OpName;                         \
+}                                                      \
+};                                                        \
+
+        exprtk_define_unary_op(abs  )
+        exprtk_define_unary_op(acos )
+        exprtk_define_unary_op(acosh)
+        exprtk_define_unary_op(asin )
+        exprtk_define_unary_op(asinh)
+        exprtk_define_unary_op(atan )
+        exprtk_define_unary_op(atanh)
+        exprtk_define_unary_op(ceil )
+        exprtk_define_unary_op(cos  )
+        exprtk_define_unary_op(cosh )
+        exprtk_define_unary_op(cot  )
+        exprtk_define_unary_op(csc  )
+        exprtk_define_unary_op(d2g  )
+        exprtk_define_unary_op(d2r  )
+        exprtk_define_unary_op(erf  )
+        exprtk_define_unary_op(erfc )
+        exprtk_define_unary_op(exp  )
+        exprtk_define_unary_op(expm1)
+        exprtk_define_unary_op(floor)
+        exprtk_define_unary_op(frac )
+        exprtk_define_unary_op(g2d  )
+        exprtk_define_unary_op(log  )
+        exprtk_define_unary_op(log10)
+        exprtk_define_unary_op(log2 )
+        exprtk_define_unary_op(log1p)
+        exprtk_define_unary_op(ncdf )
+        exprtk_define_unary_op(neg  )
+        exprtk_define_unary_op(notl )
+        exprtk_define_unary_op(pos  )
+        exprtk_define_unary_op(r2d  )
+        exprtk_define_unary_op(round)
+        exprtk_define_unary_op(sec  )
+        exprtk_define_unary_op(sgn  )
+        exprtk_define_unary_op(sin  )
+        exprtk_define_unary_op(sinc )
+        exprtk_define_unary_op(sinh )
+        exprtk_define_unary_op(sqrt )
+        exprtk_define_unary_op(tan  )
+        exprtk_define_unary_op(tanh )
+        exprtk_define_unary_op(trunc)
+#undef exprtk_define_unary_op
+        
+        template <typename T>
+        struct opr_base
+        {
+            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;
+        };
+        
+        template <typename T>
+        struct add_op : public opr_base<T>
+        {
+            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; }
+            static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_add; }
+            static inline details::operator_type operation() { return details::e_add; }
+        };
+        
+        template <typename T>
+        struct mul_op : public opr_base<T>
+        {
+            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; }
+            static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_mul; }
+            static inline details::operator_type operation() { return details::e_mul; }
+        };
+        
+        template <typename T>
+        struct sub_op : public opr_base<T>
+        {
+            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; }
+            static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_sub; }
+            static inline details::operator_type operation() { return details::e_sub; }
+        };
+        
+        template <typename T>
+        struct div_op : public opr_base<T>
+        {
+            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; }
+            static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_div; }
+            static inline details::operator_type operation() { return details::e_div; }
+        };
+        
+        template <typename T>
+        struct mod_op : public opr_base<T>
+        {
+            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; }
+            static inline details::operator_type operation() { return details::e_mod; }
+        };
+        
+        template <typename T>
+        struct pow_op : public opr_base<T>
+        {
+            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; }
+            static inline details::operator_type operation() { return details::e_pow; }
+        };
+        
+        template <typename T>
+        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; }
+            static inline details::operator_type operation() { return details::e_lt; }
+        };
+        
+        template <typename T>
+        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; }
+            static inline details::operator_type operation() { return details::e_lte; }
+        };
+        
+        template <typename T>
+        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; }
+            static inline details::operator_type operation() { return details::e_gt; }
+        };
+        
+        template <typename T>
+        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; }
+            static inline details::operator_type operation() { return details::e_gte; }
+        };
+        
+        template <typename T>
+        struct eq_op : public opr_base<T>
+        {
+            typedef typename opr_base<T>::Type Type;
+            static inline T process(Type t1, Type t2) { return (std::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_eq; }
+            static inline details::operator_type operation() { return details::e_eq; }
+        };
+        
+        template <typename T>
+        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<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_eq; }
+            static inline details::operator_type operation() { return details::e_equal; }
+        };
+        
+        template <typename T>
+        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; }
+            static inline details::operator_type operation() { return details::e_ne; }
+        };
+        
+        template <typename T>
+        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; }
+        };
+        
+        template <typename T>
+        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; }
+        };
+        
+        template <typename T>
+        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; }
+        };
+        
+        template <typename T>
+        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; }
+        };
+        
+        template <typename T>
+        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; }
+        };
+        
+        template <typename T>
+        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; }
+        };
+        
+        template <typename T>
+        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; }
+            static inline details::operator_type operation() { return details::e_in; }
+        };
+        
+        template <typename T>
+        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; }
+            static inline details::operator_type operation() { return details::e_like; }
+        };
+        
+        template <typename T>
+        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; }
+            static inline details::operator_type operation() { return details::e_ilike; }
+        };
+        
+        template <typename T>
+        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)
+            {
+                return ((t0 <= t1) && (t1 <= t2)) ? T(1) : T(0);
+            }
+            static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_inranges; }
+            static inline details::operator_type operation() { return details::e_inrange; }
+        };
+        
+        template <typename T>
+        inline T value(details::expression_node<T>* n)
+        {
+            return n->value();
+        }
+        
+        template <typename T>
+        inline T value(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>
+            static inline T process(const Sequence<Type,Allocator>& arg_list)
+            {
+                switch (arg_list.size())
+                {
+                    case 0  : return T(0);
+                    case 1  : return process_1(arg_list);
+                    case 2  : return process_2(arg_list);
+                    case 3  : return process_3(arg_list);
+                    case 4  : return process_4(arg_list);
+                    case 5  : return process_5(arg_list);
+                    default :
+                    {
+                        T result = T(0);
+                        
+                        for (std::size_t i = 0; i < arg_list.size(); ++i)
+                        {
+                            result += value(arg_list[i]);
+                        }
+                        
+                        return result;
+                    }
+                }
             }
-         }
-
-         VarArgFunction* function_;
-         std::vector<expression_ptr> arg_list_;
-         mutable std::vector<T> value_list_;
-      };
-
-      template <typename T, typename GenericFunction>
-      class generic_function_node : public expression_node<T>
-      {
-      public:
-
-         typedef type_store<T>                      type_store_t;
-         typedef expression_node<T>*              expression_ptr;
-         typedef variable_node<T>                variable_node_t;
-         typedef vector_elem_node<T>          vector_elem_node_t;
-         typedef vector_node<T>                    vector_node_t;
-         typedef variable_node_t*            variable_node_ptr_t;
-         typedef vector_elem_node_t*      vector_elem_node_ptr_t;
-         typedef vector_node_t*                vector_node_ptr_t;
-         typedef range_interface<T>            range_interface_t;
-         typedef range_data_type<T>            range_data_type_t;
-         typedef range_pack<T>                           range_t;
-         typedef std::pair<expression_ptr,bool>         branch_t;
-         typedef std::pair<void*,std::size_t>             void_t;
-         typedef std::vector<T>                         tmp_vs_t;
-         typedef std::vector<type_store_t>      typestore_list_t;
-         typedef std::vector<range_data_type_t>     range_list_t;
-
-         generic_function_node(GenericFunction* func,
-                               const std::vector<expression_ptr>& arg_list)
-         : function_(func),
-           arg_list_(arg_list)
-         {}
-
-        ~generic_function_node()
-         {
-            cleanup_branches::execute(branch_);
-         }
-
-         virtual bool init_branches()
-         {
-            expr_as_vec1_store_.resize(arg_list_.size(),T(0)               );
-            typestore_list_    .resize(arg_list_.size(),type_store_t()     );
-            range_list_        .resize(arg_list_.size(),range_data_type_t());
-            branch_            .resize(arg_list_.size(),branch_t((expression_ptr)0,false));
-
-            for (std::size_t i = 0; i < arg_list_.size(); ++i)
+            
+            template <typename Sequence>
+            static inline T process_1(const Sequence& arg_list)
             {
-               type_store_t& ts = typestore_list_[i];
-
-               if (0 == arg_list_[i])
-                  return false;
-               else if (is_ivector_node(arg_list_[i]))
-               {
-                  vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
-
-                  if (0 == (vi = dynamic_cast<vector_interface<T>*>(arg_list_[i])))
-                     return false;
-
-                  ts.size = vi->size();
-                  ts.data = vi->vec()->ref()[0];
-                  ts.type = type_store_t::e_vector;
-               }
-               else if (is_generally_string_node(arg_list_[i]))
-               {
-                  string_base_node<T>* sbn = reinterpret_cast<string_base_node<T>*>(0);
-
-                  if (0 == (sbn = dynamic_cast<string_base_node<T>*>(arg_list_[i])))
-                     return false;
-
-                  ts.size = sbn->size();
-                  ts.data = reinterpret_cast<void*>(const_cast<char*>(sbn->base()));
-                  ts.type = type_store_t::e_string;
-
-                  range_list_[i].data      = ts.data;
-                  range_list_[i].size      = ts.size;
-                  range_list_[i].type_size = sizeof(char);
-                  range_list_[i].str_node  = sbn;
-
-                  if (is_generally_string_node(arg_list_[i]))
-                  {
-                     range_interface_t* ri = reinterpret_cast<range_interface_t*>(0);
-
-                     if (0 == (ri = dynamic_cast<range_interface_t*>(arg_list_[i])))
-                        return false;
-
-                     range_t& rp = ri->range_ref();
-
-                     if (
-                          rp.const_range() &&
-                          is_const_string_range_node(arg_list_[i])
-                        )
-                     {
-                        ts.size = rp.const_size();
-                        ts.data = static_cast<char*>(ts.data) + rp.n0_c.second;
-                        range_list_[i].range = reinterpret_cast<range_t*>(0);
-                     }
-                     else
-                        range_list_[i].range = &(ri->range_ref());
-                  }
-               }
-               else if (is_variable_node(arg_list_[i]))
-               {
-                  variable_node_ptr_t var = variable_node_ptr_t(0);
-
-                  if (0 == (var = dynamic_cast<variable_node_ptr_t>(arg_list_[i])))
-                     return false;
-
-                  ts.size = 1;
-                  ts.data = &var->ref();
-                  ts.type = type_store_t::e_scalar;
-               }
-               else if (is_vector_elem_node(arg_list_[i]))
-               {
-                  vector_elem_node_ptr_t var = vector_elem_node_ptr_t(0);
-
-                  if (0 == (var = dynamic_cast<vector_elem_node_ptr_t>(arg_list_[i])))
-                     return false;
-
-                  ts.size = 1;
-                  ts.data = reinterpret_cast<void*>(&var->ref());
-                  ts.type = type_store_t::e_scalar;
-               }
-               else
-               {
-                  ts.size = 1;
-                  ts.data = reinterpret_cast<void*>(&expr_as_vec1_store_[i]);
-                  ts.type = type_store_t::e_scalar;
-               }
-
-               branch_[i] = std::make_pair(arg_list_[i],branch_deletable(arg_list_[i]));
+                return value(arg_list[0]);
             }
-
-            return true;
-         }
-
-         inline bool operator <(const generic_function_node<T,GenericFunction>& fn) const
-         {
-            return this < (&fn);
-         }
-
-         inline T value() const
-         {
-            if (function_)
+            
+            template <typename Sequence>
+            static inline T process_2(const Sequence& arg_list)
             {
-               if (populate_value_list())
-               {
-                  typedef typename GenericFunction::parameter_list_t parameter_list_t;
-
-                  return (*function_)(parameter_list_t(typestore_list_));
-               }
+                return value(arg_list[0]) + value(arg_list[1]);
             }
-
-            return std::numeric_limits<T>::quiet_NaN();
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_genfunction;
-         }
-
-      protected:
-
-         inline virtual bool populate_value_list() const
-         {
-            for (std::size_t i = 0; i < branch_.size(); ++i)
+            
+            template <typename Sequence>
+            static inline T process_3(const Sequence& arg_list)
             {
-               expr_as_vec1_store_[i] = branch_[i].first->value();
+                return value(arg_list[0]) + value(arg_list[1]) +
+                value(arg_list[2]);
             }
-
-            for (std::size_t i = 0; i < branch_.size(); ++i)
+            
+            template <typename Sequence>
+            static inline T process_4(const Sequence& arg_list)
             {
-               range_data_type_t& rdt = range_list_[i];
-
-               if (rdt.range)
-               {
-                  range_t&      rp = (*rdt.range);
-                  std::size_t   r0 = 0;
-                  std::size_t   r1 = 0;
-
-                  if (rp(r0,r1,rdt.size))
-                  {
-                     type_store_t& ts = typestore_list_[i];
-
-                     ts.size = rp.cache_size();
-
-                     if (ts.type == type_store_t::e_string)
-                        ts.data = const_cast<char*>(rdt.str_node->base()) + rp.cache.first;
-                     else
-                        ts.data = static_cast<char*>(rdt.data) + (rp.cache.first * rdt.type_size);
-                  }
-                  else
-                     return false;
-               }
+                return value(arg_list[0]) + value(arg_list[1]) +
+                value(arg_list[2]) + value(arg_list[3]);
             }
-
-            return true;
-         }
-
-         GenericFunction* function_;
-         mutable typestore_list_t typestore_list_;
-
-      private:
-
-         std::vector<expression_ptr> arg_list_;
-         std::vector<branch_t> branch_;
-         mutable tmp_vs_t expr_as_vec1_store_;
-         mutable range_list_t range_list_;
-      };
-
-      template <typename T, typename StringFunction>
-      class string_function_node : public generic_function_node<T,StringFunction>,
-                                   public string_base_node<T>,
-                                   public range_interface <T>
-      {
-      public:
-
-         typedef generic_function_node<T, StringFunction> gen_function_t;
-         typedef range_pack<T> range_t;
-
-         string_function_node(StringFunction* func,
-                              const std::vector<typename gen_function_t::expression_ptr>& arg_list)
-         : gen_function_t(func,arg_list)
-         {
-            range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
-            range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
-            range_.cache.first  = range_.n0_c.second;
-            range_.cache.second = range_.n1_c.second;
-         }
-
-         inline bool operator <(const string_function_node<T,StringFunction>& fn) const
-         {
-            return this < (&fn);
-         }
-
-         inline T value() const
-         {
-            T result = std::numeric_limits<T>::quiet_NaN();
-
-            if (gen_function_t::function_)
+            
+            template <typename Sequence>
+            static inline T process_5(const Sequence& arg_list)
             {
-               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_));
-
-                  range_.n1_c.second  = ret_string_.size() - 1;
-                  range_.cache.second = range_.n1_c.second;
-
-                  return result;
-               }
+                return value(arg_list[0]) + value(arg_list[1]) +
+                value(arg_list[2]) + value(arg_list[3]) +
+                value(arg_list[4]);
             }
-
-            return result;
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_strfunction;
-         }
-
-         std::string str() const
-         {
-            return ret_string_;
-         }
-
-         const char* base() const
-         {
-           return ret_string_.data();
-         }
-
-         std::size_t size() const
-         {
-            return ret_string_.size();
-         }
-
-         range_t& range_ref()
-         {
-            return range_;
-         }
-
-         const range_t& range_ref() const
-         {
-            return range_;
-         }
-
-      protected:
-
-         mutable range_t     range_;
-         mutable std::string ret_string_;
-      };
-
-      template <typename T, typename GenericFunction>
-      class multimode_genfunction_node : public generic_function_node<T,GenericFunction>
-      {
-      public:
-
-         typedef generic_function_node<T, GenericFunction> gen_function_t;
-         typedef range_pack<T> range_t;
-
-         multimode_genfunction_node(GenericFunction* func,
-                                    const std::size_t& param_seq_index,
-                                    const std::vector<typename gen_function_t::expression_ptr>& arg_list)
-         : gen_function_t(func,arg_list),
-           param_seq_index_(param_seq_index)
-         {}
-
-         inline T value() const
-         {
-            T result = std::numeric_limits<T>::quiet_NaN();
-
-            if (gen_function_t::function_)
+        };
+        
+        template <typename T>
+        struct vararg_mul_op : public opr_base<T>
+        {
+            typedef typename opr_base<T>::Type Type;
+            
+            template <typename Type,
+            typename Allocator,
+            template <typename,typename> class Sequence>
+            static inline T process(const Sequence<Type,Allocator>& arg_list)
+            {
+                switch (arg_list.size())
+                {
+                    case 0  : return T(0);
+                    case 1  : return process_1(arg_list);
+                    case 2  : return process_2(arg_list);
+                    case 3  : return process_3(arg_list);
+                    case 4  : return process_4(arg_list);
+                    case 5  : return process_5(arg_list);
+                    default :
+                    {
+                        T result = T(value(arg_list[0]));
+                        
+                        for (std::size_t i = 1; i < arg_list.size(); ++i)
+                        {
+                            result *= value(arg_list[i]);
+                        }
+                        
+                        return result;
+                    }
+                }
+            }
+            
+            template <typename Sequence>
+            static inline T process_1(const Sequence& arg_list)
             {
-               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 value(arg_list[0]);
             }
-
-            return result;
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_genfunction;
-         }
-
-      private:
-
-         std::size_t param_seq_index_;
-      };
-
-      template <typename T, typename StringFunction>
-      class multimode_strfunction_node : public string_function_node<T,StringFunction>
-      {
-      public:
-
-         typedef string_function_node<T, StringFunction> str_function_t;
-         typedef range_pack<T> range_t;
-
-         multimode_strfunction_node(StringFunction* func,
-                                    const std::size_t& param_seq_index,
-                                    const std::vector<typename str_function_t::expression_ptr>& arg_list)
-         : str_function_t(func,arg_list),
-           param_seq_index_(param_seq_index)
-         {}
-
-         inline T value() const
-         {
-            T result = std::numeric_limits<T>::quiet_NaN();
-
-            if (str_function_t::function_)
+            
+            template <typename Sequence>
+            static inline T process_2(const Sequence& arg_list)
             {
-               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_));
-
-                  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;
-
-                  return result;
-               }
+                return value(arg_list[0]) * value(arg_list[1]);
             }
-
-            return result;
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_strfunction;
-         }
-
-      private:
-
-         std::size_t param_seq_index_;
-      };
-
-      #define exprtk_define_unary_op(OpName)                         \
-      template <typename T>                                          \
-      struct OpName##_op                                             \
-      {                                                              \
-         typedef typename functor_t<T>::Type Type;                   \
-                                                                     \
-         static inline T process(Type v)                             \
-         {                                                           \
-            return numeric:: OpName (v);                             \
-         }                                                           \
-                                                                     \
-         static inline typename expression_node<T>::node_type type() \
-         {                                                           \
-            return expression_node<T>::e_##OpName;                   \
-         }                                                           \
-                                                                     \
-         static inline details::operator_type operation()            \
-         {                                                           \
-            return details::e_##OpName;                              \
-         }                                                           \
-      };                                                             \
-
-      exprtk_define_unary_op(abs  )
-      exprtk_define_unary_op(acos )
-      exprtk_define_unary_op(acosh)
-      exprtk_define_unary_op(asin )
-      exprtk_define_unary_op(asinh)
-      exprtk_define_unary_op(atan )
-      exprtk_define_unary_op(atanh)
-      exprtk_define_unary_op(ceil )
-      exprtk_define_unary_op(cos  )
-      exprtk_define_unary_op(cosh )
-      exprtk_define_unary_op(cot  )
-      exprtk_define_unary_op(csc  )
-      exprtk_define_unary_op(d2g  )
-      exprtk_define_unary_op(d2r  )
-      exprtk_define_unary_op(erf  )
-      exprtk_define_unary_op(erfc )
-      exprtk_define_unary_op(exp  )
-      exprtk_define_unary_op(expm1)
-      exprtk_define_unary_op(floor)
-      exprtk_define_unary_op(frac )
-      exprtk_define_unary_op(g2d  )
-      exprtk_define_unary_op(log  )
-      exprtk_define_unary_op(log10)
-      exprtk_define_unary_op(log2 )
-      exprtk_define_unary_op(log1p)
-      exprtk_define_unary_op(ncdf )
-      exprtk_define_unary_op(neg  )
-      exprtk_define_unary_op(notl )
-      exprtk_define_unary_op(pos  )
-      exprtk_define_unary_op(r2d  )
-      exprtk_define_unary_op(round)
-      exprtk_define_unary_op(sec  )
-      exprtk_define_unary_op(sgn  )
-      exprtk_define_unary_op(sin  )
-      exprtk_define_unary_op(sinc )
-      exprtk_define_unary_op(sinh )
-      exprtk_define_unary_op(sqrt )
-      exprtk_define_unary_op(tan  )
-      exprtk_define_unary_op(tanh )
-      exprtk_define_unary_op(trunc)
-      #undef exprtk_define_unary_op
-
-      template <typename T>
-      struct opr_base
-      {
-         typedef typename details::functor_t<T>::Type Type;
-         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;
-         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 typename expression_node<T>::node_type type() { return expression_node<T>::e_add; }
-         static inline details::operator_type operation() { return details::e_add; }
-      };
-
-      template <typename T>
-      struct mul_op : public opr_base<T>
-      {
-         typedef typename opr_base<T>::Type Type;
-         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 typename expression_node<T>::node_type type() { return expression_node<T>::e_mul; }
-         static inline details::operator_type operation() { return details::e_mul; }
-      };
-
-      template <typename T>
-      struct sub_op : public opr_base<T>
-      {
-         typedef typename opr_base<T>::Type Type;
-         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 typename expression_node<T>::node_type type() { return expression_node<T>::e_sub; }
-         static inline details::operator_type operation() { return details::e_sub; }
-      };
-
-      template <typename T>
-      struct div_op : public opr_base<T>
-      {
-         typedef typename opr_base<T>::Type Type;
-         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 typename expression_node<T>::node_type type() { return expression_node<T>::e_div; }
-         static inline details::operator_type operation() { return details::e_div; }
-      };
-
-      template <typename T>
-      struct mod_op : public opr_base<T>
-      {
-         typedef typename opr_base<T>::Type Type;
-         static inline T process(Type t1, Type t2) { return numeric::modulus<T>(t1,t2); }
-         static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_mod; }
-         static inline details::operator_type operation() { return details::e_mod; }
-      };
-
-      template <typename T>
-      struct pow_op : public opr_base<T>
-      {
-         typedef typename opr_base<T>::Type Type;
-         static inline T process(Type t1, Type t2) { return numeric::pow<T>(t1,t2); }
-         static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_pow; }
-         static inline details::operator_type operation() { return details::e_pow; }
-      };
-
-      template <typename T>
-      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; }
-         static inline details::operator_type operation() { return details::e_lt; }
-      };
-
-      template <typename T>
-      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; }
-         static inline details::operator_type operation() { return details::e_lte; }
-      };
-
-      template <typename T>
-      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; }
-         static inline details::operator_type operation() { return details::e_gt; }
-      };
-
-      template <typename T>
-      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; }
-         static inline details::operator_type operation() { return details::e_gte; }
-      };
-
-      template <typename T>
-      struct eq_op : public opr_base<T>
-      {
-         typedef typename opr_base<T>::Type Type;
-         static inline T process(Type t1, Type t2) { return (std::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_eq; }
-         static inline details::operator_type operation() { return details::e_eq; }
-      };
-
-      template <typename T>
-      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; }
-         static inline details::operator_type operation() { return details::e_ne; }
-      };
-
-      template <typename T>
-      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; }
-      };
-
-      template <typename T>
-      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; }
-      };
-
-      template <typename T>
-      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; }
-      };
-
-      template <typename T>
-      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; }
-      };
-
-      template <typename T>
-      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; }
-      };
-
-      template <typename T>
-      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; }
-      };
-
-      template <typename T>
-      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; }
-         static inline details::operator_type operation() { return details::e_in; }
-      };
-
-      template <typename T>
-      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; }
-         static inline details::operator_type operation() { return details::e_like; }
-      };
-
-      template <typename T>
-      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; }
-         static inline details::operator_type operation() { return details::e_ilike; }
-      };
-
-      template <typename T>
-      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)
-         {
-            return ((t0 <= t1) && (t1 <= t2)) ? T(1) : T(0);
-         }
-         static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_inranges; }
-         static inline details::operator_type operation() { return details::e_inrange; }
-      };
-
-      template <typename T>
-      inline T value(details::expression_node<T>* n)
-      {
-         return n->value();
-      }
-
-      template <typename T>
-      inline T value(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>
-         static inline T process(const Sequence<Type,Allocator>& arg_list)
-         {
-            switch (arg_list.size())
-            {
-               case 0  : return T(0);
-               case 1  : return process_1(arg_list);
-               case 2  : return process_2(arg_list);
-               case 3  : return process_3(arg_list);
-               case 4  : return process_4(arg_list);
-               case 5  : return process_5(arg_list);
-               default :
-                         {
-                            T result = T(0);
-
-                            for (std::size_t i = 0; i < arg_list.size(); ++i)
-                            {
-                              result += value(arg_list[i]);
-                            }
-
-                            return result;
-                         }
-            }
-         }
-
-         template <typename Sequence>
-         static inline T process_1(const Sequence& arg_list)
-         {
-            return value(arg_list[0]);
-         }
-
-         template <typename Sequence>
-         static inline T process_2(const Sequence& arg_list)
-         {
-            return value(arg_list[0]) + value(arg_list[1]);
-         }
-
-         template <typename Sequence>
-         static inline T process_3(const Sequence& arg_list)
-         {
-            return value(arg_list[0]) + value(arg_list[1]) +
-                   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]);
-         }
-
-         template <typename Sequence>
-         static inline T process_5(const Sequence& arg_list)
-         {
-            return value(arg_list[0]) + value(arg_list[1]) +
-                   value(arg_list[2]) + value(arg_list[3]) +
-                   value(arg_list[4]);
-         }
-      };
-
-      template <typename T>
-      struct vararg_mul_op : public opr_base<T>
-      {
-         typedef typename opr_base<T>::Type Type;
-
-         template <typename Type,
-                   typename Allocator,
-                   template <typename,typename> class Sequence>
-         static inline T process(const Sequence<Type,Allocator>& arg_list)
-         {
-            switch (arg_list.size())
-            {
-               case 0  : return T(0);
-               case 1  : return process_1(arg_list);
-               case 2  : return process_2(arg_list);
-               case 3  : return process_3(arg_list);
-               case 4  : return process_4(arg_list);
-               case 5  : return process_5(arg_list);
-               default :
-                         {
-                            T result = T(value(arg_list[0]));
-
-                            for (std::size_t i = 1; i < arg_list.size(); ++i)
-                            {
-                               result *= value(arg_list[i]);
-                            }
-
-                            return result;
-                         }
-            }
-         }
-
-         template <typename Sequence>
-         static inline T process_1(const Sequence& arg_list)
-         {
-            return value(arg_list[0]);
-         }
-
-         template <typename Sequence>
-         static inline T process_2(const Sequence& arg_list)
-         {
-            return value(arg_list[0]) * value(arg_list[1]);
-         }
-
-         template <typename Sequence>
-         static inline T process_3(const Sequence& arg_list)
-         {
-            return value(arg_list[0]) * value(arg_list[1]) *
-                   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]);
-         }
-
-         template <typename Sequence>
-         static inline T process_5(const Sequence& arg_list)
-         {
-            return value(arg_list[0]) * value(arg_list[1]) *
-                   value(arg_list[2]) * value(arg_list[3]) *
-                   value(arg_list[4]);
-         }
-      };
-
-      template <typename T>
-      struct vararg_avg_op : public opr_base<T>
-      {
-         typedef typename opr_base<T>::Type Type;
-
-         template <typename Type,
-                   typename Allocator,
-                   template <typename,typename> class Sequence>
-         static inline T process(const Sequence<Type,Allocator>& arg_list)
-         {
-            switch (arg_list.size())
-            {
-               case 0  : return T(0);
-               case 1  : return process_1(arg_list);
-               case 2  : return process_2(arg_list);
-               case 3  : return process_3(arg_list);
-               case 4  : return process_4(arg_list);
-               case 5  : return process_5(arg_list);
-               default : return vararg_add_op<T>::process(arg_list) / arg_list.size();
-            }
-         }
-
-         template <typename Sequence>
-         static inline T process_1(const Sequence& arg_list)
-         {
-            return value(arg_list[0]);
-         }
-
-         template <typename Sequence>
-         static inline T process_2(const Sequence& arg_list)
-         {
-            return (value(arg_list[0]) + value(arg_list[1])) / T(2);
-         }
-
-         template <typename Sequence>
-         static inline T process_3(const Sequence& arg_list)
-         {
-            return (value(arg_list[0]) + value(arg_list[1]) + value(arg_list[2])) / T(3);
-         }
-
-         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])) / T(4);
-         }
-
-         template <typename Sequence>
-         static inline T process_5(const Sequence& arg_list)
-         {
-            return (value(arg_list[0]) + value(arg_list[1]) +
-                    value(arg_list[2]) + value(arg_list[3]) +
-                    value(arg_list[4])) / T(5);
-         }
-      };
-
-      template <typename T>
-      struct vararg_min_op : public opr_base<T>
-      {
-         typedef typename opr_base<T>::Type Type;
-
-         template <typename Type,
-                   typename Allocator,
-                   template <typename,typename> class Sequence>
-         static inline T process(const Sequence<Type,Allocator>& arg_list)
-         {
-            switch (arg_list.size())
-            {
-               case 0  : return T(0);
-               case 1  : return process_1(arg_list);
-               case 2  : return process_2(arg_list);
-               case 3  : return process_3(arg_list);
-               case 4  : return process_4(arg_list);
-               case 5  : return process_5(arg_list);
-               default :
-                         {
-                            T result = T(value(arg_list[0]));
-
-                            for (std::size_t i = 1; i < arg_list.size(); ++i)
-                            {
-                               const T v = value(arg_list[i]);
-
-                               if (v < result)
-                                  result = v;
-                            }
-
-                            return result;
-                         }
+            
+            template <typename Sequence>
+            static inline T process_3(const Sequence& arg_list)
+            {
+                return value(arg_list[0]) * value(arg_list[1]) *
+                value(arg_list[2]);
             }
-         }
-
-         template <typename Sequence>
-         static inline T process_1(const Sequence& arg_list)
-         {
-            return value(arg_list[0]);
-         }
-
-         template <typename Sequence>
-         static inline T process_2(const Sequence& arg_list)
-         {
-            return std::min<T>(value(arg_list[0]),value(arg_list[1]));
-         }
-
-         template <typename Sequence>
-         static inline T process_3(const Sequence& arg_list)
-         {
-            return std::min<T>(std::min<T>(value(arg_list[0]),value(arg_list[1])),value(arg_list[2]));
-         }
-
-         template <typename Sequence>
-         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])));
-         }
-
-         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]))),
-                               value(arg_list[4]));
-         }
-      };
-
-      template <typename T>
-      struct vararg_max_op : public opr_base<T>
-      {
-         typedef typename opr_base<T>::Type Type;
-
-         template <typename Type,
-                   typename Allocator,
-                   template <typename,typename> class Sequence>
-         static inline T process(const Sequence<Type,Allocator>& arg_list)
-         {
-            switch (arg_list.size())
-            {
-               case 0  : return T(0);
-               case 1  : return process_1(arg_list);
-               case 2  : return process_2(arg_list);
-               case 3  : return process_3(arg_list);
-               case 4  : return process_4(arg_list);
-               case 5  : return process_5(arg_list);
-               default :
-                         {
-                            T result = T(value(arg_list[0]));
-
-                            for (std::size_t i = 1; i < arg_list.size(); ++i)
-                            {
-                               const T v = value(arg_list[i]);
-                               if (v > result)
-                                  result = v;
-                            }
-
-                            return result;
-                         }
+            
+            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]);
             }
-         }
-
-         template <typename Sequence>
-         static inline T process_1(const Sequence& arg_list)
-         {
-            return value(arg_list[0]);
-         }
-
-         template <typename Sequence>
-         static inline T process_2(const Sequence& arg_list)
-         {
-            return std::max<T>(value(arg_list[0]),value(arg_list[1]));
-         }
-
-         template <typename Sequence>
-         static inline T process_3(const Sequence& arg_list)
-         {
-            return std::max<T>(std::max<T>(value(arg_list[0]),value(arg_list[1])),value(arg_list[2]));
-         }
-
-         template <typename Sequence>
-         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])));
-         }
-
-         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]))),
-                               value(arg_list[4]));
-         }
-      };
-
-      template <typename T>
-      struct vararg_mand_op : public opr_base<T>
-      {
-         typedef typename opr_base<T>::Type Type;
-
-         template <typename Type,
-                   typename Allocator,
-                   template <typename,typename> class Sequence>
-         static inline T process(const Sequence<Type,Allocator>& arg_list)
-         {
-            switch (arg_list.size())
-            {
-               case 1  : return process_1(arg_list);
-               case 2  : return process_2(arg_list);
-               case 3  : return process_3(arg_list);
-               case 4  : return process_4(arg_list);
-               case 5  : return process_5(arg_list);
-               default :
-                         {
-                            for (std::size_t i = 0; i < arg_list.size(); ++i)
-                            {
-                               if (std::equal_to<T>()(T(0),value(arg_list[i])))
-                                  return T(0);
-                            }
-
-                            return T(1);
-                         }
+            
+            template <typename Sequence>
+            static inline T process_5(const Sequence& arg_list)
+            {
+                return value(arg_list[0]) * value(arg_list[1]) *
+                value(arg_list[2]) * value(arg_list[3]) *
+                value(arg_list[4]);
             }
-         }
-
-         template <typename Sequence>
-         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);
-         }
-
-         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]))
-                   ) ? T(1) : T(0);
-         }
-
-         template <typename Sequence>
-         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]))
-                   ) ? T(1) : T(0);
-         }
-
-         template <typename Sequence>
-         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]))
-                   ) ? T(1) : T(0);
-         }
-
-         template <typename Sequence>
-         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]))
-                   ) ? T(1) : T(0);
-         }
-      };
-
-      template <typename T>
-      struct vararg_mor_op : public opr_base<T>
-      {
-         typedef typename opr_base<T>::Type Type;
-
-         template <typename Type,
-                   typename Allocator,
-                   template <typename,typename> class Sequence>
-         static inline T process(const Sequence<Type,Allocator>& arg_list)
-         {
-            switch (arg_list.size())
-            {
-               case 1  : return process_1(arg_list);
-               case 2  : return process_2(arg_list);
-               case 3  : return process_3(arg_list);
-               case 4  : return process_4(arg_list);
-               case 5  : return process_5(arg_list);
-               default :
-                         {
-                            for (std::size_t i = 0; i < arg_list.size(); ++i)
-                            {
-                               if (std::not_equal_to<T>()(T(0),value(arg_list[i])))
-                                  return T(1);
-                            }
-
-                            return T(0);
-                         }
+        };
+        
+        template <typename T>
+        struct vararg_avg_op : public opr_base<T>
+        {
+            typedef typename opr_base<T>::Type Type;
+            
+            template <typename Type,
+            typename Allocator,
+            template <typename,typename> class Sequence>
+            static inline T process(const Sequence<Type,Allocator>& arg_list)
+            {
+                switch (arg_list.size())
+                {
+                    case 0  : return T(0);
+                    case 1  : return process_1(arg_list);
+                    case 2  : return process_2(arg_list);
+                    case 3  : return process_3(arg_list);
+                    case 4  : return process_4(arg_list);
+                    case 5  : return process_5(arg_list);
+                    default : return vararg_add_op<T>::process(arg_list) / arg_list.size();
+                }
+            }
+            
+            template <typename Sequence>
+            static inline T process_1(const Sequence& arg_list)
+            {
+                return value(arg_list[0]);
+            }
+            
+            template <typename Sequence>
+            static inline T process_2(const Sequence& arg_list)
+            {
+                return (value(arg_list[0]) + value(arg_list[1])) / T(2);
+            }
+            
+            template <typename Sequence>
+            static inline T process_3(const Sequence& arg_list)
+            {
+                return (value(arg_list[0]) + value(arg_list[1]) + value(arg_list[2])) / T(3);
+            }
+            
+            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])) / T(4);
+            }
+            
+            template <typename Sequence>
+            static inline T process_5(const Sequence& arg_list)
+            {
+                return (value(arg_list[0]) + value(arg_list[1]) +
+                        value(arg_list[2]) + value(arg_list[3]) +
+                        value(arg_list[4])) / T(5);
             }
-         }
-
-         template <typename Sequence>
-         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);
-         }
-
-         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]))
-                   ) ? T(1) : T(0);
-         }
-
-         template <typename Sequence>
-         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]))
-                   ) ? T(1) : T(0);
-         }
-
-         template <typename Sequence>
-         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]))
-                   ) ? T(1) : T(0);
-         }
-
-         template <typename Sequence>
-         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]))
-                   ) ? T(1) : T(0);
-         }
-      };
-
-      template <typename T>
-      struct vararg_multi_op : public opr_base<T>
-      {
-         typedef typename opr_base<T>::Type Type;
-
-         template <typename Type,
-                   typename Allocator,
-                   template <typename,typename> class Sequence>
-         static inline T process(const Sequence<Type,Allocator>& arg_list)
-         {
-            switch (arg_list.size())
-            {
-               case 0  : return std::numeric_limits<T>::quiet_NaN();
-               case 1  : return process_1(arg_list);
-               case 2  : return process_2(arg_list);
-               case 3  : return process_3(arg_list);
-               case 4  : return process_4(arg_list);
-               case 5  : return process_5(arg_list);
-               case 6  : return process_6(arg_list);
-               case 7  : return process_7(arg_list);
-               case 8  : return process_8(arg_list);
-               default :
-                         {
-                            for (std::size_t i = 0; i < (arg_list.size() - 1); ++i)
-                            {
-                               value(arg_list[i]);
-                            }
-
-                            return value(arg_list.back());
-                         }
+        };
+        
+        template <typename T>
+        struct vararg_min_op : public opr_base<T>
+        {
+            typedef typename opr_base<T>::Type Type;
+            
+            template <typename Type,
+            typename Allocator,
+            template <typename,typename> class Sequence>
+            static inline T process(const Sequence<Type,Allocator>& arg_list)
+            {
+                switch (arg_list.size())
+                {
+                    case 0  : return T(0);
+                    case 1  : return process_1(arg_list);
+                    case 2  : return process_2(arg_list);
+                    case 3  : return process_3(arg_list);
+                    case 4  : return process_4(arg_list);
+                    case 5  : return process_5(arg_list);
+                    default :
+                    {
+                        T result = T(value(arg_list[0]));
+                        
+                        for (std::size_t i = 1; i < arg_list.size(); ++i)
+                        {
+                            const T v = value(arg_list[i]);
+                            
+                            if (v < result)
+                                result = v;
+                        }
+                        
+                        return result;
+                    }
+                }
             }
-         }
-
-         template <typename Sequence>
-         static inline T process_1(const Sequence& arg_list)
-         {
-            return value(arg_list[0]);
-         }
-
-         template <typename Sequence>
-         static inline T process_2(const Sequence& arg_list)
-         {
-                   value(arg_list[0]);
-            return value(arg_list[1]);
-         }
-
-         template <typename Sequence>
-         static inline T process_3(const Sequence& arg_list)
-         {
-                   value(arg_list[0]);
-                   value(arg_list[1]);
-            return value(arg_list[2]);
-         }
-
-         template <typename Sequence>
-         static inline T process_4(const Sequence& arg_list)
-         {
-                   value(arg_list[0]);
-                   value(arg_list[1]);
-                   value(arg_list[2]);
-            return value(arg_list[3]);
-         }
-
-         template <typename Sequence>
-         static inline T process_5(const Sequence& arg_list)
-         {
-                   value(arg_list[0]);
-                   value(arg_list[1]);
-                   value(arg_list[2]);
-                   value(arg_list[3]);
-            return value(arg_list[4]);
-         }
-
-         template <typename Sequence>
-         static inline T process_6(const Sequence& arg_list)
-         {
-                   value(arg_list[0]);
-                   value(arg_list[1]);
-                   value(arg_list[2]);
-                   value(arg_list[3]);
-                   value(arg_list[4]);
-            return value(arg_list[5]);
-         }
-
-         template <typename Sequence>
-         static inline T process_7(const Sequence& arg_list)
-         {
-                   value(arg_list[0]);
-                   value(arg_list[1]);
-                   value(arg_list[2]);
-                   value(arg_list[3]);
-                   value(arg_list[4]);
-                   value(arg_list[5]);
-            return value(arg_list[6]);
-         }
-
-         template <typename Sequence>
-         static inline T process_8(const Sequence& arg_list)
-         {
-                   value(arg_list[0]);
-                   value(arg_list[1]);
-                   value(arg_list[2]);
-                   value(arg_list[3]);
-                   value(arg_list[4]);
-                   value(arg_list[5]);
-                   value(arg_list[6]);
-            return value(arg_list[7]);
-         }
-      };
-
-      template <typename T>
-      struct vec_add_op
-      {
-         typedef vector_interface<T>* ivector_ptr;
-
-         static inline T process(const ivector_ptr v)
-         {
-            vector_holder<T>& vec = v->vec()->ref();
-
-            T result = T(0);
-
-            for (std::size_t i = 0; i < vec.size(); ++i)
+            
+            template <typename Sequence>
+            static inline T process_1(const Sequence& arg_list)
             {
-              result += (*vec[i]);
+                return value(arg_list[0]);
             }
-
-            return result;
-         }
-      };
-
-      template <typename T>
-      struct vec_mul_op
-      {
-         typedef vector_interface<T>* ivector_ptr;
-
-         static inline T process(const ivector_ptr v)
-         {
-            vector_holder<T>& vec = v->vec()->ref();
-
-            T result = (*vec[0]);
-
-            for (std::size_t i = 1; i < vec.size(); ++i)
+            
+            template <typename Sequence>
+            static inline T process_2(const Sequence& arg_list)
             {
-              result *= (*vec[i]);
+                return std::min<T>(value(arg_list[0]),value(arg_list[1]));
             }
-
-            return result;
-         }
-      };
-
-      template <typename T>
-      struct vec_avg_op
-      {
-         typedef vector_interface<T>* ivector_ptr;
-
-         static inline T process(const ivector_ptr v)
-         {
-            vector_holder<T>& vec = v->vec()->ref();
-
-            T result = T(0);
-
-            for (std::size_t i = 0; i < vec.size(); ++i)
+            
+            template <typename Sequence>
+            static inline T process_3(const Sequence& arg_list)
             {
-              result += (*vec[i]);
+                return std::min<T>(std::min<T>(value(arg_list[0]),value(arg_list[1])),value(arg_list[2]));
             }
-
-            return result / vec.size();
-         }
-      };
-
-      template <typename T>
-      struct vec_min_op
-      {
-         typedef vector_interface<T>* ivector_ptr;
-
-         static inline T process(const ivector_ptr v)
-         {
-            vector_holder<T>& vec = v->vec()->ref();
-
-            T result = (*vec[0]);
-
-            for (std::size_t i = 1; i < vec.size(); ++i)
+            
+            template <typename Sequence>
+            static inline T process_4(const Sequence& arg_list)
             {
-              T v_i = (*vec[i]);
-
-              if (v_i < result)
-                result = v_i;
+                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])));
             }
-
-            return result;
-         }
-      };
-
-      template <typename T>
-      struct vec_max_op
-      {
-         typedef vector_interface<T>* ivector_ptr;
-
-         static inline T process(const ivector_ptr v)
-         {
-            vector_holder<T>& vec = v->vec()->ref();
-
-            T result = (*vec[0]);
-
-            for (std::size_t i = 1; i < vec.size(); ++i)
+            
+            template <typename Sequence>
+            static inline T process_5(const Sequence& arg_list)
             {
-              T v_i = (*vec[i]);
-              if (v_i > result)
-                result = v_i;
+                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]))),
+                                   value(arg_list[4]));
             }
-
-            return result;
-         }
-      };
-
-      template <typename T>
-      class vov_base_node : public expression_node<T>
-      {
-      public:
-
-         inline virtual operator_type operation() const
-         {
-            return details::e_default;
-         }
-
-         virtual const T& v0() const = 0;
-
-         virtual const T& v1() const = 0;
-      };
-
-      template <typename T>
-      class cov_base_node : public expression_node<T>
-      {
-      public:
-
-         inline virtual operator_type operation() const
-         {
-            return details::e_default;
-         }
-
-         virtual const T c() const = 0;
-
-         virtual const T& v() const = 0;
-      };
-
-      template <typename T>
-      class voc_base_node : public expression_node<T>
-      {
-      public:
-
-         inline virtual operator_type operation() const
-         {
-            return details::e_default;
-         }
-
-         virtual const T c() const = 0;
-
-         virtual const T& v() const = 0;
-      };
-
-      template <typename T>
-      class vob_base_node : public expression_node<T>
-      {
-      public:
-
-         virtual const T& v() const = 0;
-      };
-
-      template <typename T>
-      class bov_base_node : public expression_node<T>
-      {
-      public:
-
-         virtual const T& v() const = 0;
-      };
-
-      template <typename T>
-      class cob_base_node : public expression_node<T>
-      {
-      public:
-
-         inline virtual operator_type operation() const
-         {
-            return details::e_default;
-         }
-
-         virtual const T c() const = 0;
-
-         virtual void set_c(const T) = 0;
-
-         virtual expression_node<T>* move_branch(const std::size_t& index) = 0;
-      };
-
-      template <typename T>
-      class boc_base_node : public expression_node<T>
-      {
-      public:
-
-         inline virtual operator_type operation() const
-         {
-            return details::e_default;
-         }
-
-         virtual const T c() const = 0;
-
-         virtual void set_c(const T) = 0;
-
-         virtual expression_node<T>* move_branch(const std::size_t& index) = 0;
-      };
-
-      template <typename T>
-      class uv_base_node : public expression_node<T>
-      {
-      public:
-
-         inline virtual operator_type operation() const
-         {
-            return details::e_default;
-         }
-
-         virtual const T& v() const = 0;
-      };
-
-      template <typename T>
-      class sos_base_node : public expression_node<T>
-      {
-      public:
-
-         inline virtual operator_type operation() const
-         {
-            return details::e_default;
-         }
-      };
-
-      template <typename T>
-      class sosos_base_node : public expression_node<T>
-      {
-      public:
-
-         inline virtual operator_type operation() const
-         {
-            return details::e_default;
-         }
-      };
-
-      template <typename T>
-      class T0oT1oT2_base_node : public expression_node<T>
-      {
-      public:
-
-         virtual std::string type_id() const = 0;
-      };
-
-      template <typename T>
-      class T0oT1oT2oT3_base_node : public expression_node<T>
-      {
-      public:
-
-         virtual std::string type_id() const = 0;
-      };
-
-      template <typename T, typename Operation>
-      class unary_variable_node : public uv_base_node<T>
-      {
-      public:
-
-         typedef expression_node<T>* expression_ptr;
-         typedef Operation operation_t;
-
-         explicit unary_variable_node(const T& var)
-         : v_(var)
-         {}
-
-         inline T value() const
-         {
-            return Operation::process(v_);
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return Operation::type();
-         }
-
-         inline operator_type operation() const
-         {
-            return Operation::operation();
-         }
-
-         inline const T& v() const
-         {
-            return v_;
-         }
-
-      private:
-
-         unary_variable_node(unary_variable_node<T,Operation>&);
-         unary_variable_node<T,Operation>& operator=(unary_variable_node<T,Operation>&);
-
-         const T& v_;
-      };
-
-      template <typename T>
-      class uvouv_node : public expression_node<T>
-      {
-      public:
-
-         // UOpr1(v0) Op UOpr2(v1)
-
-         typedef expression_node<T>* expression_ptr;
-         typedef typename details::functor_t<T> functor_t;
-         typedef typename functor_t::bfunc_t      bfunc_t;
-         typedef typename functor_t::ufunc_t      ufunc_t;
-
-         explicit uvouv_node(const T& var0,const T& var1,
-                             ufunc_t uf0, ufunc_t uf1, bfunc_t bf)
-         : v0_(var0),
-           v1_(var1),
-           u0_(uf0),
-           u1_(uf1),
-           f_ (bf)
-         {}
-
-         inline T value() const
-         {
-            return f_(u0_(v0_),u1_(v1_));
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_uvouv;
-         }
-
-         inline operator_type operation() const
-         {
-            return details::e_default;
-         }
-
-         inline const T& v0()
-         {
-            return v0_;
-         }
-
-         inline const T& v1()
-         {
-            return v1_;
-         }
-
-         inline ufunc_t u0()
-         {
-            return u0_;
-         }
-
-         inline ufunc_t u1()
-         {
-            return u1_;
-         }
-
-         inline ufunc_t f()
-         {
-            return f_;
-         }
-
-      private:
-
-         uvouv_node(uvouv_node<T>&);
-         uvouv_node<T>& operator=(uvouv_node<T>&);
-
-         const T& v0_;
-         const T& v1_;
-         const ufunc_t u0_;
-         const ufunc_t u1_;
-         const bfunc_t f_;
-      };
-
-      template <typename T, typename Operation>
-      class unary_branch_node : public expression_node<T>
-      {
-      public:
-
-         typedef expression_node<T>* expression_ptr;
-         typedef Operation operation_t;
-
-         explicit unary_branch_node(expression_ptr brnch)
-         : branch_(brnch),
-           branch_deletable_(branch_deletable(branch_))
-         {}
-
-        ~unary_branch_node()
-         {
-            if (branch_ && branch_deletable_)
-            {
-               delete branch_;
-               branch_ = 0;
+        };
+        
+        template <typename T>
+        struct vararg_max_op : public opr_base<T>
+        {
+            typedef typename opr_base<T>::Type Type;
+            
+            template <typename Type,
+            typename Allocator,
+            template <typename,typename> class Sequence>
+            static inline T process(const Sequence<Type,Allocator>& arg_list)
+            {
+                switch (arg_list.size())
+                {
+                    case 0  : return T(0);
+                    case 1  : return process_1(arg_list);
+                    case 2  : return process_2(arg_list);
+                    case 3  : return process_3(arg_list);
+                    case 4  : return process_4(arg_list);
+                    case 5  : return process_5(arg_list);
+                    default :
+                    {
+                        T result = T(value(arg_list[0]));
+                        
+                        for (std::size_t i = 1; i < arg_list.size(); ++i)
+                        {
+                            const T v = value(arg_list[i]);
+                            
+                            if (v > result)
+                                result = v;
+                        }
+                        
+                        return result;
+                    }
+                }
             }
-         }
-
-         inline T value() const
-         {
-            return Operation::process(branch_->value());
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return Operation::type();
-         }
-
-         inline operator_type operation() const
-         {
-            return Operation::operation();
-         }
-
-         inline expression_node<T>* branch(const std::size_t&) const
-         {
-            return branch_;
-         }
-
-         inline void release()
-         {
-            branch_deletable_ = false;
-         }
-
-      private:
-
-         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_;
-      };
-
-      template <typename T> struct is_const                { enum {result = 0}; };
-      template <typename T> struct is_const <const T>      { enum {result = 1}; };
-      template <typename T> struct is_const_ref            { enum {result = 0}; };
-      template <typename T> struct is_const_ref <const T&> { enum {result = 1}; };
-      template <typename T> struct is_ref                  { enum {result = 0}; };
-      template <typename T> struct is_ref<T&>              { enum {result = 1}; };
-      template <typename T> struct is_ref<const T&>        { enum {result = 0}; };
-
-      template <std::size_t State>
-      struct param_to_str { static std::string result() { static const std::string r("v"); return r; } };
-
-      template <>
-      struct param_to_str<0> { static std::string result() { static const std::string r("c"); return r; } };
-
-      #define exprtk_crtype(Type)                          \
-      param_to_str<is_const_ref< Type >::result>::result() \
-
-      template <typename T>
-      struct T0oT1oT2process
-      {
-         typedef typename details::functor_t<T> functor_t;
-         typedef typename functor_t::bfunc_t      bfunc_t;
-
-         struct mode0
-         {
-            static inline T process(const T& t0, const T& t1, const T& t2, const bfunc_t bf0, const bfunc_t bf1)
+            
+            template <typename Sequence>
+            static inline T process_1(const Sequence& arg_list)
             {
-               // (T0 o0 T1) o1 T2
-               return bf1(bf0(t0,t1),t2);
+                return value(arg_list[0]);
             }
-
-            template <typename T0, typename T1, typename T2>
-            static inline std::string id()
+            
+            template <typename Sequence>
+            static inline T process_2(const Sequence& arg_list)
             {
-               static const std::string result = "(" + exprtk_crtype(T0) + "o"   +
-                                                       exprtk_crtype(T1) + ")o(" +
-                                                       exprtk_crtype(T2) + ")"   ;
-               return result;
+                return std::max<T>(value(arg_list[0]),value(arg_list[1]));
             }
-         };
-
-         struct mode1
-         {
-            static inline T process(const T& t0, const T& t1, const T& t2, const bfunc_t bf0, const bfunc_t bf1)
+            
+            template <typename Sequence>
+            static inline T process_3(const Sequence& arg_list)
             {
-               // T0 o0 (T1 o1 T2)
-               return bf0(t0,bf1(t1,t2));
+                return std::max<T>(std::max<T>(value(arg_list[0]),value(arg_list[1])),value(arg_list[2]));
             }
-
-            template <typename T0, typename T1, typename T2>
-            static inline std::string id()
+            
+            template <typename Sequence>
+            static inline T process_4(const Sequence& arg_list)
             {
-               static const std::string result = "(" + exprtk_crtype(T0) + ")o(" +
-                                                       exprtk_crtype(T1) + "o"   +
-                                                       exprtk_crtype(T2) + ")"   ;
-               return result;
+                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])));
             }
-         };
-      };
-
-      template <typename T>
-      struct T0oT1oT20T3process
-      {
-         typedef typename details::functor_t<T> functor_t;
-         typedef typename functor_t::bfunc_t      bfunc_t;
-
-         struct mode0
-         {
-            static inline T process(const T& t0, const T& t1,
-                                    const T& t2, const T& t3,
-                                    const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
+            
+            template <typename Sequence>
+            static inline T process_5(const Sequence& arg_list)
             {
-               // (T0 o0 T1) o1 (T2 o2 T3)
-               return bf1(bf0(t0,t1),bf2(t2,t3));
+                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]))),
+                                   value(arg_list[4]));
             }
-
-            template <typename T0, typename T1, typename T2, typename T3>
-            static inline std::string id()
-            {
-               static const std::string result = "(" + exprtk_crtype(T0) + "o"  +
-                                                       exprtk_crtype(T1) + ")o" +
-                                                 "(" + exprtk_crtype(T2) + "o"  +
-                                                       exprtk_crtype(T3) + ")"  ;
-               return result;
+        };
+        
+        template <typename T>
+        struct vararg_mand_op : public opr_base<T>
+        {
+            typedef typename opr_base<T>::Type Type;
+            
+            template <typename Type,
+            typename Allocator,
+            template <typename,typename> class Sequence>
+            static inline T process(const Sequence<Type,Allocator>& arg_list)
+            {
+                switch (arg_list.size())
+                {
+                    case 1  : return process_1(arg_list);
+                    case 2  : return process_2(arg_list);
+                    case 3  : return process_3(arg_list);
+                    case 4  : return process_4(arg_list);
+                    case 5  : return process_5(arg_list);
+                    default :
+                    {
+                        for (std::size_t i = 0; i < arg_list.size(); ++i)
+                        {
+                            if (std::equal_to<T>()(T(0),value(arg_list[i])))
+                                return T(0);
+                        }
+                        
+                        return T(1);
+                    }
+                }
+            }
+            
+            template <typename Sequence>
+            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);
+            }
+            
+            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]))
+                        ) ? T(1) : T(0);
+            }
+            
+            template <typename Sequence>
+            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]))
+                        ) ? T(1) : T(0);
+            }
+            
+            template <typename Sequence>
+            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]))
+                        ) ? T(1) : T(0);
+            }
+            
+            template <typename Sequence>
+            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]))
+                        ) ? T(1) : T(0);
             }
-         };
-
-         struct mode1
-         {
-            static inline T process(const T& t0, const T& t1,
-                                    const T& t2, const T& t3,
-                                    const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
+        };
+        
+        template <typename T>
+        struct vararg_mor_op : public opr_base<T>
+        {
+            typedef typename opr_base<T>::Type Type;
+            
+            template <typename Type,
+            typename Allocator,
+            template <typename,typename> class Sequence>
+            static inline T process(const Sequence<Type,Allocator>& arg_list)
+            {
+                switch (arg_list.size())
+                {
+                    case 1  : return process_1(arg_list);
+                    case 2  : return process_2(arg_list);
+                    case 3  : return process_3(arg_list);
+                    case 4  : return process_4(arg_list);
+                    case 5  : return process_5(arg_list);
+                    default :
+                    {
+                        for (std::size_t i = 0; i < arg_list.size(); ++i)
+                        {
+                            if (std::not_equal_to<T>()(T(0),value(arg_list[i])))
+                                return T(1);
+                        }
+                        
+                        return T(0);
+                    }
+                }
+            }
+            
+            template <typename Sequence>
+            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);
+            }
+            
+            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]))
+                        ) ? T(1) : T(0);
+            }
+            
+            template <typename Sequence>
+            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]))
+                        ) ? T(1) : T(0);
+            }
+            
+            template <typename Sequence>
+            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]))
+                        ) ? T(1) : T(0);
+            }
+            
+            template <typename Sequence>
+            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]))
+                        ) ? T(1) : T(0);
+            }
+        };
+        
+        template <typename T>
+        struct vararg_multi_op : public opr_base<T>
+        {
+            typedef typename opr_base<T>::Type Type;
+            
+            template <typename Type,
+            typename Allocator,
+            template <typename,typename> class Sequence>
+            static inline T process(const Sequence<Type,Allocator>& arg_list)
+            {
+                switch (arg_list.size())
+                {
+                    case 0  : return std::numeric_limits<T>::quiet_NaN();
+                    case 1  : return process_1(arg_list);
+                    case 2  : return process_2(arg_list);
+                    case 3  : return process_3(arg_list);
+                    case 4  : return process_4(arg_list);
+                    case 5  : return process_5(arg_list);
+                    case 6  : return process_6(arg_list);
+                    case 7  : return process_7(arg_list);
+                    case 8  : return process_8(arg_list);
+                    default :
+                    {
+                        for (std::size_t i = 0; i < (arg_list.size() - 1); ++i)
+                        {
+                            value(arg_list[i]);
+                        }
+                        
+                        return value(arg_list.back());
+                    }
+                }
+            }
+            
+            template <typename Sequence>
+            static inline T process_1(const Sequence& arg_list)
+            {
+                return value(arg_list[0]);
+            }
+            
+            template <typename Sequence>
+            static inline T process_2(const Sequence& arg_list)
+            {
+                value(arg_list[0]);
+                return value(arg_list[1]);
+            }
+            
+            template <typename Sequence>
+            static inline T process_3(const Sequence& arg_list)
+            {
+                value(arg_list[0]);
+                value(arg_list[1]);
+                return value(arg_list[2]);
+            }
+            
+            template <typename Sequence>
+            static inline T process_4(const Sequence& arg_list)
+            {
+                value(arg_list[0]);
+                value(arg_list[1]);
+                value(arg_list[2]);
+                return value(arg_list[3]);
+            }
+            
+            template <typename Sequence>
+            static inline T process_5(const Sequence& arg_list)
+            {
+                value(arg_list[0]);
+                value(arg_list[1]);
+                value(arg_list[2]);
+                value(arg_list[3]);
+                return value(arg_list[4]);
+            }
+            
+            template <typename Sequence>
+            static inline T process_6(const Sequence& arg_list)
+            {
+                value(arg_list[0]);
+                value(arg_list[1]);
+                value(arg_list[2]);
+                value(arg_list[3]);
+                value(arg_list[4]);
+                return value(arg_list[5]);
+            }
+            
+            template <typename Sequence>
+            static inline T process_7(const Sequence& arg_list)
+            {
+                value(arg_list[0]);
+                value(arg_list[1]);
+                value(arg_list[2]);
+                value(arg_list[3]);
+                value(arg_list[4]);
+                value(arg_list[5]);
+                return value(arg_list[6]);
+            }
+            
+            template <typename Sequence>
+            static inline T process_8(const Sequence& arg_list)
+            {
+                value(arg_list[0]);
+                value(arg_list[1]);
+                value(arg_list[2]);
+                value(arg_list[3]);
+                value(arg_list[4]);
+                value(arg_list[5]);
+                value(arg_list[6]);
+                return value(arg_list[7]);
+            }
+        };
+        
+        template <typename T>
+        struct vec_add_op
+        {
+            typedef vector_interface<T>* ivector_ptr;
+            
+            static inline T process(const ivector_ptr v)
+            {
+                const T* vec = v->vec()->vds().data();
+                const std::size_t vec_size = v->vec()->vds().size();
+                
+                loop_unroll::details lud(vec_size);
+                
+                if (vec_size <= static_cast<std::size_t>(lud.batch_size))
+                {
+                    T result = T(0);
+                    int i    = 0;
+                    
+                    switch (vec_size)
+                    {
+#define case_stmt(N)         \
+case N : result += vec[i++]; \
+
+#ifndef exprtk_disable_superscalar_unroll
+                            case_stmt(16) case_stmt(15)
+                            case_stmt(14) case_stmt(13)
+                            case_stmt(12) case_stmt(11)
+                            case_stmt(10) case_stmt( 9)
+                            case_stmt( 8) case_stmt( 7)
+                            case_stmt( 6) case_stmt( 5)
+#endif
+                            case_stmt( 4) case_stmt( 3)
+                            case_stmt( 2) case_stmt( 1)
+                    }
+                    
+#undef case_stmt
+                    
+                    return result;
+                }
+                
+                T r[] = {
+                    T(0), T(0), T(0), T(0), T(0), T(0), T(0), T(0),
+                    T(0), T(0), T(0), T(0), T(0), T(0), T(0), T(0)
+                };
+                
+                const T* upper_bound = vec + lud.upper_bound;
+                
+                while (vec < upper_bound)
+                {
+#define exprtk_loop(N) \
+r[N] += vec[N];        \
+
+                    exprtk_loop( 0) exprtk_loop( 1)
+                    exprtk_loop( 2) exprtk_loop( 3)
+#ifndef exprtk_disable_superscalar_unroll
+                    exprtk_loop( 4) exprtk_loop( 5)
+                    exprtk_loop( 6) exprtk_loop( 7)
+                    exprtk_loop( 8) exprtk_loop( 9)
+                    exprtk_loop(10) exprtk_loop(11)
+                    exprtk_loop(12) exprtk_loop(13)
+                    exprtk_loop(14) exprtk_loop(15)
+#endif
+                    
+                    vec += lud.batch_size;
+                }
+                
+                int i = 0;
+                
+                switch (lud.remainder)
+                {
+#define case_stmt(N)       \
+case N : r[0] += vec[i++]; \
+
+#ifndef exprtk_disable_superscalar_unroll
+                        case_stmt(15) case_stmt(14)
+                        case_stmt(13) case_stmt(12)
+                        case_stmt(11) case_stmt(10)
+                        case_stmt( 9) case_stmt( 8)
+                        case_stmt( 7) case_stmt( 6)
+                        case_stmt( 5) case_stmt( 4)
+#endif
+                        case_stmt( 3) case_stmt( 2)
+                        case_stmt( 1)
+                }
+                
+#undef exprtk_loop
+#undef case_stmt
+                
+                return (r[ 0] + r[ 1] + r[ 2] + r[ 3])
+#ifndef exprtk_disable_superscalar_unroll
+                + (r[ 4] + r[ 5] + r[ 6] + r[ 7])
+                + (r[ 8] + r[ 9] + r[10] + r[11])
+                + (r[12] + r[13] + r[14] + r[15])
+#endif
+                ;
+            }
+        };
+        
+        template <typename T>
+        struct vec_mul_op
+        {
+            typedef vector_interface<T>* ivector_ptr;
+            
+            static inline T process(const ivector_ptr v)
+            {
+                const T* vec = v->vec()->vds().data();
+                const std::size_t vec_size = v->vec()->vds().size();
+                
+                loop_unroll::details lud(vec_size);
+                
+                if (vec_size <= static_cast<std::size_t>(lud.batch_size))
+                {
+                    T result = T(1);
+                    int i    = 0;
+                    
+                    switch (vec_size)
+                    {
+#define case_stmt(N)         \
+case N : result *= vec[i++]; \
+
+#ifndef exprtk_disable_superscalar_unroll
+                            case_stmt(16) case_stmt(15)
+                            case_stmt(14) case_stmt(13)
+                            case_stmt(12) case_stmt(11)
+                            case_stmt(10) case_stmt( 9)
+                            case_stmt( 8) case_stmt( 7)
+                            case_stmt( 6) case_stmt( 5)
+#endif
+                            case_stmt( 4) case_stmt( 3)
+                            case_stmt( 2) case_stmt( 1)
+                    }
+                    
+#undef case_stmt
+                    
+                    return result;
+                }
+                
+                T r[] = {
+                    T(1), T(1), T(1), T(1), T(1), T(1), T(1), T(1),
+                    T(1), T(1), T(1), T(1), T(1), T(1), T(1), T(1)
+                };
+                
+                const T* upper_bound = vec + lud.upper_bound;
+                
+                while (vec < upper_bound)
+                {
+#define exprtk_loop(N) \
+r[N] *= vec[N];        \
+
+                    exprtk_loop( 0) exprtk_loop( 1)
+                    exprtk_loop( 2) exprtk_loop( 3)
+#ifndef exprtk_disable_superscalar_unroll
+                    exprtk_loop( 4) exprtk_loop( 5)
+                    exprtk_loop( 6) exprtk_loop( 7)
+                    exprtk_loop( 8) exprtk_loop( 9)
+                    exprtk_loop(10) exprtk_loop(11)
+                    exprtk_loop(12) exprtk_loop(13)
+                    exprtk_loop(14) exprtk_loop(15)
+#endif
+                    
+                    vec += lud.batch_size;
+                }
+                
+                int i = 0;
+                
+                switch (lud.remainder)
+                {
+#define case_stmt(N)       \
+case N : r[0] *= vec[i++]; \
+
+#ifndef exprtk_disable_superscalar_unroll
+                        case_stmt(15) case_stmt(14)
+                        case_stmt(13) case_stmt(12)
+                        case_stmt(11) case_stmt(10)
+                        case_stmt( 9) case_stmt( 8)
+                        case_stmt( 7) case_stmt( 6)
+                        case_stmt( 5) case_stmt( 4)
+#endif
+                        case_stmt( 3) case_stmt( 2)
+                        case_stmt( 1)
+                }
+                
+#undef exprtk_loop
+#undef case_stmt
+                
+                return (r[ 0] * r[ 1] * r[ 2] * r[ 3])
+#ifndef exprtk_disable_superscalar_unroll
+                + (r[ 4] * r[ 5] * r[ 6] * r[ 7])
+                + (r[ 8] * r[ 9] * r[10] * r[11])
+                + (r[12] * r[13] * r[14] * r[15])
+#endif
+                ;
+            }
+        };
+        
+        template <typename T>
+        struct vec_avg_op
+        {
+            typedef vector_interface<T>* ivector_ptr;
+            
+            static inline T process(const ivector_ptr v)
+            {
+                const std::size_t vec_size = v->vec()->vds().size();
+                
+                return vec_add_op<T>::process(v) / vec_size;
+            }
+        };
+        
+        template <typename T>
+        struct vec_min_op
+        {
+            typedef vector_interface<T>* ivector_ptr;
+            
+            static inline T process(const ivector_ptr v)
+            {
+                const T* vec = v->vec()->vds().data();
+                const std::size_t vec_size = v->vec()->vds().size();
+                
+                T result = vec[0];
+                
+                for (std::size_t i = 1; i < vec_size; ++i)
+                {
+                    T v_i = vec[i];
+                    
+                    if (v_i < result)
+                        result = v_i;
+                }
+                
+                return result;
+            }
+        };
+        
+        template <typename T>
+        struct vec_max_op
+        {
+            typedef vector_interface<T>* ivector_ptr;
+            
+            static inline T process(const ivector_ptr v)
+            {
+                const T* vec = v->vec()->vds().data();
+                const std::size_t vec_size = v->vec()->vds().size();
+                
+                T result = vec[0];
+                
+                for (std::size_t i = 1; i < vec_size; ++i)
+                {
+                    T v_i = vec[i];
+                    
+                    if (v_i > result)
+                        result = v_i;
+                }
+                
+                return result;
+            }
+        };
+        
+        template <typename T>
+        class vov_base_node : public expression_node<T>
+        {
+        public:
+            
+            virtual ~vov_base_node()
+            {}
+            
+            inline virtual operator_type operation() const
+            {
+                return details::e_default;
+            }
+            
+            virtual const T& v0() const = 0;
+            
+            virtual const T& v1() const = 0;
+        };
+        
+        template <typename T>
+        class cov_base_node : public expression_node<T>
+        {
+        public:
+            
+            virtual ~cov_base_node()
+            {}
+            
+            inline virtual operator_type operation() const
+            {
+                return details::e_default;
+            }
+            
+            virtual const T c() const = 0;
+            
+            virtual const T& v() const = 0;
+        };
+        
+        template <typename T>
+        class voc_base_node : public expression_node<T>
+        {
+        public:
+            
+            virtual ~voc_base_node()
+            {}
+            
+            inline virtual operator_type operation() const
+            {
+                return details::e_default;
+            }
+            
+            virtual const T c() const = 0;
+            
+            virtual const T& v() const = 0;
+        };
+        
+        template <typename T>
+        class vob_base_node : public expression_node<T>
+        {
+        public:
+            
+            virtual ~vob_base_node()
+            {}
+            
+            virtual const T& v() const = 0;
+        };
+        
+        template <typename T>
+        class bov_base_node : public expression_node<T>
+        {
+        public:
+            
+            virtual ~bov_base_node()
+            {}
+            
+            virtual const T& v() const = 0;
+        };
+        
+        template <typename T>
+        class cob_base_node : public expression_node<T>
+        {
+        public:
+            
+            virtual ~cob_base_node()
+            {}
+            
+            inline virtual operator_type operation() const
+            {
+                return details::e_default;
+            }
+            
+            virtual const T c() const = 0;
+            
+            virtual void set_c(const T) = 0;
+            
+            virtual expression_node<T>* move_branch(const std::size_t& index) = 0;
+        };
+        
+        template <typename T>
+        class boc_base_node : public expression_node<T>
+        {
+        public:
+            
+            virtual ~boc_base_node()
+            {}
+            
+            inline virtual operator_type operation() const
+            {
+                return details::e_default;
+            }
+            
+            virtual const T c() const = 0;
+            
+            virtual void set_c(const T) = 0;
+            
+            virtual expression_node<T>* move_branch(const std::size_t& index) = 0;
+        };
+        
+        template <typename T>
+        class uv_base_node : public expression_node<T>
+        {
+        public:
+            
+            virtual ~uv_base_node()
+            {}
+            
+            inline virtual operator_type operation() const
+            {
+                return details::e_default;
+            }
+            
+            virtual const T& v() const = 0;
+        };
+        
+        template <typename T>
+        class sos_base_node : public expression_node<T>
+        {
+        public:
+            
+            virtual ~sos_base_node()
+            {}
+            
+            inline virtual operator_type operation() const
+            {
+                return details::e_default;
+            }
+        };
+        
+        template <typename T>
+        class sosos_base_node : public expression_node<T>
+        {
+        public:
+            
+            virtual ~sosos_base_node()
+            {}
+            
+            inline virtual operator_type operation() const
+            {
+                return details::e_default;
+            }
+        };
+        
+        template <typename T>
+        class T0oT1oT2_base_node : public expression_node<T>
+        {
+        public:
+            
+            virtual ~T0oT1oT2_base_node()
+            {}
+            
+            virtual std::string type_id() const = 0;
+        };
+        
+        template <typename T>
+        class T0oT1oT2oT3_base_node : public expression_node<T>
+        {
+        public:
+            
+            virtual ~T0oT1oT2oT3_base_node()
+            {}
+            
+            virtual std::string type_id() const = 0;
+        };
+        
+        template <typename T, typename Operation>
+        class unary_variable_node : public uv_base_node<T>
+        {
+        public:
+            
+            typedef expression_node<T>* expression_ptr;
+            typedef Operation operation_t;
+            
+            explicit unary_variable_node(const T& var)
+            : v_(var)
+            {}
+            
+            inline T value() const
+            {
+                return Operation::process(v_);
+            }
+            
+            inline typename expression_node<T>::node_type type() const
+            {
+                return Operation::type();
+            }
+            
+            inline operator_type operation() const
+            {
+                return Operation::operation();
+            }
+            
+            inline const T& v() const
+            {
+                return v_;
+            }
+            
+        private:
+            
+            unary_variable_node(unary_variable_node<T,Operation>&);
+            unary_variable_node<T,Operation>& operator=(unary_variable_node<T,Operation>&);
+            
+            const T& v_;
+        };
+        
+        template <typename T>
+        class uvouv_node : public expression_node<T>
+        {
+        public:
+            
+            // UOpr1(v0) Op UOpr2(v1)
+            
+            typedef expression_node<T>* expression_ptr;
+            typedef typename details::functor_t<T> functor_t;
+            typedef typename functor_t::bfunc_t      bfunc_t;
+            typedef typename functor_t::ufunc_t      ufunc_t;
+            
+            explicit uvouv_node(const T& var0,const T& var1,
+                                ufunc_t uf0, ufunc_t uf1, bfunc_t bf)
+            : v0_(var0),
+            v1_(var1),
+            u0_(uf0),
+            u1_(uf1),
+            f_ (bf)
+            {}
+            
+            inline T value() const
+            {
+                return f_(u0_(v0_),u1_(v1_));
+            }
+            
+            inline typename expression_node<T>::node_type type() const
+            {
+                return expression_node<T>::e_uvouv;
+            }
+            
+            inline operator_type operation() const
+            {
+                return details::e_default;
+            }
+            
+            inline const T& v0()
+            {
+                return v0_;
+            }
+            
+            inline const T& v1()
+            {
+                return v1_;
+            }
+            
+            inline ufunc_t u0()
+            {
+                return u0_;
+            }
+            
+            inline ufunc_t u1()
+            {
+                return u1_;
+            }
+            
+            inline ufunc_t f()
+            {
+                return f_;
+            }
+            
+        private:
+            
+            uvouv_node(uvouv_node<T>&);
+            uvouv_node<T>& operator=(uvouv_node<T>&);
+            
+            const T& v0_;
+            const T& v1_;
+            const ufunc_t u0_;
+            const ufunc_t u1_;
+            const bfunc_t f_;
+        };
+        
+        template <typename T, typename Operation>
+        class unary_branch_node : public expression_node<T>
+        {
+        public:
+            
+            typedef expression_node<T>* expression_ptr;
+            typedef Operation operation_t;
+            
+            explicit unary_branch_node(expression_ptr brnch)
+            : branch_(brnch),
+            branch_deletable_(branch_deletable(branch_))
+            {}
+            
+            ~unary_branch_node()
+            {
+                if (branch_ && branch_deletable_)
+                {
+                    delete branch_;
+                    branch_ = 0;
+                }
+            }
+            
+            inline T value() const
+            {
+                return Operation::process(branch_->value());
+            }
+            
+            inline typename expression_node<T>::node_type type() const
+            {
+                return Operation::type();
+            }
+            
+            inline operator_type operation() const
+            {
+                return Operation::operation();
+            }
+            
+            inline expression_node<T>* branch(const std::size_t&) const
+            {
+                return branch_;
+            }
+            
+            inline void release()
+            {
+                branch_deletable_ = false;
+            }
+            
+        private:
+            
+            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_;
+        };
+        
+        template <typename T> struct is_const                { enum {result = 0}; };
+        template <typename T> struct is_const <const T>      { enum {result = 1}; };
+        template <typename T> struct is_const_ref            { enum {result = 0}; };
+        template <typename T> struct is_const_ref <const T&> { enum {result = 1}; };
+        template <typename T> struct is_ref                  { enum {result = 0}; };
+        template <typename T> struct is_ref<T&>              { enum {result = 1}; };
+        template <typename T> struct is_ref<const T&>        { enum {result = 0}; };
+        
+        template <std::size_t State>
+        struct param_to_str { static std::string result() { static const std::string r("v"); return r; } };
+        
+        template <>
+        struct param_to_str<0> { static std::string result() { static const std::string r("c"); return r; } };
+        
+#define exprtk_crtype(Type)                          \
+param_to_str<is_const_ref< Type >::result>::result() \
+
+        template <typename T>
+        struct T0oT1oT2process
+        {
+            typedef typename details::functor_t<T> functor_t;
+            typedef typename functor_t::bfunc_t      bfunc_t;
+            
+            struct mode0
+            {
+                static inline T process(const T& t0, const T& t1, const T& t2, const bfunc_t bf0, const bfunc_t bf1)
+                {
+                    // (T0 o0 T1) o1 T2
+                    return bf1(bf0(t0,t1),t2);
+                }
+                
+                template <typename T0, typename T1, typename T2>
+                static inline std::string id()
+                {
+                    static const std::string result = "(" + exprtk_crtype(T0) + "o"   +
+                    exprtk_crtype(T1) + ")o(" +
+                    exprtk_crtype(T2) + ")"   ;
+                    return result;
+                }
+            };
+            
+            struct mode1
+            {
+                static inline T process(const T& t0, const T& t1, const T& t2, const bfunc_t bf0, const bfunc_t bf1)
+                {
+                    // T0 o0 (T1 o1 T2)
+                    return bf0(t0,bf1(t1,t2));
+                }
+                
+                template <typename T0, typename T1, typename T2>
+                static inline std::string id()
+                {
+                    static const std::string result = "(" + exprtk_crtype(T0) + ")o(" +
+                    exprtk_crtype(T1) + "o"   +
+                    exprtk_crtype(T2) + ")"   ;
+                    return result;
+                }
+            };
+        };
+        
+        template <typename T>
+        struct T0oT1oT20T3process
+        {
+            typedef typename details::functor_t<T> functor_t;
+            typedef typename functor_t::bfunc_t      bfunc_t;
+            
+            struct mode0
+            {
+                static inline T process(const T& t0, const T& t1,
+                                        const T& t2, const T& t3,
+                                        const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
+                {
+                    // (T0 o0 T1) o1 (T2 o2 T3)
+                    return bf1(bf0(t0,t1),bf2(t2,t3));
+                }
+                
+                template <typename T0, typename T1, typename T2, typename T3>
+                static inline std::string id()
+                {
+                    static const std::string result = "(" + exprtk_crtype(T0) + "o"  +
+                    exprtk_crtype(T1) + ")o" +
+                    "(" + exprtk_crtype(T2) + "o"  +
+                    exprtk_crtype(T3) + ")"  ;
+                    return result;
+                }
+            };
+            
+            struct mode1
+            {
+                static inline T process(const T& t0, const T& t1,
+                                        const T& t2, const T& t3,
+                                        const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
+                {
+                    // (T0 o0 (T1 o1 (T2 o2 T3))
+                    return bf0(t0,bf1(t1,bf2(t2,t3)));
+                }
+                template <typename T0, typename T1, typename T2, typename T3>
+                static inline std::string id()
+                {
+                    static const std::string result = "(" + exprtk_crtype(T0) +  ")o((" +
+                    exprtk_crtype(T1) +  ")o("  +
+                    exprtk_crtype(T2) +  "o"    +
+                    exprtk_crtype(T3) +  "))"   ;
+                    return result;
+                }
+            };
+            
+            struct mode2
+            {
+                static inline T process(const T& t0, const T& t1,
+                                        const T& t2, const T& t3,
+                                        const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
+                {
+                    // (T0 o0 ((T1 o1 T2) o2 T3)
+                    return bf0(t0,bf2(bf1(t1,t2),t3));
+                }
+                
+                template <typename T0, typename T1, typename T2, typename T3>
+                static inline std::string id()
+                {
+                    static const std::string result = "(" + exprtk_crtype(T0) + ")o((" +
+                    exprtk_crtype(T1) + "o"    +
+                    exprtk_crtype(T2) + ")o("  +
+                    exprtk_crtype(T3) + "))"   ;
+                    return result;
+                }
+            };
+            
+            struct mode3
+            {
+                static inline T process(const T& t0, const T& t1,
+                                        const T& t2, const T& t3,
+                                        const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
+                {
+                    // (((T0 o0 T1) o1 T2) o2 T3)
+                    return bf2(bf1(bf0(t0,t1),t2),t3);
+                }
+                
+                template <typename T0, typename T1, typename T2, typename T3>
+                static inline std::string id()
+                {
+                    static const std::string result = "((" + exprtk_crtype(T0) + "o"    +
+                    exprtk_crtype(T1) + ")o("  +
+                    exprtk_crtype(T2) + "))o(" +
+                    exprtk_crtype(T3) + ")";
+                    return result;
+                }
+            };
+            
+            struct mode4
+            {
+                static inline T process(const T& t0, const T& t1,
+                                        const T& t2, const T& t3,
+                                        const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
+                {
+                    // ((T0 o0 (T1 o1 T2)) o2 T3
+                    return bf2(bf0(t0,bf1(t1,t2)),t3);
+                }
+                
+                template <typename T0, typename T1, typename T2, typename T3>
+                static inline std::string id()
+                {
+                    static const std::string result = "((" + exprtk_crtype(T0) + ")o("  +
+                    exprtk_crtype(T1) + "o"    +
+                    exprtk_crtype(T2) + "))o(" +
+                    exprtk_crtype(T3) + ")"    ;
+                    return result;
+                }
+            };
+        };
+        
+#undef exprtk_crtype
+        
+        template <typename T, typename T0, typename T1>
+        struct nodetype_T0oT1 { static const typename expression_node<T>::node_type result; };
+        template <typename T, typename T0, typename T1>
+        const typename expression_node<T>::node_type nodetype_T0oT1<T,T0,T1>::result = expression_node<T>::e_none;
+        
+#define synthesis_node_type_define(T0_,T1_,v_)                                                            \
+template <typename T, typename T0, typename T1>                                                           \
+struct nodetype_T0oT1<T,T0_,T1_> { static const typename expression_node<T>::node_type result; };         \
+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)
+#undef synthesis_node_type_define
+        
+        template <typename T, typename T0, typename T1, typename T2>
+        struct nodetype_T0oT1oT2 { static const typename expression_node<T>::node_type result; };
+        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>::e_none;
+        
+#define synthesis_node_type_define(T0_,T1_,T2_,v_)                                                               \
+template <typename T, typename T0, typename T1, typename T2>                                                     \
+struct nodetype_T0oT1oT2<T,T0_,T1_,T2_> { static const typename expression_node<T>::node_type result; };         \
+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 )
+#undef synthesis_node_type_define
+        
+        template <typename T, typename T0, typename T1, typename T2, typename T3>
+        struct nodetype_T0oT1oT2oT3 { static const typename expression_node<T>::node_type result; };
+        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>::e_none;
+        
+#define synthesis_node_type_define(T0_,T1_,T2_,T3_,v_)                                                                  \
+template <typename T, typename T0, typename T1, typename T2, typename T3>                                               \
+struct nodetype_T0oT1oT2oT3<T,T0_,T1_,T2_,T3_> { static const typename expression_node<T>::node_type result; };         \
+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   )
+#undef synthesis_node_type_define
+        
+        template <typename T, typename T0, typename T1>
+        class T0oT1 : public expression_node<T>
+        {
+        public:
+            
+            typedef typename details::functor_t<T> functor_t;
+            typedef typename functor_t::bfunc_t      bfunc_t;
+            typedef T value_type;
+            typedef T0oT1<T,T0,T1> node_type;
+            
+            T0oT1(T0 p0, T1 p1, const bfunc_t p2)
+            : t0_(p0),
+            t1_(p1),
+            f_ (p2)
+            {}
+            
+            inline typename expression_node<T>::node_type type() const
+            {
+                static const typename expression_node<T>::node_type result = nodetype_T0oT1<T,T0,T1>::result;
+                return result;
+            }
+            
+            inline operator_type operation() const
+            {
+                return e_default;
+            }
+            
+            inline T value() const
+            {
+                return f_(t0_,t1_);
+            }
+            
+            inline T0 t0() const
+            {
+                return t0_;
+            }
+            
+            inline T1 t1() const
             {
-               // (T0 o0 (T1 o1 (T2 o2 T3))
-               return bf0(t0,bf1(t1,bf2(t2,t3)));
+                return t1_;
             }
-            template <typename T0, typename T1, typename T2, typename T3>
+            
+            inline bfunc_t f() const
+            {
+                return f_;
+            }
+            
+            template <typename Allocator>
+            static inline expression_node<T>* allocate(Allocator& allocator,
+                                                       T0 p0, T1 p1,
+                                                       bfunc_t p2)
+            {
+                return allocator.template allocate_type<node_type,T0,T1,bfunc_t&>(p0,p1,p2);
+            }
+            
+        private:
+            
+            T0oT1(T0oT1<T,T0,T1>&) {}
+            T0oT1<T,T0,T1>& operator=(T0oT1<T,T0,T1>&) { return *this; }
+            
+            T0 t0_;
+            T1 t1_;
+            const bfunc_t f_;
+        };
+        
+        template <typename T, typename T0, typename T1, typename T2, typename ProcessMode>
+        class T0oT1oT2 : public T0oT1oT2_base_node<T>
+        {
+        public:
+            
+            typedef typename details::functor_t<T> functor_t;
+            typedef typename functor_t::bfunc_t      bfunc_t;
+            typedef T value_type;
+            typedef T0oT1oT2<T,T0,T1,T2,ProcessMode> node_type;
+            typedef ProcessMode process_mode_t;
+            
+            T0oT1oT2(T0 p0, T1 p1, T2 p2, const bfunc_t p3, const bfunc_t p4)
+            : t0_(p0),
+            t1_(p1),
+            t2_(p2),
+            f0_(p3),
+            f1_(p4)
+            {}
+            
+            inline typename expression_node<T>::node_type type() const
+            {
+                static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result;
+                return result;
+            }
+            
+            inline operator_type operation() const
+            {
+                return e_default;
+            }
+            
+            inline T value() const
+            {
+                return ProcessMode::process(t0_,t1_,t2_,f0_,f1_);
+            }
+            
+            inline T0 t0() const
+            {
+                return t0_;
+            }
+            
+            inline T1 t1() const
+            {
+                return t1_;
+            }
+            
+            inline T2 t2() const
+            {
+                return t2_;
+            }
+            
+            bfunc_t f0() const
+            {
+                return f0_;
+            }
+            
+            bfunc_t f1() const
+            {
+                return f1_;
+            }
+            
+            std::string type_id() const
+            {
+                return id();
+            }
+            
             static inline std::string id()
             {
-               static const std::string result = "(" + exprtk_crtype(T0) +  ")o((" +
-                                                       exprtk_crtype(T1) +  ")o("  +
-                                                       exprtk_crtype(T2) +  "o"    +
-                                                       exprtk_crtype(T3) +  "))"   ;
-               return result;
+                return process_mode_t::template id<T0,T1,T2>();
             }
-         };
-
-         struct mode2
-         {
-            static inline T process(const T& t0, const T& t1,
-                                    const T& t2, const T& t3,
-                                    const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
+            
+            template <typename Allocator>
+            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>(p0,p1,p2,p3,p4);
+            }
+            
+        private:
+            
+            T0oT1oT2(node_type&) {}
+            node_type& operator=(node_type&) { return *this; }
+            
+            T0 t0_;
+            T1 t1_;
+            T2 t2_;
+            const bfunc_t f0_;
+            const bfunc_t f1_;
+        };
+        
+        template <typename T, typename T0_, typename T1_, typename T2_, typename T3_, typename ProcessMode>
+        class T0oT1oT2oT3 : public T0oT1oT2oT3_base_node<T>
+        {
+        public:
+            
+            typedef typename details::functor_t<T> functor_t;
+            typedef typename functor_t::bfunc_t      bfunc_t;
+            typedef T value_type;
+            typedef T0_ T0;
+            typedef T1_ T1;
+            typedef T2_ T2;
+            typedef T3_ T3;
+            typedef T0oT1oT2oT3<T,T0,T1,T2,T3,ProcessMode> node_type;
+            typedef ProcessMode process_mode_t;
+            
+            T0oT1oT2oT3(T0 p0, T1 p1, T2 p2, T3 p3, bfunc_t p4, bfunc_t p5, bfunc_t p6)
+            : t0_(p0),
+            t1_(p1),
+            t2_(p2),
+            t3_(p3),
+            f0_(p4),
+            f1_(p5),
+            f2_(p6)
+            {}
+            
+            inline T value() const
             {
-               // (T0 o0 ((T1 o1 T2) o2 T3)
-               return bf0(t0,bf2(bf1(t1,t2),t3));
+                return ProcessMode::process(t0_,t1_,t2_,t3_,f0_,f1_,f2_);
             }
-
-            template <typename T0, typename T1, typename T2, typename T3>
+            
+            inline T0 t0() const
+            {
+                return t0_;
+            }
+            
+            inline T1 t1() const
+            {
+                return t1_;
+            }
+            
+            inline T2 t2() const
+            {
+                return t2_;
+            }
+            
+            inline T3 t3() const
+            {
+                return t3_;
+            }
+            
+            inline bfunc_t f0() const
+            {
+                return f0_;
+            }
+            
+            inline bfunc_t f1() const
+            {
+                return f1_;
+            }
+            
+            inline bfunc_t f2() const
+            {
+                return f2_;
+            }
+            
+            inline std::string type_id() const
+            {
+                return id();
+            }
+            
             static inline std::string id()
             {
-               static const std::string result = "(" + exprtk_crtype(T0) + ")o((" +
-                                                       exprtk_crtype(T1) + "o"    +
-                                                       exprtk_crtype(T2) + ")o("  +
-                                                       exprtk_crtype(T3) + "))"   ;
-               return result;
+                return process_mode_t::template id<T0,T1,T2,T3>();
             }
-         };
-
-         struct mode3
-         {
-            static inline T process(const T& t0, const T& t1,
-                                    const T& t2, const T& t3,
-                                    const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
+            
+            template <typename Allocator>
+            static inline expression_node<T>* allocate(Allocator& allocator,
+                                                       T0 p0, T1 p1, T2 p2, T3 p3,
+                                                       bfunc_t p4, bfunc_t p5, bfunc_t p6)
+            {
+                return allocator.template allocate_type<node_type,T0,T1,T2,T3,bfunc_t,bfunc_t>(p0,p1,p2,p3,p4,p5,p6);
+            }
+            
+        private:
+            
+            T0oT1oT2oT3(node_type&) {}
+            node_type& operator=(node_type&) { return *this; }
+            
+            T0 t0_;
+            T1 t1_;
+            T2 t2_;
+            T3 t3_;
+            const bfunc_t f0_;
+            const bfunc_t f1_;
+            const bfunc_t f2_;
+        };
+        
+        template <typename T, typename T0, typename T1, typename T2>
+        class T0oT1oT2_sf3 : public T0oT1oT2_base_node<T>
+        {
+        public:
+            
+            typedef typename details::functor_t<T> functor_t;
+            typedef typename functor_t::tfunc_t      tfunc_t;
+            typedef T value_type;
+            typedef T0oT1oT2_sf3<T,T0,T1,T2> node_type;
+            
+            T0oT1oT2_sf3(T0 p0, T1 p1, T2 p2, const tfunc_t p3)
+            : t0_(p0),
+            t1_(p1),
+            t2_(p2),
+            f_ (p3)
+            {}
+            
+            inline typename expression_node<T>::node_type type() const
             {
-               // (((T0 o0 T1) o1 T2) o2 T3)
-               return bf2(bf1(bf0(t0,t1),t2),t3);
+                static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result;
+                return result;
             }
-
-            template <typename T0, typename T1, typename T2, typename T3>
+            
+            inline operator_type operation() const
+            {
+                return e_default;
+            }
+            
+            inline T value() const
+            {
+                return f_(t0_,t1_,t2_);
+            }
+            
+            inline T0 t0() const
+            {
+                return t0_;
+            }
+            
+            inline T1 t1() const
+            {
+                return t1_;
+            }
+            
+            inline T2 t2() const
+            {
+                return t2_;
+            }
+            
+            tfunc_t f() const
+            {
+                return f_;
+            }
+            
+            std::string type_id() const
+            {
+                return id();
+            }
+            
             static inline std::string id()
             {
-               static const std::string result = "((" + exprtk_crtype(T0) + "o"    +
-                                                        exprtk_crtype(T1) + ")o("  +
-                                                        exprtk_crtype(T2) + "))o(" +
-                                                        exprtk_crtype(T3) + ")";
-               return result;
+                return "sf3";
             }
-         };
-
-         struct mode4
-         {
-            static inline T process(const T& t0, const T& t1,
-                                    const T& t2, const T& t3,
-                                    const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
+            
+            template <typename Allocator>
+            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>(p0,p1,p2,p3);
+            }
+            
+        private:
+            
+            T0oT1oT2_sf3(node_type&) {}
+            node_type& operator=(node_type&) { return *this; }
+            
+            T0 t0_;
+            T1 t1_;
+            T2 t2_;
+            const tfunc_t f_;
+        };
+        
+        template <typename T, typename T0, typename T1, typename T2>
+        class sf3ext_type_node : public T0oT1oT2_base_node<T>
+        {
+        public:
+            
+            virtual ~sf3ext_type_node()
+            {}
+            
+            virtual T0 t0() const = 0;
+            
+            virtual T1 t1() const = 0;
+            
+            virtual T2 t2() const = 0;
+        };
+        
+        template <typename T, typename T0, typename T1, typename T2, typename SF3Operation>
+        class T0oT1oT2_sf3ext : public sf3ext_type_node<T,T0,T1,T2>
+        {
+        public:
+            
+            typedef typename details::functor_t<T> functor_t;
+            typedef typename functor_t::tfunc_t      tfunc_t;
+            typedef T value_type;
+            typedef T0oT1oT2_sf3ext<T,T0,T1,T2,SF3Operation> node_type;
+            
+            T0oT1oT2_sf3ext(T0 p0, T1 p1, T2 p2)
+            : t0_(p0),
+            t1_(p1),
+            t2_(p2)
+            {}
+            
+            inline typename expression_node<T>::node_type type() const
             {
-               // ((T0 o0 (T1 o1 T2)) o2 T3
-               return bf2(bf0(t0,bf1(t1,t2)),t3);
+                static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result;
+                return result;
             }
-
-            template <typename T0, typename T1, typename T2, typename T3>
+            
+            inline operator_type operation() const
+            {
+                return e_default;
+            }
+            
+            inline T value() const
+            {
+                return SF3Operation::process(t0_,t1_,t2_);
+            }
+            
+            T0 t0() const
+            {
+                return t0_;
+            }
+            
+            T1 t1() const
+            {
+                return t1_;
+            }
+            
+            T2 t2() const
+            {
+                return t2_;
+            }
+            
+            std::string type_id() const
+            {
+                return id();
+            }
+            
             static inline std::string id()
             {
-               static const std::string result = "((" + exprtk_crtype(T0) + ")o("  +
-                                                        exprtk_crtype(T1) + "o"    +
-                                                        exprtk_crtype(T2) + "))o(" +
-                                                        exprtk_crtype(T3) + ")"    ;
-               return result;
+                return SF3Operation::id();
             }
-         };
-      };
-
-      #undef exprtk_crtype
-
-      template <typename T, typename T0, typename T1>
-      struct nodetype_T0oT1 { static const typename expression_node<T>::node_type result; };
-      template <typename T, typename T0, typename T1>
-      const typename expression_node<T>::node_type nodetype_T0oT1<T,T0,T1>::result = expression_node<T>::e_none;
-
-      #define synthesis_node_type_define(T0_,T1_,v_)                                                            \
-      template <typename T, typename T0, typename T1>                                                           \
-      struct nodetype_T0oT1<T,T0_,T1_> { static const typename expression_node<T>::node_type result; };         \
-      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)
-      #undef synthesis_node_type_define
-
-      template <typename T, typename T0, typename T1, typename T2>
-      struct nodetype_T0oT1oT2 { static const typename expression_node<T>::node_type result; };
-      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>::e_none;
-
-      #define synthesis_node_type_define(T0_,T1_,T2_,v_)                                                               \
-      template <typename T, typename T0, typename T1, typename T2>                                                     \
-      struct nodetype_T0oT1oT2<T,T0_,T1_,T2_> { static const typename expression_node<T>::node_type result; };         \
-      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 )
-      #undef synthesis_node_type_define
-
-      template <typename T, typename T0, typename T1, typename T2, typename T3>
-      struct nodetype_T0oT1oT2oT3 { static const typename expression_node<T>::node_type result; };
-      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>::e_none;
-
-      #define synthesis_node_type_define(T0_,T1_,T2_,T3_,v_)                                                                  \
-      template <typename T, typename T0, typename T1, typename T2, typename T3>                                               \
-      struct nodetype_T0oT1oT2oT3<T,T0_,T1_,T2_,T3_> { static const typename expression_node<T>::node_type result; };         \
-      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   )
-      #undef synthesis_node_type_define
-
-      template <typename T, typename T0, typename T1>
-      class T0oT1 : public expression_node<T>
-      {
-      public:
-
-         typedef typename details::functor_t<T> functor_t;
-         typedef typename functor_t::bfunc_t      bfunc_t;
-         typedef T value_type;
-         typedef T0oT1<T,T0,T1> node_type;
-
-         T0oT1(T0 p0, T1 p1, const bfunc_t p2)
-         : t0_(p0),
-           t1_(p1),
-           f_ (p2)
-         {}
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            static const typename expression_node<T>::node_type result = nodetype_T0oT1<T,T0,T1>::result;
-            return result;
-         }
-
-         inline operator_type operation() const
-         {
-            return e_default;
-         }
-
-         inline T value() const
-         {
-            return f_(t0_,t1_);
-         }
-
-         inline T0 t0() const
-         {
-            return t0_;
-         }
-
-         inline T1 t1() const
-         {
-            return t1_;
-         }
-
-         inline bfunc_t f() const
-         {
-            return f_;
-         }
-
-         template <typename Allocator>
-         static inline expression_node<T>* allocate(Allocator& allocator,
-                                                    T0 p0, T1 p1,
-                                                    bfunc_t p2)
-         {
-            return allocator.template allocate_type<node_type,T0,T1,bfunc_t&>(p0,p1,p2);
-         }
-
-      private:
-
-         T0oT1(T0oT1<T,T0,T1>&) {}
-         T0oT1<T,T0,T1>& operator=(T0oT1<T,T0,T1>&) { return *this; }
-
-         T0 t0_;
-         T1 t1_;
-         const bfunc_t f_;
-      };
-
-      template <typename T, typename T0, typename T1, typename T2, typename ProcessMode>
-      class T0oT1oT2 : public T0oT1oT2_base_node<T>
-      {
-      public:
-
-         typedef typename details::functor_t<T> functor_t;
-         typedef typename functor_t::bfunc_t      bfunc_t;
-         typedef T value_type;
-         typedef T0oT1oT2<T,T0,T1,T2,ProcessMode> node_type;
-         typedef ProcessMode process_mode_t;
-
-         T0oT1oT2(T0 p0, T1 p1, T2 p2, const bfunc_t p3, const bfunc_t p4)
-         : t0_(p0),
-           t1_(p1),
-           t2_(p2),
-           f0_(p3),
-           f1_(p4)
-         {}
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result;
-            return result;
-         }
-
-         inline operator_type operation() const
-         {
-            return e_default;
-         }
-
-         inline T value() const
-         {
-            return ProcessMode::process(t0_,t1_,t2_,f0_,f1_);
-         }
-
-         inline T0 t0() const
-         {
-            return t0_;
-         }
-
-         inline T1 t1() const
-         {
-            return t1_;
-         }
-
-         inline T2 t2() const
-         {
-            return t2_;
-         }
-
-         bfunc_t f0() const
-         {
-            return f0_;
-         }
-
-         bfunc_t f1() const
-         {
-            return f1_;
-         }
-
-         std::string type_id() const
-         {
-            return id();
-         }
-
-         static inline std::string id()
-         {
-            return process_mode_t::template id<T0,T1,T2>();
-         }
-
-         template <typename Allocator>
-         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>(p0,p1,p2,p3,p4);
-         }
-
-      private:
-
-         T0oT1oT2(node_type&) {}
-         node_type& operator=(node_type&) { return *this; }
-
-         T0 t0_;
-         T1 t1_;
-         T2 t2_;
-         const bfunc_t f0_;
-         const bfunc_t f1_;
-      };
-
-      template <typename T, typename T0_, typename T1_, typename T2_, typename T3_, typename ProcessMode>
-      class T0oT1oT2oT3 : public T0oT1oT2oT3_base_node<T>
-      {
-      public:
-
-         typedef typename details::functor_t<T> functor_t;
-         typedef typename functor_t::bfunc_t      bfunc_t;
-         typedef T value_type;
-         typedef T0_ T0;
-         typedef T1_ T1;
-         typedef T2_ T2;
-         typedef T3_ T3;
-         typedef T0oT1oT2oT3<T,T0,T1,T2,T3,ProcessMode> node_type;
-         typedef ProcessMode process_mode_t;
-
-         T0oT1oT2oT3(T0 p0, T1 p1, T2 p2, T3 p3, bfunc_t p4, bfunc_t p5, bfunc_t p6)
-         : t0_(p0),
-           t1_(p1),
-           t2_(p2),
-           t3_(p3),
-           f0_(p4),
-           f1_(p5),
-           f2_(p6)
-         {}
-
-         inline T value() const
-         {
-            return ProcessMode::process(t0_,t1_,t2_,t3_,f0_,f1_,f2_);
-         }
-
-         inline T0 t0() const
-         {
-            return t0_;
-         }
-
-         inline T1 t1() const
-         {
-            return t1_;
-         }
-
-         inline T2 t2() const
-         {
-            return t2_;
-         }
-
-         inline T3 t3() const
-         {
-            return t3_;
-         }
-
-         inline bfunc_t f0() const
-         {
-            return f0_;
-         }
-
-         inline bfunc_t f1() const
-         {
-            return f1_;
-         }
-
-         inline bfunc_t f2() const
-         {
-            return f2_;
-         }
-
-         inline std::string type_id() const
-         {
-            return id();
-         }
-
-         static inline std::string id()
-         {
-            return process_mode_t::template id<T0,T1,T2,T3>();
-         }
-
-         template <typename Allocator>
-         static inline expression_node<T>* allocate(Allocator& allocator,
-                                                    T0 p0, T1 p1, T2 p2, T3 p3,
-                                                    bfunc_t p4, bfunc_t p5, bfunc_t p6)
-         {
-            return allocator.template allocate_type<node_type,T0,T1,T2,T3,bfunc_t,bfunc_t>(p0,p1,p2,p3,p4,p5,p6);
-         }
-
-      private:
-
-         T0oT1oT2oT3(node_type&) {}
-         node_type& operator=(node_type&) { return *this; }
-
-         T0 t0_;
-         T1 t1_;
-         T2 t2_;
-         T3 t3_;
-         const bfunc_t f0_;
-         const bfunc_t f1_;
-         const bfunc_t f2_;
-      };
-
-      template <typename T, typename T0, typename T1, typename T2>
-      class T0oT1oT2_sf3 : public T0oT1oT2_base_node<T>
-      {
-      public:
-
-         typedef typename details::functor_t<T> functor_t;
-         typedef typename functor_t::tfunc_t      tfunc_t;
-         typedef T value_type;
-         typedef T0oT1oT2_sf3<T,T0,T1,T2> node_type;
-
-         T0oT1oT2_sf3(T0 p0, T1 p1, T2 p2, const tfunc_t p3)
-         : t0_(p0),
-           t1_(p1),
-           t2_(p2),
-           f_ (p3)
-         {}
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result;
-            return result;
-         }
-
-         inline operator_type operation() const
-         {
-            return e_default;
-         }
-
-         inline T value() const
-         {
-            return f_(t0_,t1_,t2_);
-         }
-
-         inline T0 t0() const
-         {
-            return t0_;
-         }
-
-         inline T1 t1() const
-         {
-            return t1_;
-         }
-
-         inline T2 t2() const
-         {
-            return t2_;
-         }
-
-         tfunc_t f() const
-         {
-            return f_;
-         }
-
-         std::string type_id() const
-         {
-            return id();
-         }
-
-         static inline std::string id()
-         {
-            return "sf3";
-         }
-
-         template <typename Allocator>
-         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>(p0,p1,p2,p3);
-         }
-
-      private:
-
-         T0oT1oT2_sf3(node_type&) {}
-         node_type& operator=(node_type&) { return *this; }
-
-         T0 t0_;
-         T1 t1_;
-         T2 t2_;
-         const tfunc_t f_;
-      };
-
-      template <typename T, typename T0, typename T1, typename T2>
-      class sf3ext_type_node : public T0oT1oT2_base_node<T>
-      {
-      public:
-
-         virtual T0 t0() const = 0;
-
-         virtual T1 t1() const = 0;
-
-         virtual T2 t2() const = 0;
-      };
-
-      template <typename T, typename T0, typename T1, typename T2, typename SF3Operation>
-      class T0oT1oT2_sf3ext : public sf3ext_type_node<T,T0,T1,T2>
-      {
-      public:
-
-         typedef typename details::functor_t<T> functor_t;
-         typedef typename functor_t::tfunc_t      tfunc_t;
-         typedef T value_type;
-         typedef T0oT1oT2_sf3ext<T,T0,T1,T2,SF3Operation> node_type;
-
-         T0oT1oT2_sf3ext(T0 p0, T1 p1, T2 p2)
-         : t0_(p0),
-           t1_(p1),
-           t2_(p2)
-         {}
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result;
-            return result;
-         }
-
-         inline operator_type operation() const
-         {
-            return e_default;
-         }
-
-         inline T value() const
-         {
-            return SF3Operation::process(t0_,t1_,t2_);
-         }
-
-         T0 t0() const
-         {
-            return t0_;
-         }
-
-         T1 t1() const
-         {
-            return t1_;
-         }
-
-         T2 t2() const
-         {
-            return t2_;
-         }
-
-         std::string type_id() const
-         {
-            return id();
-         }
-
-         static inline std::string id()
-         {
-            return SF3Operation::id();
-         }
-
-         template <typename Allocator>
-         static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2)
-         {
-            return allocator.template allocate_type<node_type,T0,T1,T2>(p0,p1,p2);
-         }
-
-      private:
-
-         T0oT1oT2_sf3ext(node_type&) {}
-         node_type& operator=(node_type&) { return *this; }
-
-         T0 t0_;
-         T1 t1_;
-         T2 t2_;
-      };
-
-      template <typename T>
-      inline bool is_sf3ext_node(const expression_node<T>* n)
-      {
-         switch (n->type())
-         {
-            case expression_node<T>::e_vovov : return true;
-            case expression_node<T>::e_vovoc : return true;
-            case expression_node<T>::e_vocov : return true;
-            case expression_node<T>::e_covov : return true;
-            case expression_node<T>::e_covoc : return true;
-            default                          : return false;
-         }
-      }
-
-      template <typename T, typename T0, typename T1, typename T2, typename T3>
-      class T0oT1oT2oT3_sf4 : public T0oT1oT2_base_node<T>
-      {
-      public:
-
-         typedef typename details::functor_t<T> functor_t;
-         typedef typename functor_t::qfunc_t      qfunc_t;
-         typedef T value_type;
-         typedef T0oT1oT2oT3_sf4<T,T0,T1,T2,T3> node_type;
-
-         T0oT1oT2oT3_sf4(T0 p0, T1 p1, T2 p2, T3 p3, const qfunc_t p4)
-         : t0_(p0),
-           t1_(p1),
-           t2_(p2),
-           t3_(p3),
-           f_ (p4)
-         {}
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result;
-            return result;
-         }
-
-         inline operator_type operation() const
-         {
-            return e_default;
-         }
-
-         inline T value() const
-         {
-            return f_(t0_,t1_,t2_,t3_);
-         }
-
-         inline T0 t0() const
-         {
-            return t0_;
-         }
-
-         inline T1 t1() const
-         {
-            return t1_;
-         }
-
-         inline T2 t2() const
-         {
-            return t2_;
-         }
-
-         inline T3 t3() const
-         {
-            return t3_;
-         }
-
-         qfunc_t f() const
-         {
-            return f_;
-         }
-
-         std::string type_id() const
-         {
-            return id();
-         }
-
-         static inline std::string id()
-         {
-            return "sf4";
-         }
-
-         template <typename Allocator>
-         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>(p0,p1,p2,p3,p4);
-         }
-
-      private:
-
-         T0oT1oT2oT3_sf4(node_type&) {}
-         node_type& operator=(node_type&) { return *this; }
-
-         T0 t0_;
-         T1 t1_;
-         T2 t2_;
-         T3 t3_;
-         const qfunc_t f_;
-      };
-
-      template <typename T, typename T0, typename T1, typename T2, typename T3, typename SF4Operation>
-      class T0oT1oT2oT3_sf4ext : public T0oT1oT2oT3_base_node<T>
-      {
-      public:
-
-         typedef typename details::functor_t<T> functor_t;
-         typedef typename functor_t::tfunc_t      tfunc_t;
-         typedef T value_type;
-         typedef T0oT1oT2oT3_sf4ext<T,T0,T1,T2,T3,SF4Operation> node_type;
-
-         T0oT1oT2oT3_sf4ext(T0 p0, T1 p1, T2 p2, T3 p3)
-         : t0_(p0),
-           t1_(p1),
-           t2_(p2),
-           t3_(p3)
-         {}
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result;
-            return result;
-         }
-
-         inline operator_type operation() const
-         {
-            return e_default;
-         }
-
-         inline T value() const
-         {
-            return SF4Operation::process(t0_,t1_,t2_,t3_);
-         }
-
-         inline T0 t0() const
-         {
-            return t0_;
-         }
-
-         inline T1 t1() const
-         {
-            return t1_;
-         }
-
-         inline T2 t2() const
-         {
-            return t2_;
-         }
-
-         inline T3 t3() const
-         {
-            return t2_;
-         }
-
-         std::string type_id() const
-         {
-            return id();
-         }
-
-         static inline std::string id()
-         {
-            return SF4Operation::id();
-         }
-
-         template <typename Allocator>
-         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>(p0,p1,p2,p3);
-         }
-
-      private:
-
-         T0oT1oT2oT3_sf4ext(node_type&) {}
-         node_type& operator=(node_type&) { return *this; }
-
-         T0 t0_;
-         T1 t1_;
-         T2 t2_;
-         T3 t3_;
-      };
-
-      template <typename T>
-      inline bool is_sf4ext_node(const expression_node<T>* n)
-      {
-         switch (n->type())
-         {
-            case expression_node<T>::e_vovovov : return true;
-            case expression_node<T>::e_vovovoc : return true;
-            case expression_node<T>::e_vovocov : return true;
-            case expression_node<T>::e_vocovov : return true;
-            case expression_node<T>::e_covovov : return true;
-            case expression_node<T>::e_covocov : return true;
-            case expression_node<T>::e_vocovoc : return true;
-            case expression_node<T>::e_covovoc : return true;
-            case expression_node<T>::e_vococov : return true;
-            default                            : return false;
-         }
-      }
-
-      template <typename T, typename T0, typename T1>
-      struct T0oT1_define
-      {
-         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;
-      };
-
-      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;
-      };
-
-      template <typename T, typename Operation>
-      class vov_node : public vov_base_node<T>
-      {
-      public:
-
-         typedef expression_node<T>* expression_ptr;
-         typedef Operation operation_t;
-
-         // variable op variable node
-         explicit vov_node(const T& var0, const T& var1)
-         : v0_(var0),
-           v1_(var1)
-         {}
-
-         inline T value() const
-         {
-            return Operation::process(v0_,v1_);
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return Operation::type();
-         }
-
-         inline operator_type operation() const
-         {
-            return Operation::operation();
-         }
-
-         inline const T& v0() const
-         {
-            return v0_;
-         }
-
-         inline const T& v1() const
-         {
-            return v1_;
-         }
-
-      protected:
-
-         const T& v0_;
-         const T& v1_;
-
-      private:
-
-         vov_node(vov_node<T,Operation>&);
-         vov_node<T,Operation>& operator=(vov_node<T,Operation>&);
-      };
-
-      template <typename T, typename Operation>
-      class cov_node : public cov_base_node<T>
-      {
-      public:
-
-         typedef expression_node<T>* expression_ptr;
-         typedef Operation operation_t;
-
-         // constant op variable node
-         explicit cov_node(const T& const_var, const T& var)
-         : c_(const_var),
-           v_(var)
-         {}
-
-         inline T value() const
-         {
-            return Operation::process(c_,v_);
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return Operation::type();
-         }
-
-         inline operator_type operation() const
-         {
-            return Operation::operation();
-         }
-
-         inline const T c() const
-         {
-            return c_;
-         }
-
-         inline const T& v() const
-         {
-            return v_;
-         }
-
-      protected:
-
-         const T  c_;
-         const T& v_;
-
-      private:
-
-         cov_node(const cov_node<T,Operation>&);
-         cov_node<T,Operation>& operator=(const cov_node<T,Operation>&);
-      };
-
-      template <typename T, typename Operation>
-      class voc_node : public voc_base_node<T>
-      {
-      public:
-
-         typedef expression_node<T>* expression_ptr;
-         typedef Operation operation_t;
-
-         // variable op constant node
-         explicit voc_node(const T& var, const T& const_var)
-         : v_(var),
-           c_(const_var)
-         {}
-
-         inline T value() const
-         {
-            return Operation::process(v_,c_);
-         }
-
-         inline operator_type operation() const
-         {
-            return Operation::operation();
-         }
-
-         inline const T c() const
-         {
-            return c_;
-         }
-
-         inline const T& v() const
-         {
-            return v_;
-         }
-
-      protected:
-
-         const T& v_;
-         const T  c_;
-
-      private:
-
-         voc_node(const voc_node<T,Operation>&);
-         voc_node<T,Operation>& operator=(const voc_node<T,Operation>&);
-      };
-
-      template <typename T, typename Operation>
-      class vob_node : public vob_base_node<T>
-      {
-      public:
-
-         typedef expression_node<T>* expression_ptr;
-         typedef std::pair<expression_ptr,bool> branch_t;
-         typedef Operation operation_t;
-
-         // variable op constant node
-         explicit vob_node(const T& var, const expression_ptr brnch)
-         : v_(var)
-         {
-            init_branches<1>(branch_,brnch);
-         }
-
-        ~vob_node()
-         {
-            cleanup_branches::execute<T,1>(branch_);
-         }
-
-         inline T value() const
-         {
-            return Operation::process(v_,branch_[0].first->value());
-         }
-
-         inline operator_type operation() const
-         {
-            return Operation::operation();
-         }
-
-         inline const T& v() const
-         {
-            return v_;
-         }
-
-         inline expression_node<T>* branch(const std::size_t&) const
-         {
-            return branch_[0].first;
-         }
-
-      private:
-
-         vob_node(const vob_node<T,Operation>&);
-         vob_node<T,Operation>& operator=(const vob_node<T,Operation>&);
-
-         const T& v_;
-         branch_t branch_[1];
-      };
-
-      template <typename T, typename Operation>
-      class bov_node : public bov_base_node<T>
-      {
-      public:
-
-         typedef expression_node<T>* expression_ptr;
-         typedef std::pair<expression_ptr,bool> branch_t;
-         typedef Operation operation_t;
-
-         // variable op constant node
-         explicit bov_node(const expression_ptr brnch, const T& var)
-         : v_(var)
-         {
-            init_branches<1>(branch_,brnch);
-         }
-
-        ~bov_node()
-         {
-            cleanup_branches::execute<T,1>(branch_);
-         }
-
-         inline T value() const
-         {
-            return Operation::process(branch_[0].first->value(),v_);
-         }
-
-         inline operator_type operation() const
-         {
-            return Operation::operation();
-         }
-
-         inline const T& v() const
-         {
-            return v_;
-         }
-
-         inline expression_node<T>* branch(const std::size_t&) const
-         {
-            return branch_[0].first;
-         }
-
-      private:
-
-         bov_node(const bov_node<T,Operation>&);
-         bov_node<T,Operation>& operator=(const bov_node<T,Operation>&);
-
-         const T& v_;
-         branch_t branch_[1];
-      };
-
-      template <typename T, typename Operation>
-      class cob_node : public cob_base_node<T>
-      {
-      public:
-
-         typedef expression_node<T>* expression_ptr;
-         typedef std::pair<expression_ptr,bool> branch_t;
-         typedef Operation operation_t;
-
-         // variable op constant node
-         explicit cob_node(const T const_var, const expression_ptr brnch)
-         : c_(const_var)
-         {
-            init_branches<1>(branch_,brnch);
-         }
-
-        ~cob_node()
-         {
-            cleanup_branches::execute<T,1>(branch_);
-         }
-
-         inline T value() const
-         {
-            return Operation::process(c_,branch_[0].first->value());
-         }
-
-         inline operator_type operation() const
-         {
-            return Operation::operation();
-         }
-
-         inline const T c() const
-         {
-            return c_;
-         }
-
-         inline void set_c(const T new_c)
-         {
-            (*const_cast<T*>(&c_)) = new_c;
-         }
-
-         inline expression_node<T>* branch(const std::size_t&) const
-         {
-            return branch_[0].first;
-         }
-
-         inline expression_node<T>* move_branch(const std::size_t&)
-         {
-            branch_[0].second = false;
-            return branch_[0].first;
-         }
-
-      private:
-
-         cob_node(const cob_node<T,Operation>&);
-         cob_node<T,Operation>& operator=(const cob_node<T,Operation>&);
-
-         const T c_;
-         branch_t branch_[1];
-      };
-
-      template <typename T, typename Operation>
-      class boc_node : public boc_base_node<T>
-      {
-      public:
-
-         typedef expression_node<T>* expression_ptr;
-         typedef std::pair<expression_ptr,bool> branch_t;
-         typedef Operation operation_t;
-
-         // variable op constant node
-         explicit boc_node(const expression_ptr brnch, const T const_var)
-         : c_(const_var)
-         {
-            init_branches<1>(branch_,brnch);
-         }
-
-        ~boc_node()
-         {
-            cleanup_branches::execute<T,1>(branch_);
-         }
-
-         inline T value() const
-         {
-            return Operation::process(branch_[0].first->value(),c_);
-         }
-
-         inline operator_type operation() const
-         {
-            return Operation::operation();
-         }
-
-         inline const T c() const
-         {
-            return c_;
-         }
-
-         inline void set_c(const T new_c)
-         {
-            (*const_cast<T*>(&c_)) = new_c;
-         }
-
-         inline expression_node<T>* branch(const std::size_t&) const
-         {
-            return branch_[0].first;
-         }
-
-         inline expression_node<T>* move_branch(const std::size_t&)
-         {
-            branch_[0].second = false;
-            return branch_[0].first;
-         }
-
-      private:
-
-         boc_node(const boc_node<T,Operation>&);
-         boc_node<T,Operation>& operator=(const boc_node<T,Operation>&);
-
-         const T c_;
-         branch_t branch_[1];
-      };
-
-      #ifndef exprtk_disable_string_capabilities
-      template <typename T, typename SType0, typename SType1, typename Operation>
-      class sos_node : public sos_base_node<T>
-      {
-      public:
-
-         typedef expression_node<T>* expression_ptr;
-         typedef Operation operation_t;
-
-         // string op string node
-         explicit sos_node(SType0 p0, SType1 p1)
-         : s0_(p0),
-           s1_(p1)
-         {}
-
-         inline T value() const
-         {
-            return Operation::process(s0_,s1_);
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return Operation::type();
-         }
-
-         inline operator_type operation() const
-         {
-            return Operation::operation();
-         }
-
-         inline std::string& s0()
-         {
-            return s0_;
-         }
-
-         inline std::string& s1()
-         {
-            return s1_;
-         }
-
-      protected:
-
-         SType0 s0_;
-         SType1 s1_;
-
-      private:
-
-         sos_node(sos_node<T,SType0,SType1,Operation>&);
-         sos_node<T,SType0,SType1,Operation>& operator=(sos_node<T,SType0,SType1,Operation>&);
-      };
-
-      template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation>
-      class str_xrox_node : public sos_base_node<T>
-      {
-      public:
-
-         typedef expression_node<T>* expression_ptr;
-         typedef Operation operation_t;
-
-         // string-range op string node
-         explicit str_xrox_node(SType0 p0, SType1 p1, RangePack rp0)
-         : s0_(p0),
-           s1_(p1),
-           rp0_(rp0)
-         {}
-
-        ~str_xrox_node()
-         {
-            rp0_.free();
-         }
-
-         inline T value() const
-         {
-            std::size_t r0 = 0;
-            std::size_t r1 = 0;
-
-            if (rp0_(r0,r1,s0_.size()))
-               return Operation::process(s0_.substr(r0,(r1 - r0) + 1),s1_);
-            else
-               return T(0);
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return Operation::type();
-         }
-
-         inline operator_type operation() const
-         {
-            return Operation::operation();
-         }
-
-         inline std::string& s0()
-         {
-            return s0_;
-         }
-
-         inline std::string& s1()
-         {
-            return s1_;
-         }
-
-      protected:
-
-         SType0    s0_;
-         SType1    s1_;
-         RangePack rp0_;
-
-      private:
-
-         str_xrox_node(str_xrox_node<T,SType0,SType1,RangePack,Operation>&);
-         str_xrox_node<T,SType0,SType1,RangePack,Operation>& operator=(str_xrox_node<T,SType0,SType1,RangePack,Operation>&);
-      };
-
-      template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation>
-      class str_xoxr_node : public sos_base_node<T>
-      {
-      public:
-
-         typedef expression_node<T>* expression_ptr;
-         typedef Operation operation_t;
-
-         // string op string range node
-         explicit str_xoxr_node(SType0 p0, SType1 p1, RangePack rp1)
-         : s0_ (p0 ),
-           s1_ (p1 ),
-           rp1_(rp1)
-         {}
-
-        ~str_xoxr_node()
-         {
-            rp1_.free();
-         }
-
-         inline T value() const
-         {
-            std::size_t r0 = 0;
-            std::size_t r1 = 0;
-
-            if (rp1_(r0,r1,s1_.size()))
-               return Operation::process(s0_,s1_.substr(r0,(r1 - r0) + 1));
-            else
-               return T(0);
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return Operation::type();
-         }
-
-         inline operator_type operation() const
-         {
-            return Operation::operation();
-         }
-
-         inline std::string& s0()
-         {
-            return s0_;
-         }
-
-         inline std::string& s1()
-         {
-            return s1_;
-         }
-
-      protected:
-
-         SType0    s0_;
-         SType1    s1_;
-         RangePack rp1_;
-
-      private:
-
-         str_xoxr_node(str_xoxr_node<T,SType0,SType1,RangePack,Operation>&);
-         str_xoxr_node<T,SType0,SType1,RangePack,Operation>& operator=(str_xoxr_node<T,SType0,SType1,RangePack,Operation>&);
-      };
-
-      template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation>
-      class str_xroxr_node : public sos_base_node<T>
-      {
-      public:
-
-         typedef expression_node<T>* expression_ptr;
-         typedef Operation operation_t;
-
-         // string-range op string-range node
-         explicit str_xroxr_node(SType0 p0, SType1 p1, RangePack rp0, RangePack rp1)
-         : s0_ (p0 ),
-           s1_ (p1 ),
-           rp0_(rp0),
-           rp1_(rp1)
-         {}
-
-        ~str_xroxr_node()
-         {
-            rp0_.free();
-            rp1_.free();
-         }
-
-         inline T value() const
-         {
-            std::size_t r0_0 = 0;
-            std::size_t r0_1 = 0;
-            std::size_t r1_0 = 0;
-            std::size_t r1_1 = 0;
-            if (
-                 rp0_(r0_0,r1_0,s0_.size()) &&
-                 rp1_(r0_1,r1_1,s1_.size())
-               )
+            
+            template <typename Allocator>
+            static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2)
+            {
+                return allocator.template allocate_type<node_type,T0,T1,T2>(p0,p1,p2);
+            }
+            
+        private:
+            
+            T0oT1oT2_sf3ext(node_type&) {}
+            node_type& operator=(node_type&) { return *this; }
+            
+            T0 t0_;
+            T1 t1_;
+            T2 t2_;
+        };
+        
+        template <typename T>
+        inline bool is_sf3ext_node(const expression_node<T>* n)
+        {
+            switch (n->type())
+            {
+                case expression_node<T>::e_vovov : return true;
+                case expression_node<T>::e_vovoc : return true;
+                case expression_node<T>::e_vocov : return true;
+                case expression_node<T>::e_covov : return true;
+                case expression_node<T>::e_covoc : return true;
+                default                          : return false;
+            }
+        }
+        
+        template <typename T, typename T0, typename T1, typename T2, typename T3>
+        class T0oT1oT2oT3_sf4 : public T0oT1oT2_base_node<T>
+        {
+        public:
+            
+            typedef typename details::functor_t<T> functor_t;
+            typedef typename functor_t::qfunc_t      qfunc_t;
+            typedef T value_type;
+            typedef T0oT1oT2oT3_sf4<T,T0,T1,T2,T3> node_type;
+            
+            T0oT1oT2oT3_sf4(T0 p0, T1 p1, T2 p2, T3 p3, const qfunc_t p4)
+            : t0_(p0),
+            t1_(p1),
+            t2_(p2),
+            t3_(p3),
+            f_ (p4)
+            {}
+            
+            inline typename expression_node<T>::node_type type() const
             {
-               return Operation::process(
-                                          s0_.substr(r0_0,(r1_0 - r0_0) + 1),
-                                          s1_.substr(r0_1,(r1_1 - r0_1) + 1)
-                                        );
+                static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result;
+                return result;
             }
-            else
-               return T(0);
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return Operation::type();
-         }
-
-         inline operator_type operation() const
-         {
-            return Operation::operation();
-         }
-
-         inline std::string& s0()
-         {
-            return s0_;
-         }
-
-         inline std::string& s1()
-         {
-            return s1_;
-         }
-
-      protected:
-
-         SType0    s0_;
-         SType1    s1_;
-         RangePack rp0_;
-         RangePack rp1_;
-
-      private:
-
-         str_xroxr_node(str_xroxr_node<T,SType0,SType1,RangePack,Operation>&);
-         str_xroxr_node<T,SType0,SType1,RangePack,Operation>& operator=(str_xroxr_node<T,SType0,SType1,RangePack,Operation>&);
-      };
-
-      template <typename T, typename Operation>
-      class str_sogens_node : public binary_node<T>
-      {
-      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;
-
-         str_sogens_node(const operator_type& opr,
-                         expression_ptr branch0,
-                         expression_ptr branch1)
-         : binary_node<T>(opr,branch0,branch1),
-           str0_base_ptr_ (0),
-           str1_base_ptr_ (0),
-           str0_range_ptr_(0),
-           str1_range_ptr_(0)
-         {
-            if (is_generally_string_node(binary_node<T>::branch_[0].first))
-            {
-               str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
-
-               if (0 == str0_base_ptr_)
-                  return;
-
-               irange_ptr range_ptr = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first);
-
-               if (0 == range_ptr)
-                  return;
-
-               str0_range_ptr_ = &(range_ptr->range_ref());
+            
+            inline operator_type operation() const
+            {
+                return e_default;
             }
-
-            if (is_generally_string_node(binary_node<T>::branch_[1].first))
+            
+            inline T value() const
             {
-               str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);
-
-               if (0 == str1_base_ptr_)
-                  return;
-
-               irange_ptr range_ptr = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
-
-               if (0 == range_ptr)
-                  return;
-
-               str1_range_ptr_ = &(range_ptr->range_ref());
+                return f_(t0_,t1_,t2_,t3_);
             }
-         }
-
-         inline T value() const
-         {
-            if (
-                 str0_base_ptr_  &&
-                 str1_base_ptr_  &&
-                 str0_range_ptr_ &&
-                 str1_range_ptr_
-               )
-            {
-               binary_node<T>::branch_[0].first->value();
-               binary_node<T>::branch_[1].first->value();
-
-               std::size_t str0_r0 = 0;
-               std::size_t str0_r1 = 0;
-
-               std::size_t str1_r0 = 0;
-               std::size_t str1_r1 = 0;
-
-               range_t& range0 = (*str0_range_ptr_);
-               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())
-                  )
-               {
-                  return Operation::process(
-                                             str0_base_ptr_->str().substr(str0_r0,(str0_r1 - str0_r0) + 1),
-                                             str1_base_ptr_->str().substr(str1_r0,(str1_r1 - str1_r0) + 1)
-                                           );
-               }
+            
+            inline T0 t0() const
+            {
+                return t0_;
             }
-
-            return std::numeric_limits<T>::quiet_NaN();
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return Operation::type();
-         }
-
-         inline operator_type operation() const
-         {
-            return Operation::operation();
-         }
-
-      private:
-
-         str_sogens_node(str_sogens_node<T,Operation>&);
-         str_sogens_node<T,Operation>& operator=(str_sogens_node<T,Operation>&);
-
-         str_base_ptr str0_base_ptr_;
-         str_base_ptr str1_base_ptr_;
-         range_ptr    str0_range_ptr_;
-         range_ptr    str1_range_ptr_;
-      };
-
-      template <typename T, typename SType0, typename SType1, typename SType2, typename Operation>
-      class sosos_node : public sosos_base_node<T>
-      {
-      public:
-
-         typedef expression_node<T>* expression_ptr;
-         typedef Operation operation_t;
-
-         // variable op variable node
-         explicit sosos_node(SType0 p0, SType1 p1, SType2 p2)
-         : s0_(p0),
-           s1_(p1),
-           s2_(p2)
-         {}
-
-         inline T value() const
-         {
-            return Operation::process(s0_,s1_,s2_);
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return Operation::type();
-         }
-
-         inline operator_type operation() const
-         {
-            return Operation::operation();
-         }
-
-         inline std::string& s0()
-         {
-            return s0_;
-         }
-
-         inline std::string& s1()
-         {
-            return s1_;
-         }
-
-         inline std::string& s2()
-         {
-            return s2_;
-         }
-
-      protected:
-
-         SType0 s0_;
-         SType1 s1_;
-         SType2 s2_;
-
-      private:
-
-         sosos_node(sosos_node<T,SType0,SType1,SType2,Operation>&);
-         sosos_node<T,SType0,SType1,SType2,Operation>& operator=(sosos_node<T,SType0,SType1,SType2,Operation>&);
-      };
-      #endif
-
-      template <typename T, typename PowOp>
-      class ipow_node : public expression_node<T>
-      {
-      public:
-
-         typedef expression_node<T>* expression_ptr;
-         typedef PowOp operation_t;
-
-         explicit ipow_node(const T& v)
-         : v_(v)
-         {}
-
-         inline T value() const
-         {
-            return PowOp::result(v_);
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_ipow;
-         }
-
-      private:
-
-         ipow_node(const ipow_node<T,PowOp>&);
-         ipow_node<T,PowOp>& operator=(const ipow_node<T,PowOp>&);
-
-         const T& v_;
-      };
-
-      template <typename T, typename PowOp>
-      class ipowinv_node : public expression_node<T>
-      {
-      public:
-
-         typedef expression_node<T>* expression_ptr;
-         typedef PowOp operation_t;
-
-         explicit ipowinv_node(const T& v)
-         : v_(v)
-         {}
-
-         inline T value() const
-         {
-            return (T(1) / PowOp::result(v_));
-         }
-
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_ipowinv;
-         }
-
-      private:
-
-         ipowinv_node(const ipowinv_node<T,PowOp>&);
-         ipowinv_node<T,PowOp>& operator=(const ipowinv_node<T,PowOp>&);
-
-         const T& v_;
-      };
-
-      template <typename T>
-      inline bool is_vov_node(const expression_node<T>* node)
-      {
-         return (0 != dynamic_cast<const vov_base_node<T>*>(node));
-      }
-
-      template <typename T>
-      inline bool is_cov_node(const expression_node<T>* node)
-      {
-         return (0 != dynamic_cast<const cov_base_node<T>*>(node));
-      }
-
-      template <typename T>
-      inline bool is_voc_node(const expression_node<T>* node)
-      {
-         return (0 != dynamic_cast<const voc_base_node<T>*>(node));
-      }
-
-      template <typename T>
-      inline bool is_cob_node(const expression_node<T>* node)
-      {
-         return (0 != dynamic_cast<const cob_base_node<T>*>(node));
-      }
-
-      template <typename T>
-      inline bool is_boc_node(const expression_node<T>* node)
-      {
-         return (0 != dynamic_cast<const boc_base_node<T>*>(node));
-      }
-
-      template <typename T>
-      inline bool is_t0ot1ot2_node(const expression_node<T>* node)
-      {
-         return (0 != dynamic_cast<const T0oT1oT2_base_node<T>*>(node));
-      }
-
-      template <typename T>
-      inline bool is_t0ot1ot2ot3_node(const expression_node<T>* node)
-      {
-         return (0 != dynamic_cast<const T0oT1oT2oT3_base_node<T>*>(node));
-      }
-
-      template <typename T>
-      inline bool is_uv_node(const expression_node<T>* node)
-      {
-         return (0 != dynamic_cast<const uv_base_node<T>*>(node));
-      }
-
-      template <typename T>
-      inline bool is_string_node(const expression_node<T>* node)
-      {
-         return node && (expression_node<T>::e_stringvar == node->type());
-      }
-
-      template <typename T>
-      inline bool is_string_range_node(const expression_node<T>* node)
-      {
-         return node && (expression_node<T>::e_stringvarrng == node->type());
-      }
-
-      template <typename T>
-      inline bool is_const_string_node(const expression_node<T>* node)
-      {
-         return node && (expression_node<T>::e_stringconst == node->type());
-      }
-
-      template <typename T>
-      inline bool is_const_string_range_node(const expression_node<T>* node)
-      {
-         return node && (expression_node<T>::e_cstringvarrng == node->type());
-      }
-
-      template <typename T>
-      inline bool is_string_assignment_node(const expression_node<T>* node)
-      {
-         return node && (expression_node<T>::e_strass == node->type());
-      }
-
-      template <typename T>
-      inline bool is_string_concat_node(const expression_node<T>* node)
-      {
-         return node && (expression_node<T>::e_strconcat == node->type());
-      }
-
-      template <typename T>
-      inline bool is_string_function_node(const expression_node<T>* node)
-      {
-         return node && (expression_node<T>::e_strfunction == node->type());
-      }
-
-      template <typename T>
-      inline bool is_genricstring_range_node(const expression_node<T>* node)
-      {
-         return node && (expression_node<T>::e_strgenrange == node->type());
-      }
-
-      template <typename T>
-      inline bool is_generally_string_node(const expression_node<T>* node)
-      {
-         if (node)
-         {
-            switch (node->type())
-            {
-               case expression_node<T>::e_stringvar     :
-               case expression_node<T>::e_stringconst   :
-               case expression_node<T>::e_stringvarrng  :
-               case expression_node<T>::e_cstringvarrng :
-               case expression_node<T>::e_strgenrange   :
-               case expression_node<T>::e_strass        :
-               case expression_node<T>::e_strconcat     :
-               case expression_node<T>::e_strfunction   : return true;
-               default                                  : return false;
-            }
-         }
-
-         return false;
-      }
-
-      class node_allocator
-      {
-      public:
-
-         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]);
-         }
-
-         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]);
-         }
-
-         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]);
-         }
-
-         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]);
-         }
-
-         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]);
-         }
-
-         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]);
-         }
-
-         template <typename node_type>
-         inline expression_node<typename node_type::value_type>* allocate() const
-         {
-            return new node_type();
-         }
-
-         template <typename node_type,
-                   typename Type,
-                   typename Allocator,
-                   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);
-         }
-
-         template <typename node_type, typename T1>
-         inline expression_node<typename node_type::value_type>* allocate(T1& t1) const
-         {
-            return new node_type(t1);
-         }
-
-         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);
-         }
-
-         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);
-         }
-
-         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);
-         }
-
-         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);
-         }
-
-         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);
-         }
-
-         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);
-         }
-
-         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);
-         }
-
-         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);
-         }
-
-         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);
-         }
-
-         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);
-         }
-
-         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);
-         }
-
-         template <typename node_type,
-                   typename T1, typename T2, typename T3>
-         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);
-         }
-
-         template <typename node_type,
-                   typename T1, typename T2,
-                   typename T3, typename T4>
-         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);
-         }
-
-         template <typename node_type,
-                   typename T1, typename T2,
-                   typename T3, typename T4, typename T5>
-         inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
-                                                                          const T3& t3, const T4& t4,
-                                                                          const T5& t5) const
-         {
-            return new node_type(t1,t2,t3,t4,t5);
-         }
-
-         template <typename node_type,
-                   typename T1, typename T2,
-                   typename T3, typename T4, typename T5, typename T6>
-         inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
-                                                                          const T3& t3, const T4& t4,
-                                                                          const T5& t5, const T6& t6) const
-         {
-            return new node_type(t1,t2,t3,t4,t5,t6);
-         }
-
-         template <typename node_type,
-                   typename T1, typename T2,
-                   typename T3, typename T4,
-                   typename T5, typename T6, typename T7>
-         inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
-                                                                          const T3& t3, const T4& t4,
-                                                                          const T5& t5, const T6& t6,
-                                                                          const T7& t7) const
-         {
-            return new node_type(t1,t2,t3,t4,t5,t6,t7);
-         }
-
-         template <typename node_type,
-                   typename T1, typename T2,
-                   typename T3, typename T4,
-                   typename T5, typename T6,
-                   typename T7, typename T8>
-         inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
-                                                                          const T3& t3, const T4& t4,
-                                                                          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);
-         }
-
-         template <typename node_type,
-                   typename T1, typename T2,
-                   typename T3, typename T4,
-                   typename T5, typename T6,
-                   typename T7, typename T8, typename T9>
-         inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
-                                                                          const T3& t3, const T4& t4,
-                                                                          const T5& t5, const T6& t6,
-                                                                          const T7& t7, const T8& t8,
-                                                                          const T9& t9) const
-         {
-            return new node_type(t1,t2,t3,t4,t5,t6,t7,t8,t9);
-         }
-
-         template <typename node_type,
-                   typename T1, typename T2,
-                   typename T3, typename T4,
-                   typename T5, typename T6,
-                   typename T7, typename T8,
-                   typename T9, typename T10>
-         inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const  T2&  t2,
-                                                                          const T3& t3, const  T4&  t4,
-                                                                          const T5& t5, const  T6&  t6,
-                                                                          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);
-         }
-
-         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);
-         }
-
-         template <typename node_type,
-                   typename T1, typename T2,
-                   typename T3, typename T4>
-         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);
-         }
-
-         template <typename node_type,
-                   typename T1, typename T2,
-                   typename T3, typename T4,
-                   typename T5>
-         inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2,
-                                                                               T3 t3, T4 t4,
-                                                                               T5 t5) const
-         {
-            return new node_type(t1,t2,t3,t4,t5);
-         }
-
-         template <typename node_type,
-                   typename T1, typename T2,
-                   typename T3, typename T4,
-                   typename T5, typename T6, typename T7>
-         inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2,
-                                                                               T3 t3, T4 t4,
-                                                                               T5 t5, T6 t6,
-                                                                               T7 t7) const
-         {
-            return new node_type(t1,t2,t3,t4,t5,t6,t7);
-         }
-
-         template <typename T>
-         void inline free(expression_node<T>*& e) const
-         {
-            delete e;
-            e = 0;
-         }
-      };
-
-      inline void load_operations_map(std::multimap<std::string,details::base_operation_t,details::ilesscompare>& m)
-      {
-         #define register_op(Symbol,Type,Args)                                               \
-         m.insert(std::make_pair(std::string(Symbol),details::base_operation_t(Type,Args))); \
-
-         register_op(      "abs",e_abs     , 1)
-         register_op(     "acos",e_acos    , 1)
-         register_op(    "acosh",e_acosh   , 1)
-         register_op(     "asin",e_asin    , 1)
-         register_op(    "asinh",e_asinh   , 1)
-         register_op(     "atan",e_atan    , 1)
-         register_op(    "atanh",e_atanh   , 1)
-         register_op(     "ceil",e_ceil    , 1)
-         register_op(      "cos",e_cos     , 1)
-         register_op(     "cosh",e_cosh    , 1)
-         register_op(      "exp",e_exp     , 1)
-         register_op(    "expm1",e_expm1   , 1)
-         register_op(    "floor",e_floor   , 1)
-         register_op(      "log",e_log     , 1)
-         register_op(    "log10",e_log10   , 1)
-         register_op(     "log2",e_log2    , 1)
-         register_op(    "log1p",e_log1p   , 1)
-         register_op(    "round",e_round   , 1)
-         register_op(      "sin",e_sin     , 1)
-         register_op(     "sinc",e_sinc    , 1)
-         register_op(     "sinh",e_sinh    , 1)
-         register_op(      "sec",e_sec     , 1)
-         register_op(      "csc",e_csc     , 1)
-         register_op(     "sqrt",e_sqrt    , 1)
-         register_op(      "tan",e_tan     , 1)
-         register_op(     "tanh",e_tanh    , 1)
-         register_op(      "cot",e_cot     , 1)
-         register_op(  "rad2deg",e_r2d     , 1)
-         register_op(  "deg2rad",e_d2r     , 1)
-         register_op( "deg2grad",e_d2g     , 1)
-         register_op( "grad2deg",e_g2d     , 1)
-         register_op(      "sgn",e_sgn     , 1)
-         register_op(      "not",e_notl    , 1)
-         register_op(      "erf",e_erf     , 1)
-         register_op(     "erfc",e_erfc    , 1)
-         register_op(     "ncdf",e_ncdf    , 1)
-         register_op(     "frac",e_frac    , 1)
-         register_op(    "trunc",e_trunc   , 1)
-         register_op(    "atan2",e_atan2   , 2)
-         register_op(      "mod",e_mod     , 2)
-         register_op(     "logn",e_logn    , 2)
-         register_op(      "pow",e_pow     , 2)
-         register_op(     "root",e_root    , 2)
-         register_op(   "roundn",e_roundn  , 2)
-         register_op(    "equal",e_equal   , 2)
-         register_op("not_equal",e_nequal  , 2)
-         register_op(    "hypot",e_hypot   , 2)
-         register_op(      "shr",e_shr     , 2)
-         register_op(      "shl",e_shl     , 2)
-         register_op(    "clamp",e_clamp   , 3)
-         register_op(   "iclamp",e_iclamp  , 3)
-         register_op(  "inrange",e_inrange , 3)
-         #undef register_op
-      }
-
-   } // namespace details
-
-   template <typename T>
-   class ifunction
-   {
-   public:
-
-      explicit ifunction(const std::size_t& pc, const bool hse = true)
-      : param_count(pc),
-        has_side_effects(hse)
-      {}
-
-      virtual ~ifunction()
-      {}
-
-      inline virtual T operator()()
-      {
-         return std::numeric_limits<T>::quiet_NaN();
-      }
-
-      inline virtual T operator()(const T&)
-      {
-         return std::numeric_limits<T>::quiet_NaN();
-      }
-
-      inline virtual T operator()(const T&,const T&)
-      {
-         return std::numeric_limits<T>::quiet_NaN();
-      }
-
-      inline virtual T operator()(const T&, const T&, const T&)
-      {
-         return std::numeric_limits<T>::quiet_NaN();
-      }
-
-      inline virtual T operator()(const T&, const T&, const T&, const T&)
-      {
-         return std::numeric_limits<T>::quiet_NaN();
-      }
-
-      inline virtual T operator()(const T&, const T&, const T&, const T&, const T&)
-      {
-         return std::numeric_limits<T>::quiet_NaN();
-      }
-
-      inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&)
-      {
-         return std::numeric_limits<T>::quiet_NaN();
-      }
-
-      inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&)
-      {
-         return std::numeric_limits<T>::quiet_NaN();
-      }
-
-      inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
-      {
-         return std::numeric_limits<T>::quiet_NaN();
-      }
-
-      inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
-      {
-         return std::numeric_limits<T>::quiet_NaN();
-      }
-
-      inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
-      {
-         return std::numeric_limits<T>::quiet_NaN();
-      }
-
-      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&)
-      {
-         return std::numeric_limits<T>::quiet_NaN();
-      }
-
-      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&)
-      {
-         return std::numeric_limits<T>::quiet_NaN();
-      }
-
-      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&)
-      {
-         return std::numeric_limits<T>::quiet_NaN();
-      }
-
-      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&)
-      {
-         return std::numeric_limits<T>::quiet_NaN();
-      }
-
-      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&)
-      {
-         return std::numeric_limits<T>::quiet_NaN();
-      }
-
-      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&)
-      {
-         return std::numeric_limits<T>::quiet_NaN();
-      }
-
-      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&)
-      {
-         return std::numeric_limits<T>::quiet_NaN();
-      }
-
-      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&)
-      {
-         return std::numeric_limits<T>::quiet_NaN();
-      }
-
-      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&)
-      {
-         return std::numeric_limits<T>::quiet_NaN();
-      }
-
-      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&)
-      {
-         return std::numeric_limits<T>::quiet_NaN();
-      }
-
-      std::size_t param_count;
-      bool has_side_effects;
-   };
-
-   template <typename T>
-   class ivararg_function
-   {
-   public:
-
-      ivararg_function(const bool hse = true)
-      : has_side_effects(hse)
-      {}
-
-      virtual ~ivararg_function()
-      {}
-
-      inline virtual T operator()(const std::vector<T>&)
-      {
-         exprtk_debug(("ivararg_function::operator() - Operator has not been overriden.\n"));
-         return std::numeric_limits<T>::quiet_NaN();
-      }
-
-      bool has_side_effects;
-   };
-
-   template <typename T>
-   class igeneric_function
-   {
-   public:
-
-      typedef T type;
-      typedef type_store<T> generic_type;
-      typedef typename generic_type::parameter_list parameter_list_t;
-
-      igeneric_function(const std::string& param_seq = "",
-                        const bool hse = true)
-      : has_side_effects(hse),
-        parameter_sequence(param_seq)
-      {}
-
-      virtual ~igeneric_function()
-      {}
-
-      // f(i_0,i_1,....,i_N) --> Number
-      inline virtual T operator()(parameter_list_t)
-      {
-         exprtk_debug(("igeneric_function::operator() - Operator has not been overriden. [1]\n"));
-         return std::numeric_limits<T>::quiet_NaN();
-      }
-
-      // f(i_0,i_1,....,i_N) --> String
-      inline virtual T operator()(std::string&, parameter_list_t)
-      {
-         exprtk_debug(("igeneric_function::operator() - Operator has not been overriden. [2]\n"));
-         return std::numeric_limits<T>::quiet_NaN();
-      }
-
-      // f(psi,i_0,i_1,....,i_N) --> Number
-      inline virtual T operator()(const std::size_t&, parameter_list_t)
-      {
-         exprtk_debug(("igeneric_function::operator() - Operator has not been overriden. [3]\n"));
-         return std::numeric_limits<T>::quiet_NaN();
-      }
-
-      // f(psi,i_0,i_1,....,i_N) --> String
-      inline virtual T operator()(const std::size_t&, std::string&, parameter_list_t)
-      {
-         exprtk_debug(("igeneric_function::operator() - Operator has not been overriden. [4]\n"));
-         return std::numeric_limits<T>::quiet_NaN();
-      }
-
-      bool has_side_effects;
-      std::string parameter_sequence;
-   };
-
-   template <typename T> class parser;
-   template <typename T> class expression_helper;
-
-   template <typename T>
-   class symbol_table
-   {
-   protected:
-
-      template <typename Type> class parser;
-
-   protected:
-
-      template <typename Type, typename RawType>
-      struct type_store
-      {
-         typedef details::expression_node<T>*        expression_ptr;
-         typedef typename details::variable_node<T>  variable_node_t;
-         typedef ifunction<T>                        ifunction_t;
-         typedef ivararg_function<T>                 ivararg_function_t;
-         typedef igeneric_function<T>                igeneric_function_t;
-         typedef details::vector_holder<T>           vector_t;
-         #ifndef exprtk_disable_string_capabilities
-         typedef typename details::stringvar_node<T> stringvar_node_t;
-         #endif
-
-         typedef Type type_t;
-         typedef type_t* type_ptr;
-         typedef std::pair<bool,type_ptr> type_pair_t;
-         typedef std::map<std::string,type_pair_t,details::ilesscompare> type_map_t;
-         typedef typename type_map_t::iterator tm_itr_t;
-         typedef typename type_map_t::const_iterator tm_const_itr_t;
-
-         enum { lut_size = 256 };
-
-         type_map_t  map;
-         std::size_t size;
-
-         type_store()
-         : size(0)
-         {}
-
-         inline bool symbol_exists(const std::string& symbol_name) const
-         {
-            if (symbol_name.empty())
-               return false;
-            else if (map.end() != map.find(symbol_name))
-               return true;
-            else
-               return false;
-         }
-
-         template <typename PtrType>
-         inline std::string entity_name(const PtrType& ptr) const
-         {
-            if (map.empty())
-               return std::string();
-
-            tm_const_itr_t itr = map.begin();
-
-            while (map.end() != itr)
+            
+            inline T1 t1() const
             {
-               if (itr->second.second == ptr)
-               {
-                  return itr->first;
-               }
-               else
-                  ++itr;
+                return t1_;
             }
-
-            return std::string();
-         }
-
-         inline bool is_constant(const std::string& symbol_name) const
-         {
-            if (symbol_name.empty())
-               return false;
-            else
+            
+            inline T2 t2() const
             {
-               tm_const_itr_t itr = map.find(symbol_name);
-
-               if (map.end() == itr)
-                  return false;
-               else
-                  return (*itr).second.first;
+                return t2_;
             }
-         }
-
-         template <typename Tie, typename RType>
-         inline bool add_impl(const std::string& symbol_name, RType t, const bool is_const)
-         {
-            if (symbol_name.size() > 1)
-            {
-               for (std::size_t i = 0; i < details::reserved_symbols_size; ++i)
-               {
-                  if (details::imatch(symbol_name,details::reserved_symbols[i]))
-                  {
-                     return false;
-                  }
-               }
+            
+            inline T3 t3() const
+            {
+                return t3_;
             }
-
-            tm_itr_t itr = map.find(symbol_name);
-
-            if (map.end() == itr)
+            
+            qfunc_t f() const
             {
-               map[symbol_name] = Tie::make(t,is_const);
-               ++size;
+                return f_;
             }
-
-            return true;
-         }
-
-         struct tie_array
-         {
-            static inline std::pair<bool,vector_t*> make(std::pair<T*,std::size_t> v, const bool is_const = false)
+            
+            std::string type_id() const
             {
-               return std::make_pair(is_const,new vector_t(v.first,v.second));
+                return id();
             }
-         };
-
-         struct tie_stdvec
-         {
+            
+            static inline std::string id()
+            {
+                return "sf4";
+            }
+            
             template <typename Allocator>
-            static inline std::pair<bool,vector_t*> make(std::vector<T,Allocator>& v, const bool is_const = false)
+            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>(p0,p1,p2,p3,p4);
+            }
+            
+        private:
+            
+            T0oT1oT2oT3_sf4(node_type&) {}
+            node_type& operator=(node_type&) { return *this; }
+            
+            T0 t0_;
+            T1 t1_;
+            T2 t2_;
+            T3 t3_;
+            const qfunc_t f_;
+        };
+        
+        template <typename T, typename T0, typename T1, typename T2, typename T3, typename SF4Operation>
+        class T0oT1oT2oT3_sf4ext : public T0oT1oT2oT3_base_node<T>
+        {
+        public:
+            
+            typedef typename details::functor_t<T> functor_t;
+            typedef typename functor_t::tfunc_t      tfunc_t;
+            typedef T value_type;
+            typedef T0oT1oT2oT3_sf4ext<T,T0,T1,T2,T3,SF4Operation> node_type;
+            
+            T0oT1oT2oT3_sf4ext(T0 p0, T1 p1, T2 p2, T3 p3)
+            : t0_(p0),
+            t1_(p1),
+            t2_(p2),
+            t3_(p3)
+            {}
+            
+            inline typename expression_node<T>::node_type type() const
             {
-               return std::make_pair(is_const,new vector_t(v));
+                static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result;
+                return result;
             }
-         };
-
-         struct tie_stddeq
-         {
+            
+            inline operator_type operation() const
+            {
+                return e_default;
+            }
+            
+            inline T value() const
+            {
+                return SF4Operation::process(t0_,t1_,t2_,t3_);
+            }
+            
+            inline T0 t0() const
+            {
+                return t0_;
+            }
+            
+            inline T1 t1() const
+            {
+                return t1_;
+            }
+            
+            inline T2 t2() const
+            {
+                return t2_;
+            }
+            
+            inline T3 t3() const
+            {
+                return t2_;
+            }
+            
+            std::string type_id() const
+            {
+                return id();
+            }
+            
+            static inline std::string id()
+            {
+                return SF4Operation::id();
+            }
+            
             template <typename Allocator>
-            static inline std::pair<bool,vector_t*> make(std::deque<T,Allocator>& v, const bool is_const = false)
+            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>(p0,p1,p2,p3);
+            }
+            
+        private:
+            
+            T0oT1oT2oT3_sf4ext(node_type&) {}
+            node_type& operator=(node_type&) { return *this; }
+            
+            T0 t0_;
+            T1 t1_;
+            T2 t2_;
+            T3 t3_;
+        };
+        
+        template <typename T>
+        inline bool is_sf4ext_node(const expression_node<T>* n)
+        {
+            switch (n->type())
+            {
+                case expression_node<T>::e_vovovov : return true;
+                case expression_node<T>::e_vovovoc : return true;
+                case expression_node<T>::e_vovocov : return true;
+                case expression_node<T>::e_vocovov : return true;
+                case expression_node<T>::e_covovov : return true;
+                case expression_node<T>::e_covocov : return true;
+                case expression_node<T>::e_vocovoc : return true;
+                case expression_node<T>::e_covovoc : return true;
+                case expression_node<T>::e_vococov : return true;
+                default                            : return false;
+            }
+        }
+        
+        template <typename T, typename T0, typename T1>
+        struct T0oT1_define
+        {
+            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;
+        };
+        
+        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;
+        };
+        
+        template <typename T, typename Operation>
+        class vov_node : public vov_base_node<T>
+        {
+        public:
+            
+            typedef expression_node<T>* expression_ptr;
+            typedef Operation operation_t;
+            
+            // variable op variable node
+            explicit vov_node(const T& var0, const T& var1)
+            : v0_(var0),
+            v1_(var1)
+            {}
+            
+            inline T value() const
             {
-               return std::make_pair(is_const,new vector_t(v));
+                return Operation::process(v0_,v1_);
             }
-         };
-
-         template <std::size_t v_size>
-         inline bool add(const std::string& symbol_name, T (&v)[v_size], const bool is_const = false)
-         {
-            return add_impl<tie_array,std::pair<T*,std::size_t> >(symbol_name,std::make_pair(v,v_size),is_const);
-         }
-
-         inline bool add(const std::string& symbol_name, T* v, const std::size_t v_size, const bool is_const = false)
-         {
-            return add_impl<tie_array,std::pair<T*,std::size_t> >(symbol_name,std::make_pair(v,v_size),is_const);
-         }
-
-         template <typename Allocator>
-         inline bool add(const std::string& symbol_name, std::vector<T,Allocator>& v, const bool is_const = false)
-         {
-            return add_impl<tie_stdvec,std::vector<T,Allocator>&>(symbol_name,v,is_const);
-         }
-
-         template <typename Allocator>
-         inline bool add(const std::string& symbol_name, std::deque<T,Allocator>& v, const bool is_const = false)
-         {
-            return add_impl<tie_stddeq,std::deque<T,Allocator>&>(symbol_name,v,is_const);
-         }
-
-         inline bool add(const std::string& symbol_name, RawType& t, const bool is_const = false)
-         {
-            struct tie
-            {
-               static inline std::pair<bool,variable_node_t*> make(T& t,const bool is_const = false)
-               {
-                  return std::make_pair(is_const,new variable_node_t(t));
-               }
-
-               #ifndef exprtk_disable_string_capabilities
-               static inline std::pair<bool,stringvar_node_t*> make(std::string& t,const bool is_const = false)
-               {
-                  return std::make_pair(is_const,new stringvar_node_t(t));
-               }
-               #endif
-
-               static inline std::pair<bool,function_t*> make(function_t& t, const bool is_constant = false)
-               {
-                  return std::make_pair(is_constant,&t);
-               }
-
-               static inline std::pair<bool,vararg_function_t*> make(vararg_function_t& t, const bool is_const = false)
-               {
-                  return std::make_pair(is_const,&t);
-               }
-
-               static inline std::pair<bool,generic_function_t*> make(generic_function_t& t, const bool is_constant = false)
-               {
-                  return std::make_pair(is_constant,&t);
-               }
-            };
-
-            if (symbol_name.size() > 1)
+            
+            inline typename expression_node<T>::node_type type() const
             {
-               for (std::size_t i = 0; i < details::reserved_symbols_size; ++i)
-               {
-                  if (details::imatch(symbol_name,details::reserved_symbols[i]))
-                  {
-                     return false;
-                  }
-               }
+                return Operation::type();
             }
-
-            tm_itr_t itr = map.find(symbol_name);
-
-            if (map.end() == itr)
+            
+            inline operator_type operation() const
             {
-               map[symbol_name] = tie::make(t,is_const);
-               ++size;
+                return Operation::operation();
             }
-
-            return true;
-         }
-
-         inline type_ptr get(const std::string& symbol_name) const
-         {
-            tm_const_itr_t itr = map.find(symbol_name);
-
-            if (map.end() == itr)
-               return reinterpret_cast<type_ptr>(0);
-            else
-               return itr->second.second;
-         }
-
-         template <typename TType, typename TRawType, typename PtrType>
-         struct ptr_match
-         {
-            static inline bool test(const PtrType, const void*)
+            
+            inline const T& v0() const
             {
-               return false;
+                return v0_;
             }
-         };
-
-         template <typename TType, typename TRawType>
-         struct ptr_match<TType,TRawType,variable_node_t*>
-         {
-            static inline bool test(const variable_node_t* p, const void* ptr)
+            
+            inline const T& v1() const
             {
-               exprtk_debug(("ptr_match::test() - %p <--> %p\n",(void*)(&(p->ref())),ptr));
-               return (&(p->ref()) == ptr);
+                return v1_;
             }
-         };
-
-         inline type_ptr get_from_varptr(const void* ptr) const
-         {
-            tm_const_itr_t itr = map.begin();
-
-            while (map.end() != itr)
+            
+        protected:
+            
+            const T& v0_;
+            const T& v1_;
+            
+        private:
+            
+            vov_node(vov_node<T,Operation>&);
+            vov_node<T,Operation>& operator=(vov_node<T,Operation>&);
+        };
+        
+        template <typename T, typename Operation>
+        class cov_node : public cov_base_node<T>
+        {
+        public:
+            
+            typedef expression_node<T>* expression_ptr;
+            typedef Operation operation_t;
+            
+            // constant op variable node
+            explicit cov_node(const T& const_var, const T& var)
+            : c_(const_var),
+            v_(var)
+            {}
+            
+            inline T value() const
             {
-               type_ptr ret_ptr = itr->second.second;
-
-               if (ptr_match<Type,RawType,type_ptr>::test(ret_ptr,ptr))
-               {
-                  return ret_ptr;
-               }
-
-               ++itr;
+                return Operation::process(c_,v_);
             }
-
-            return type_ptr(0);
-         }
-
-         inline bool remove(const std::string& symbol_name, const bool delete_node = true)
-         {
-            tm_itr_t itr = map.find(symbol_name);
-
-            if (map.end() != itr)
-            {
-               struct deleter
-               {
-                  static inline void process(std::pair<bool,variable_node_t*>& n)  { delete n.second; }
-                  static inline void process(std::pair<bool,vector_t*>& n)         { delete n.second; }
-                  #ifndef exprtk_disable_string_capabilities
-                  static inline void process(std::pair<bool,stringvar_node_t*>& n) { delete n.second; }
-                  #endif
-                  static inline void process(std::pair<bool,function_t*>&)         {                  }
-               };
-
-               if (delete_node)
-               {
-                  deleter::process((*itr).second);
-               }
-
-               map.erase(itr);
-               --size;
-
-               return true;
+            
+            inline typename expression_node<T>::node_type type() const
+            {
+                return Operation::type();
             }
-            else
-               return false;
-         }
-
-         inline RawType& type_ref(const std::string& symbol_name)
-         {
-            struct init_type
-            {
-               static inline double set(double)           { return (0.0);           }
-               static inline double set(long double)      { return (0.0);           }
-               static inline float  set(float)            { return (0.0f);          }
-               static inline std::string set(std::string) { return std::string(""); }
-            };
-
-            static RawType null_type = init_type::set(RawType());
-
-            tm_const_itr_t itr = map.find(symbol_name);
-            if (map.end() == itr)
-               return null_type;
-            else
-               return itr->second.second->ref();
-         }
-
-         inline void clear(const bool delete_node = true)
-         {
-            struct deleter
-            {
-               static inline void process(std::pair<bool,variable_node_t*>& n)  { delete n.second; }
-               static inline void process(std::pair<bool,vector_t*>& n)         { delete n.second; }
-               static inline void process(std::pair<bool,function_t*>&)         {                  }
-               #ifndef exprtk_disable_string_capabilities
-               static inline void process(std::pair<bool,stringvar_node_t*>& n) { delete n.second; }
-               #endif
-            };
-
-            if (!map.empty())
+            
+            inline operator_type operation() const
             {
-               if (delete_node)
-               {
-                  tm_itr_t itr = map.begin();
-                  tm_itr_t end = map.end();
-
-                  while (end != itr)
-                  {
-                     deleter::process((*itr).second);
-                     ++itr;
-                  }
-               }
-
-               map.clear();
+                return Operation::operation();
             }
-
-            size = 0;
-         }
-
-         template <typename Allocator,
-                   template <typename, typename> class Sequence>
-         inline std::size_t get_list(Sequence<std::pair<std::string,RawType>,Allocator>& list) const
-         {
-            std::size_t count = 0;
-
-            if (!map.empty())
+            
+            inline const T c() const
             {
-               tm_const_itr_t itr = map.begin();
-               tm_const_itr_t end = map.end();
-
-               while (end != itr)
-               {
-                  list.push_back(std::make_pair((*itr).first,itr->second.second->ref()));
-                  ++itr;
-                  ++count;
-               }
+                return c_;
             }
-
-            return count;
-         }
-
-         template <typename Allocator,
-                   template <typename, typename> class Sequence>
-         inline std::size_t get_list(Sequence<std::string,Allocator>& vlist) const
-         {
-            std::size_t count = 0;
-
-            if (!map.empty())
+            
+            inline const T& v() const
             {
-               tm_const_itr_t itr = map.begin();
-               tm_const_itr_t end = map.end();
-
-               while (end != itr)
-               {
-                  vlist.push_back((*itr).first);
-                  ++itr;
-                  ++count;
-               }
+                return v_;
             }
-
-            return count;
-         }
-      };
-
-      typedef details::expression_node<T>* expression_ptr;
-      typedef typename details::variable_node<T> variable_t;
-      typedef typename details::vector_holder<T> vector_holder_t;
-      typedef variable_t* variable_ptr;
-      #ifndef exprtk_disable_string_capabilities
-      typedef typename details::stringvar_node<T> stringvar_t;
-      typedef stringvar_t* stringvar_ptr;
-      #endif
-      typedef ifunction<T> function_t;
-      typedef ivararg_function<T> vararg_function_t;
-      typedef igeneric_function<T> generic_function_t;
-      typedef function_t* function_ptr;
-      typedef vararg_function_t* vararg_function_ptr;
-      typedef generic_function_t* generic_function_ptr;
-
-      static const std::size_t lut_size = 256;
-
-      // Symbol Table Holder
-      struct st_holder
-      {
-         struct st_data
-         {
-            type_store<typename details::variable_node<T>,T> variable_store;
-            #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<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;
-
-            st_data()
+            
+        protected:
+            
+            const T  c_;
+            const T& v_;
+            
+        private:
+            
+            cov_node(const cov_node<T,Operation>&);
+            cov_node<T,Operation>& operator=(const cov_node<T,Operation>&);
+        };
+        
+        template <typename T, typename Operation>
+        class voc_node : public voc_base_node<T>
+        {
+        public:
+            
+            typedef expression_node<T>* expression_ptr;
+            typedef Operation operation_t;
+            
+            // variable op constant node
+            explicit voc_node(const T& var, const T& const_var)
+            : v_(var),
+            c_(const_var)
+            {}
+            
+            inline T value() const
             {
-               for (std::size_t i = 0; i < details::reserved_words_size; ++i)
-               {
-                  reserved_symbol_table_.insert(details::reserved_words[i]);
-               }
-
-               for (std::size_t i = 0; i < details::reserved_symbols_size; ++i)
-               {
-                  reserved_symbol_table_.insert(details::reserved_symbols[i]);
-               }
+                return Operation::process(v_,c_);
             }
-
-            inline bool is_reserved_symbol(const std::string& symbol) const
+            
+            inline operator_type operation() const
             {
-               return (reserved_symbol_table_.end() != reserved_symbol_table_.find(symbol));
+                return Operation::operation();
             }
-
-            std::list<T> local_symbol_list_;
-            std::list<std::string> local_stringvar_list_;
-            std::set<std::string> reserved_symbol_table_;
-         };
-
-         st_holder()
-         : ref_count(1),
-           data_(new st_data)
-         {}
-
-         st_holder(st_data* data)
-         : ref_count(1),
-           data_(data)
-         {}
-
-        ~st_holder()
-         {
-            if (data_ && (0 == ref_count))
+            
+            inline const T c() const
             {
-               delete data_;
-               data_ = 0;
+                return c_;
             }
-         }
-
-         std::size_t ref_count;
-         st_data* data_;
-      };
-
-   public:
-
-      symbol_table()
-      : holder_(new st_holder)
-      {
-         clear();
-      }
-
-     ~symbol_table()
-      {
-         if (holder_)
-         {
-            if (0 == --holder_->ref_count)
+            
+            inline const T& v() const
             {
-               clear();
-               delete holder_;
+                return v_;
             }
-         }
-      }
-
-      symbol_table(const symbol_table<T>& st)
-      {
-         holder_ = st.holder_;
-         holder_->ref_count++;
-      }
-
-      inline symbol_table<T>& operator=(const symbol_table<T>& st)
-      {
-         if (holder_)
-         {
-            if (0 == --holder_->ref_count)
+            
+        protected:
+            
+            const T& v_;
+            const T  c_;
+            
+        private:
+            
+            voc_node(const voc_node<T,Operation>&);
+            voc_node<T,Operation>& operator=(const voc_node<T,Operation>&);
+        };
+        
+        template <typename T, typename Operation>
+        class vob_node : public vob_base_node<T>
+        {
+        public:
+            
+            typedef expression_node<T>* expression_ptr;
+            typedef std::pair<expression_ptr,bool> branch_t;
+            typedef Operation operation_t;
+            
+            // variable op constant node
+            explicit vob_node(const T& var, const expression_ptr brnch)
+            : v_(var)
             {
-               delete holder_;
+                init_branches<1>(branch_,brnch);
             }
-
-            holder_ = 0;
-         }
-
-         holder_ = st.holder_;
-         holder_->ref_count++;
-
-         return *this;
-      }
-
-      inline bool operator==(const symbol_table<T>& st)
-      {
-         return (this == &st) || (holder_ == st.holder_);
-      }
-
-      inline void clear_variables(const bool delete_node = true)
-      {
-         local_data().variable_store.clear(delete_node);
-      }
-
-      inline void clear_functions()
-      {
-         local_data().function_store.clear();
-      }
-
-      inline void clear_strings()
-      {
-         #ifndef exprtk_disable_string_capabilities
-         local_data().stringvar_store.clear();
-         #endif
-      }
-
-      inline void clear_vectors()
-      {
-         local_data().vector_store.clear();
-      }
-
-      inline void clear()
-      {
-         if (!valid()) return;
-         clear_variables();
-         clear_functions();
-         clear_strings  ();
-         clear_vectors  ();
-      }
-
-      inline std::size_t variable_count() const
-      {
-         if (valid())
-            return local_data().variable_store.size;
-         else
-            return 0;
-      }
-
-      #ifndef exprtk_disable_string_capabilities
-      inline std::size_t stringvar_count() const
-      {
-         if (valid())
-            return local_data().stringvar_store.size;
-         else
-            return 0;
-      }
-      #endif
-
-      inline std::size_t function_count() const
-      {
-         if (valid())
-            return local_data().function_store.size;
-         else
-            return 0;
-      }
-
-      inline std::size_t vector_count() const
-      {
-         if (valid())
-            return local_data().vector_store.size;
-         else
-            return 0;
-      }
-
-      inline variable_ptr get_variable(const std::string& variable_name) const
-      {
-         if (!valid())
-            return reinterpret_cast<variable_ptr>(0);
-         else if (!valid_symbol(variable_name))
-            return reinterpret_cast<variable_ptr>(0);
-         else
-            return local_data().variable_store.get(variable_name);
-      }
-
-      inline variable_ptr get_variable(const T& var_ref) const
-      {
-         if (!valid())
-            return reinterpret_cast<variable_ptr>(0);
-         else
-            return local_data().variable_store.get_from_varptr(
-                                                  reinterpret_cast<const void*>(&var_ref));
-      }
-
-      #ifndef exprtk_disable_string_capabilities
-      inline stringvar_ptr get_stringvar(const std::string& string_name) const
-      {
-         if (!valid())
-            return reinterpret_cast<stringvar_ptr>(0);
-         else if (!valid_symbol(string_name))
-            return reinterpret_cast<stringvar_ptr>(0);
-         else
-            return local_data().stringvar_store.get(string_name);
-      }
-      #endif
-
-      inline function_ptr get_function(const std::string& function_name) const
-      {
-         if (!valid())
-            return reinterpret_cast<function_ptr>(0);
-         else if (!valid_symbol(function_name))
-            return reinterpret_cast<function_ptr>(0);
-         else
-            return local_data().function_store.get(function_name);
-      }
-
-      inline vararg_function_ptr get_vararg_function(const std::string& vararg_function_name) const
-      {
-         if (!valid())
-            return reinterpret_cast<vararg_function_ptr>(0);
-         else if (!valid_symbol(vararg_function_name))
-            return reinterpret_cast<vararg_function_ptr>(0);
-         else
-            return local_data().vararg_function_store.get(vararg_function_name);
-      }
-
-      inline generic_function_ptr get_generic_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().generic_function_store.get(function_name);
-      }
-
-      inline generic_function_ptr get_string_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().string_function_store.get(function_name);
-      }
-
-      typedef vector_holder_t* vector_holder_ptr;
-
-      inline vector_holder_ptr get_vector(const std::string& vector_name) const
-      {
-         if (!valid())
-            return reinterpret_cast<vector_holder_ptr>(0);
-         else if (!valid_symbol(vector_name))
-            return reinterpret_cast<vector_holder_ptr>(0);
-         else
-            return local_data().vector_store.get(vector_name);
-      }
-
-      inline T& variable_ref(const std::string& symbol_name)
-      {
-         static T null_var = T(0);
-         if (!valid())
-            return null_var;
-         else if (!valid_symbol(symbol_name))
-            return null_var;
-         else
-            return local_data().variable_store.type_ref(symbol_name);
-      }
-
-      #ifndef exprtk_disable_string_capabilities
-      inline std::string& stringvar_ref(const std::string& symbol_name)
-      {
-         static std::string null_stringvar;
-         if (!valid())
-            return null_stringvar;
-         else if (!valid_symbol(symbol_name))
-            return null_stringvar;
-         else
-            return local_data().stringvar_store.type_ref(symbol_name);
-      }
-      #endif
-
-      inline bool is_constant_node(const std::string& symbol_name) const
-      {
-         if (!valid())
-            return false;
-         else if (!valid_symbol(symbol_name))
-            return false;
-         else
-            return local_data().variable_store.is_constant(symbol_name);
-      }
-
-      #ifndef exprtk_disable_string_capabilities
-      inline bool is_constant_string(const std::string& symbol_name) const
-      {
-         if (!valid())
-            return false;
-         else if (!valid_symbol(symbol_name))
-            return false;
-         else if (!local_data().stringvar_store.symbol_exists(symbol_name))
-            return false;
-         else
-            return local_data().stringvar_store.is_constant(symbol_name);
-      }
-      #endif
-
-      inline bool create_variable(const std::string& variable_name, const T& value = T(0))
-      {
-         if (!valid())
-            return false;
-         else if (!valid_symbol(variable_name))
-            return false;
-         else if (symbol_exists(variable_name))
-            return false;
-
-         local_data().local_symbol_list_.push_back(value);
-         T& t = local_data().local_symbol_list_.back();
-
-         return add_variable(variable_name,t);
-      }
-
-      #ifndef exprtk_disable_string_capabilities
-      inline bool create_stringvar(const std::string& stringvar_name, const std::string& value = std::string(""))
-      {
-         if (!valid())
-            return false;
-         else if (!valid_symbol(stringvar_name))
-            return false;
-         else if (symbol_exists(stringvar_name))
-            return false;
-
-         local_data().local_stringvar_list_.push_back(value);
-         std::string& s = local_data().local_stringvar_list_.back();
-
-         return add_stringvar(stringvar_name,s);
-      }
-      #endif
-
-      inline bool add_variable(const std::string& variable_name, T& t, const bool is_constant = false)
-      {
-         if (!valid())
-            return false;
-         else if (!valid_symbol(variable_name))
-            return false;
-         else if (symbol_exists(variable_name))
-            return false;
-         else
-            return local_data().variable_store.add(variable_name,t,is_constant);
-      }
-
-      inline bool add_constant(const std::string& constant_name, const T& value)
-      {
-         if (!valid())
-            return false;
-         else if (!valid_symbol(constant_name))
-            return false;
-         else if (symbol_exists(constant_name))
-            return false;
-
-         local_data().local_symbol_list_.push_back(value);
-         T& t = local_data().local_symbol_list_.back();
-
-         return add_variable(constant_name,t,true);
-      }
-
-      #ifndef exprtk_disable_string_capabilities
-      inline bool add_stringvar(const std::string& stringvar_name, std::string& s, const bool is_constant = false)
-      {
-         if (!valid())
-            return false;
-         else if (!valid_symbol(stringvar_name))
-            return false;
-         else if (symbol_exists(stringvar_name))
-            return false;
-         else
-            return local_data().stringvar_store.add(stringvar_name,s,is_constant);
-      }
-      #endif
-
-      inline bool add_function(const std::string& function_name, function_t& function)
-      {
-         if (!valid())
-            return false;
-         else if (!valid_symbol(function_name))
-            return false;
-         else if (symbol_exists(function_name))
-            return false;
-         else
-            return local_data().function_store.add(function_name,function);
-      }
-
-      inline bool add_function(const std::string& vararg_function_name, vararg_function_t& vararg_function)
-      {
-         if (!valid())
-            return false;
-         else if (!valid_symbol(vararg_function_name))
-            return false;
-         else if (symbol_exists(vararg_function_name))
-            return false;
-         else
-            return local_data().vararg_function_store.add(vararg_function_name,vararg_function);
-      }
-
-      enum func_type
-      {
-         e_ft_unknown   = 0,
-         e_ft_basicfunc = 1,
-         e_ft_strfunc   = 2
-      };
-
-      inline bool add_function(const std::string& function_name, generic_function_t& function, const func_type ft = e_ft_basicfunc)
-      {
-         if (!valid())
-            return false;
-         else if (!valid_symbol(function_name))
-            return false;
-         else if (symbol_exists(function_name))
-            return false;
-         else if (std::string::npos != function.parameter_sequence.find_first_not_of("STV*?|"))
-            return false;
-         else if (e_ft_basicfunc == ft)
-            return local_data().generic_function_store.add(function_name,function);
-         else if (e_ft_strfunc == ft)
-            return local_data().string_function_store.add(function_name, function);
-         else
-            return false;
-      }
-
-      template <std::size_t N>
-      inline bool add_vector(const std::string& vector_name, T (&v)[N])
-      {
-         if (!valid())
-            return false;
-         else if (!valid_symbol(vector_name))
-            return false;
-         else if (symbol_exists(vector_name))
-            return false;
-         else
-            return local_data().vector_store.add(vector_name,v);
-      }
-
-      inline bool add_vector(const std::string& vector_name, T* v, const std::size_t& v_size)
-      {
-         if (!valid())
-            return false;
-         else if (!valid_symbol(vector_name))
-            return false;
-         else if (symbol_exists(vector_name))
-            return false;
-         else
-            return local_data().vector_store.add(vector_name,v,v_size);
-      }
-
-      template <typename Allocator>
-      inline bool add_vector(const std::string& vector_name, std::vector<T,Allocator>& v)
-      {
-         if (!valid())
-            return false;
-         else if (!valid_symbol(vector_name))
-            return false;
-         else if (symbol_exists(vector_name))
-            return false;
-         else
-            return local_data().vector_store.add(vector_name,v);
-      }
-
-      template <typename Allocator>
-      inline bool add_vector(const std::string& vector_name, std::deque<T,Allocator>& v)
-      {
-         if (!valid())
-            return false;
-         else if (!valid_symbol(vector_name))
-            return false;
-         else if (symbol_exists(vector_name))
-            return false;
-         else
-            return local_data().vector_store.add(vector_name,v);
-      }
-
-      inline bool remove_variable(const std::string& variable_name, const bool delete_node = true)
-      {
-         if (!valid())
-            return false;
-         else
-            return local_data().variable_store.remove(variable_name, delete_node);
-      }
-
-      #ifndef exprtk_disable_string_capabilities
-      inline bool remove_stringvar(const std::string& string_name)
-      {
-         if (!valid())
-            return false;
-         else
-            return local_data().stringvar_store.remove(string_name);
-      }
-      #endif
-
-      inline bool remove_function(const std::string& function_name)
-      {
-         if (!valid())
-            return false;
-         else
-            return local_data().function_store.remove(function_name);
-      }
-
-      inline bool remove_vararg_function(const std::string& vararg_function_name)
-      {
-         if (!valid())
-            return false;
-         else
-            return local_data().vararg_function_store.remove(vararg_function_name);
-      }
-
-      inline bool remove_vector(const std::string& vector_name)
-      {
-         if (!valid())
-            return false;
-         else
-            return local_data().vector_store.remove(vector_name);
-      }
-
-      inline bool add_constants()
-      {
-         return add_pi      () &&
-                add_epsilon () &&
-                add_infinity();
-      }
-
-      inline bool add_pi()
-      {
-         static const T local_pi = T(details::numeric::constant::pi);
-         return add_constant("pi",local_pi);
-      }
-
-      inline bool add_epsilon()
-      {
-         static const T local_epsilon = details::numeric::details::epsilon_type<T>::value();
-         return add_constant("epsilon",local_epsilon);
-      }
-
-      inline bool add_infinity()
-      {
-         static const T local_infinity = std::numeric_limits<T>::infinity();
-         return add_constant("inf",local_infinity);
-      }
-
-      template <typename Allocator,
-                template <typename, typename> class Sequence>
-      inline std::size_t get_variable_list(Sequence<std::pair<std::string,T>,Allocator>& vlist) const
-      {
-         if (!valid())
-            return 0;
-         else
-            return local_data().variable_store.get_list(vlist);
-      }
-
-      template <typename Allocator,
-                template <typename, typename> class Sequence>
-      inline std::size_t get_variable_list(Sequence<std::string,Allocator>& vlist) const
-      {
-         if (!valid())
-            return 0;
-         else
-            return local_data().variable_store.get_list(vlist);
-      }
-
-      #ifndef exprtk_disable_string_capabilities
-      template <typename Allocator,
-                template <typename, typename> class Sequence>
-      inline std::size_t get_stringvar_list(Sequence<std::pair<std::string,std::string>,Allocator>& svlist) const
-      {
-         if (!valid())
-            return 0;
-         else
-            return local_data().stringvar_store.get_list(svlist);
-      }
-
-      template <typename Allocator,
-                template <typename, typename> class Sequence>
-      inline std::size_t get_stringvar_list(Sequence<std::string,Allocator>& svlist) const
-      {
-         if (!valid())
-            return 0;
-         else
-            return local_data().stringvar_store.get_list(svlist);
-      }
-      #endif
-
-      template <typename Allocator,
-                template <typename, typename> class Sequence>
-      inline std::size_t get_vector_list(Sequence<std::string,Allocator>& vlist) const
-      {
-         if (!valid())
-            return 0;
-         else
-            return local_data().vector_store.get_list(vlist);
-      }
-
-      inline bool symbol_exists(const std::string& symbol_name) const
-      {
-         /*
-            Will return true if symbol_name exists as either a reserved symbol,
-            variable, stringvar or function name in any of the type stores.
-         */
-         if (!valid())
-            return false;
-         else if (local_data().variable_store.symbol_exists(symbol_name))
-            return true;
-         #ifndef exprtk_disable_string_capabilities
-         else if (local_data().stringvar_store.symbol_exists(symbol_name))
-            return true;
-         #endif
-         else if (local_data().function_store.symbol_exists(symbol_name))
-            return true;
-         else if (local_data().is_reserved_symbol(symbol_name))
-            return true;
-         else
-            return false;
-      }
-
-      inline bool is_variable(const std::string& variable_name) const
-      {
-         if (!valid())
-            return false;
-         else
-            return local_data().variable_store.symbol_exists(variable_name);
-      }
-
-      #ifndef exprtk_disable_string_capabilities
-      inline bool is_stringvar(const std::string& stringvar_name) const
-      {
-         if (!valid())
-            return false;
-         else
-            return local_data().stringvar_store.symbol_exists(stringvar_name);
-      }
-
-      inline bool is_conststr_stringvar(const std::string& symbol_name) const
-      {
-         if (!valid())
-            return false;
-         else if (!valid_symbol(symbol_name))
-            return false;
-         else if (!local_data().stringvar_store.symbol_exists(symbol_name))
-            return false;
-
-         return (
-                  local_data().stringvar_store.symbol_exists(symbol_name) ||
-                  local_data().stringvar_store.is_constant  (symbol_name)
-                );
-      }
-      #endif
-
-      inline bool is_function(const std::string& function_name) const
-      {
-         if (!valid())
-            return false;
-         else
-            return local_data().function_store.symbol_exists(function_name);
-      }
-
-      inline bool is_vararg_function(const std::string& vararg_function_name) const
-      {
-         if (!valid())
-            return false;
-         else
-            return local_data().vararg_function_store.symbol_exists(vararg_function_name);
-      }
-
-      inline bool is_vector(const std::string& vector_name) const
-      {
-         if (!valid())
-            return false;
-         else
-            return local_data().vector_store.symbol_exists(vector_name);
-      }
-
-      inline std::string get_variable_name(const expression_ptr& ptr) const
-      {
-         return local_data().variable_store.entity_name(ptr);
-      }
-
-      inline std::string get_vector_name(const vector_holder_ptr& ptr) const
-      {
-         return local_data().vector_store.entity_name(ptr);
-      }
-
-      #ifndef exprtk_disable_string_capabilities
-      inline std::string get_stringvar_name(const expression_ptr& ptr) const
-      {
-         return local_data().stringvar_store.entity_name(ptr);
-      }
-
-      inline std::string get_conststr_stringvar_name(const expression_ptr& ptr) const
-      {
-         return local_data().stringvar_store.entity_name(ptr);
-      }
-      #endif
-
-      inline bool valid() const
-      {
-         // Symbol table sanity check.
-         return holder_ && holder_->data_;
-      }
-
-      inline void load_from(const symbol_table<T>& st)
-      {
-         {
-            std::vector<std::string> name_list;
-
-            st.local_data().function_store.get_list(name_list);
-
-            if (!name_list.empty())
+            
+            ~vob_node()
             {
-               for (std::size_t i = 0; i < name_list.size(); ++i)
-               {
-                  exprtk::ifunction<T>& ifunc = *st.get_function(name_list[i]);
-                  add_function(name_list[i],ifunc);
-               }
+                cleanup_branches::execute<T,1>(branch_);
             }
-         }
-
-         {
-            std::vector<std::string> name_list;
-
-            st.local_data().vararg_function_store.get_list(name_list);
-
-            if (!name_list.empty())
+            
+            inline T value() const
             {
-               for (std::size_t i = 0; i < name_list.size(); ++i)
-               {
-                  exprtk::ivararg_function<T>& ivafunc = *st.get_vararg_function(name_list[i]);
-                  add_function(name_list[i],ivafunc);
-               }
+                return Operation::process(v_,branch_[0].first->value());
             }
-         }
-
-         {
-            std::vector<std::string> name_list;
-
-            st.local_data().generic_function_store.get_list(name_list);
-
-            if (!name_list.empty())
+            
+            inline operator_type operation() const
             {
-               for (std::size_t i = 0; i < name_list.size(); ++i)
-               {
-                  exprtk::igeneric_function<T>& ifunc = *st.get_generic_function(name_list[i]);
-                  add_function(name_list[i],ifunc);
-               }
+                return Operation::operation();
             }
-         }
-
-         {
-            std::vector<std::string> name_list;
-
-            st.local_data().string_function_store.get_list(name_list);
-
-            if (!name_list.empty())
+            
+            inline const T& v() const
             {
-               for (std::size_t i = 0; i < name_list.size(); ++i)
-               {
-                  exprtk::igeneric_function<T>& ifunc = *st.get_string_function(name_list[i]);
-                  add_function(name_list[i],ifunc,e_ft_strfunc);
-               }
+                return v_;
             }
-         }
-      }
-
-   private:
-
-      inline bool valid_symbol(const std::string& symbol) const
-      {
-         if (symbol.empty())
-            return false;
-         if (!details::is_letter(symbol[0]))
-            return false;
-         else if (symbol.size() > 1)
-         {
-            for (std::size_t i = 1; i < symbol.size(); ++i)
-            {
-               if (
-                    (!details::is_letter(symbol[i])) &&
-                    (!details:: is_digit(symbol[i])) &&
-                    ('_' != symbol[i])
-                  )
-               {
-                  return false;
-               }
-            }
-         }
-
-         return (!local_data().is_reserved_symbol(symbol));
-      }
-
-      inline typename st_holder::st_data& local_data()
-      {
-         return *(holder_->data_);
-      }
-
-      inline const typename st_holder::st_data& local_data() const
-      {
-         return *(holder_->data_);
-      }
-
-      st_holder* holder_;
-   };
-
-   template <typename T>
-   class function_compositor;
-
-   template <typename T>
-   class expression
-   {
-   private:
-
-      typedef details::expression_node<T>*  expression_ptr;
-      typedef details::vector_holder<T>* vector_holder_ptr;
-
-      struct expression_holder
-      {
-         enum data_type
-         {
-            e_unknown  ,
-            e_expr     ,
-            e_vecholder,
-            e_data     ,
-            e_vecdata  ,
-            e_string
-         };
-
-         struct data_pack
-         {
-            data_pack()
-            : pointer(0),
-              type(e_unknown),
-              size(0)
-            {}
-
-            data_pack(void* ptr, data_type dt, std::size_t sz = 0)
-            : pointer(ptr),
-              type(dt),
-              size(sz)
-            {}
-
-            void*       pointer;
-            data_type   type;
-            std::size_t size;
-         };
-
-         typedef std::vector<data_pack> local_data_list_t;
-
-         expression_holder()
-         : ref_count(0),
-           expr(0)
-         {}
-
-         expression_holder(expression_ptr e)
-         : ref_count(1),
-           expr(e)
-         {}
-
-        ~expression_holder()
-         {
-            if (expr && details::branch_deletable(expr))
+            
+            inline expression_node<T>* branch(const std::size_t&) const
             {
-               delete expr;
+                return branch_[0].first;
             }
-
-            if (!local_data_list.empty())
+            
+        private:
+            
+            vob_node(const vob_node<T,Operation>&);
+            vob_node<T,Operation>& operator=(const vob_node<T,Operation>&);
+            
+            const T& v_;
+            branch_t branch_[1];
+        };
+        
+        template <typename T, typename Operation>
+        class bov_node : public bov_base_node<T>
+        {
+        public:
+            
+            typedef expression_node<T>* expression_ptr;
+            typedef std::pair<expression_ptr,bool> branch_t;
+            typedef Operation operation_t;
+            
+            // variable op constant node
+            explicit bov_node(const expression_ptr brnch, const T& var)
+            : v_(var)
             {
-               for (std::size_t i = 0; i < local_data_list.size(); ++i)
-               {
-                  switch (local_data_list[i].type)
-                  {
-                     case e_expr      : delete reinterpret_cast<expression_ptr>(local_data_list[i].pointer);
-                                        break;
-
-                     case e_vecholder : delete reinterpret_cast<vector_holder_ptr>(local_data_list[i].pointer);
-                                        break;
-
-                     case e_data      : delete (T*)(local_data_list[i].pointer);
-                                        break;
-
-                     case e_vecdata   : delete [] (T*)(local_data_list[i].pointer);
-                                        break;
-
-                     case e_string    : delete (std::string*)(local_data_list[i].pointer);
-                                        break;
-
-                     default          : break;
-                  }
-               }
+                init_branches<1>(branch_,brnch);
             }
-         }
-
-         std::size_t ref_count;
-         expression_ptr expr;
-         local_data_list_t local_data_list;
-
-         friend class function_compositor<T>;
-      };
-
-   public:
-
-      expression()
-      : expression_holder_(0)
-      {
-         set_expression(new details::null_node<T>());
-      }
-
-      expression(const expression<T>& e)
-      : expression_holder_(e.expression_holder_),
-        symbol_table_(e.symbol_table_)
-      {
-         expression_holder_->ref_count++;
-      }
-
-      inline expression<T>& operator=(const expression<T>& e)
-      {
-         if (this != &e)
-         {
-            if (expression_holder_)
-            {
-               if (0 == --expression_holder_->ref_count)
-               {
-                  delete expression_holder_;
-               }
-
-               expression_holder_ = 0;
+            
+            ~bov_node()
+            {
+                cleanup_branches::execute<T,1>(branch_);
             }
-
-            expression_holder_ = e.expression_holder_;
-            expression_holder_->ref_count++;
-            symbol_table_ = e.symbol_table_;
-         }
-
-         return *this;
-      }
-
-      inline bool operator==(const expression<T>& e)
-      {
-         return (this == &e);
-      }
-
-      inline bool operator!() const
-      {
-         return (
-                  (0 == expression_holder_      ) ||
-                  (0 == expression_holder_->expr)
-                );
-      }
-
-      inline expression<T>& release()
-      {
-         if (expression_holder_)
-         {
-            if (0 == --expression_holder_->ref_count)
+            
+            inline T value() const
             {
-               delete expression_holder_;
+                return Operation::process(branch_[0].first->value(),v_);
             }
-
-            expression_holder_ = 0;
-         }
-
-         return *this;
-      }
-
-     ~expression()
-      {
-         if (expression_holder_)
-         {
-            if (0 == --expression_holder_->ref_count)
+            
+            inline operator_type operation() const
             {
-               delete expression_holder_;
+                return Operation::operation();
             }
-         }
-      }
-
-      inline T value() const
-      {
-         return expression_holder_->expr->value();
-      }
-
-      inline T operator()() const
-      {
-         return value();
-      }
-
-      inline operator T() const
-      {
-         return value();
-      }
-
-      inline operator bool() const
-      {
-         return details::is_true(value());
-      }
-
-      inline void register_symbol_table(symbol_table<T>& st)
-      {
-         symbol_table_ = st;
-      }
-
-      inline const symbol_table<T>& get_symbol_table() const
-      {
-         return symbol_table_;
-      }
-
-      inline symbol_table<T>& get_symbol_table()
-      {
-         return symbol_table_;
-      }
-
-   private:
-
-      inline void set_expression(const expression_ptr expr)
-      {
-         if (expr)
-         {
-            if (expression_holder_)
+            
+            inline const T& v() const
             {
-               if (0 == --expression_holder_->ref_count)
-               {
-                  delete expression_holder_;
-               }
+                return v_;
             }
-
-            expression_holder_ = new expression_holder(expr);
-         }
-      }
-
-      inline void register_local_var(expression_ptr expr)
-      {
-         if (expr)
-         {
-            if (expression_holder_)
-            {
-               expression_holder_->
-                  local_data_list.push_back(
-                     typename expression<T>::expression_holder::
-                        data_pack(reinterpret_cast<void*>(expr),
-                                  expression_holder::e_expr));
-            }
-         }
-      }
-
-      inline void register_local_var(vector_holder_ptr vec_holder)
-      {
-         if (vec_holder)
-         {
-            if (expression_holder_)
-            {
-               expression_holder_->
-                  local_data_list.push_back(
-                     typename expression<T>::expression_holder::
-                        data_pack(reinterpret_cast<void*>(vec_holder),
-                                  expression_holder::e_vecholder));
-            }
-         }
-      }
-
-      inline void register_local_data(void* data, const std::size_t& size = 0, const bool vectype = false)
-      {
-         if (data)
-         {
-            if (expression_holder_)
-            {
-               expression_holder_->
-                  local_data_list.push_back(
-                     typename expression<T>::expression_holder::
-                        data_pack(reinterpret_cast<void*>(data),
-                                  vectype ? expression_holder::e_vecdata :
-                                            expression_holder::e_data,
-                                  size));
-            }
-         }
-      }
-
-      inline const typename expression_holder::local_data_list_t& local_data_list()
-      {
-         if (expression_holder_)
-         {
-            return expression_holder_->local_data_list;
-         }
-         else
-         {
-            static typename expression_holder::local_data_list_t null_local_data_list;
-            return null_local_data_list;
-         }
-      }
-
-      expression_holder* expression_holder_;
-      symbol_table<T> symbol_table_;
-
-      friend class parser<T>;
-      friend class expression_helper<T>;
-      friend class function_compositor<T>;
-   };
-
-   template <typename T>
-   class expression_helper
-   {
-   public:
-
-      static inline bool is_constant(const expression<T>& expr)
-      {
-         return details::is_constant_node(expr.expression_holder_->expr);
-      }
-
-      static inline bool is_variable(const expression<T>& expr)
-      {
-         return details::is_variable_node(expr.expression_holder_->expr);
-      }
-
-      static inline bool is_unary(const expression<T>& expr)
-      {
-         return details::is_unary_node(expr.expression_holder_->expr);
-      }
-
-      static inline bool is_binary(const expression<T>& expr)
-      {
-         return details::is_binary_node(expr.expression_holder_->expr);
-      }
-
-      static inline bool is_function(const expression<T>& expr)
-      {
-         return details::is_function(expr.expression_holder_->expr);
-      }
-   };
-
-   namespace parser_error
-   {
-      enum error_mode
-      {
-         e_unknown = 0,
-         e_syntax  = 1,
-         e_token   = 2,
-         e_numeric = 4,
-         e_symtab  = 5,
-         e_lexer   = 6,
-         e_helper  = 7
-      };
-
-      struct type
-      {
-         type()
-         : mode(parser_error::e_unknown),
-           line_no  (0),
-           column_no(0)
-         {}
-
-         lexer::token token;
-         error_mode mode;
-         std::string diagnostic;
-         std::string error_line;
-         std::size_t line_no;
-         std::size_t column_no;
-      };
-
-      inline type make_error(error_mode mode, const std::string& diagnostic = "")
-      {
-         type t;
-         t.mode       = mode;
-         t.token.type = lexer::token::e_error;
-         t.diagnostic = diagnostic;
-         exprtk_debug(((diagnostic + "\n").c_str()));
-         return t;
-      }
-
-      inline type make_error(error_mode mode, const lexer::token& tk, const std::string& diagnostic = "")
-      {
-         type t;
-         t.mode       = mode;
-         t.token      = tk;
-         t.diagnostic = diagnostic;
-         exprtk_debug(((diagnostic + "\n").c_str()));
-         return t;
-      }
-
-      inline std::string to_str(error_mode mode)
-      {
-         switch (mode)
-         {
-            case e_unknown : return std::string("Unknown Error");
-            case e_syntax  : return std::string("Syntax Error" );
-            case e_token   : return std::string("Token Error"  );
-            case e_numeric : return std::string("Numeric Error");
-            case e_symtab  : return std::string("Symbol Error" );
-            case e_lexer   : return std::string("Lexer Error"  );
-            case e_helper  : return std::string("Helper Error" );
-            default        : return std::string("Unknown Error");
-         }
-      }
-
-      inline bool update_error(type& error, const std::string& expression)
-      {
-         if (
-              expression.empty()                         ||
-              (error.token.position > expression.size()) ||
-              (std::numeric_limits<std::size_t>::max() == error.token.position)
-            )
-         {
-            return false;
-         }
-
-         std::size_t error_line_start = 0;
-
-         for (std::size_t i = error.token.position; i > 0; --i)
-         {
-            const char c = expression[i];
-
-            if (('\n' == c) || ('\r' == c))
+            
+            inline expression_node<T>* branch(const std::size_t&) const
             {
-               error_line_start = i + 1;
-               break;
+                return branch_[0].first;
             }
-         }
-
-         std::size_t next_nl_position = std::min(expression.size(),
-                                                 expression.find_first_of('\n',error.token.position + 1));
-
-         error.column_no  = error.token.position - error_line_start;
-         error.error_line = expression.substr(error_line_start,
-                                              next_nl_position - error_line_start);
-
-         error.line_no = 0;
-
-         for (std::size_t i = 0; i < next_nl_position; ++i)
-         {
-            if ('\n' == expression[i])
-               ++error.line_no;
-         }
-
-         return true;
-      }
-
-      inline void dump_error(const type& error)
-      {
-         printf("Position: %02d   Type: [%s]   Msg: %s\n",
-                static_cast<int>(error.token.position),
-                exprtk::parser_error::to_str(error.mode).c_str(),
-                error.diagnostic.c_str());
-      }
-   }
-
-   template <typename T>
-   class parser
-   {
-   private:
-
-      enum precedence_level
-      {
-         e_level00,
-         e_level01,
-         e_level02,
-         e_level03,
-         e_level04,
-         e_level05,
-         e_level06,
-         e_level07,
-         e_level08,
-         e_level09,
-         e_level10,
-         e_level11,
-         e_level12,
-         e_level13,
-         e_level14
-      };
-
-      typedef const T&                                               cref_t;
-      typedef const T                                               const_t;
-      typedef ifunction                <T>                                F;
-      typedef ivararg_function         <T>                              VAF;
-      typedef igeneric_function        <T>                               GF;
-      typedef ifunction                <T>                      ifunction_t;
-      typedef ivararg_function         <T>               ivararg_function_t;
-      typedef igeneric_function        <T>              igeneric_function_t;
-      typedef details::expression_node <T>                expression_node_t;
-      typedef details::literal_node    <T>                   literal_node_t;
-      typedef details::unary_node      <T>                     unary_node_t;
-      typedef details::binary_node     <T>                    binary_node_t;
-      typedef details::trinary_node    <T>                   trinary_node_t;
-      typedef details::quaternary_node <T>                quaternary_node_t;
-      typedef details::quinary_node    <T>                   quinary_node_t;
-      typedef details::senary_node     <T>                    senary_node_t;
-      typedef details::conditional_node<T>               conditional_node_t;
-      typedef details::cons_conditional_node<T>     cons_conditional_node_t;
-      typedef details::while_loop_node <T>                while_loop_node_t;
-      typedef details::repeat_until_loop_node<T>   repeat_until_loop_node_t;
-      typedef details::for_loop_node   <T>                  for_loop_node_t;
-      #ifndef exprtk_disable_break_continue
-      typedef details::while_loop_bc_node <T>          while_loop_bc_node_t;
-      typedef details::repeat_until_loop_bc_node<T> repeat_until_loop_bc_node_t;
-      typedef details::for_loop_bc_node<T>               for_loop_bc_node_t;
-      #endif
-      typedef details::switch_node     <T>                    switch_node_t;
-      typedef details::variable_node   <T>                  variable_node_t;
-      typedef details::vector_elem_node<T>               vector_elem_node_t;
-      typedef details::vector_node     <T>                    vector_node_t;
-      #ifndef exprtk_disable_string_capabilities
-      typedef details::range_pack         <T>                       range_t;
-      typedef details::stringvar_node     <T>              stringvar_node_t;
-      typedef details::string_literal_node<T>         string_literal_node_t;
-      typedef details::string_range_node  <T>           string_range_node_t;
-      typedef details::const_string_range_node<T> const_string_range_node_t;
-      typedef details::generic_string_range_node<T> generic_string_range_node_t;
-      typedef details::string_concat_node <T>          string_concat_node_t;
-      typedef details::assignment_string_node<T>   assignment_string_node_t;
-      typedef details::assignment_string_range_node<T> assignment_string_range_node_t;
-      #endif
-      typedef details::assignment_node<T>                 assignment_node_t;
-      typedef details::assignment_vec_elem_node<T> assignment_vec_elem_node_t;
-      typedef details::assignment_vec_node     <T>    assignment_vec_node_t;
-      typedef details::assignment_vecvec_node  <T> assignment_vecvec_node_t;
-      typedef details::scand_node<T>                           scand_node_t;
-      typedef details::scor_node<T>                             scor_node_t;
-      typedef lexer::token                                          token_t;
-      typedef expression_node_t*                        expression_node_ptr;
-      typedef symbol_table<T>                                symbol_table_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 details::operator_type operator_t;
-
-      typedef std::map<operator_t,  unary_functor_t>   unary_op_map_t;
-      typedef std::map<operator_t, binary_functor_t>  binary_op_map_t;
-      typedef std::map<operator_t,trinary_functor_t> trinary_op_map_t;
-
-      typedef std::map<std::string,std::pair<trinary_functor_t   ,operator_t> > sf3_map_t;
-      typedef std::map<std::string,std::pair<quaternary_functor_t,operator_t> > sf4_map_t;
-
-      typedef std::map<binary_functor_t,operator_t> inv_binary_op_map_t;
-      typedef std::multimap<std::string,details::base_operation_t,details::ilesscompare> base_ops_map_t;
-
-      typedef details::T0oT1_define<T, cref_t, cref_t> vov_t;
-      typedef details::T0oT1_define<T,const_t, cref_t> cov_t;
-      typedef details::T0oT1_define<T, cref_t,const_t> voc_t;
-
-      typedef details::T0oT1oT2_define<T, cref_t, cref_t, cref_t> vovov_t;
-      typedef details::T0oT1oT2_define<T, cref_t, cref_t,const_t> vovoc_t;
-      typedef details::T0oT1oT2_define<T, cref_t,const_t, cref_t> vocov_t;
-      typedef details::T0oT1oT2_define<T,const_t, cref_t, cref_t> covov_t;
-      typedef details::T0oT1oT2_define<T,const_t, cref_t,const_t> covoc_t;
-      typedef details::T0oT1oT2_define<T,const_t,const_t, cref_t> cocov_t;
-      typedef details::T0oT1oT2_define<T,cref_t,const_t, const_t> vococ_t;
-
-      typedef details::T0oT1oT2oT3_define<T, cref_t, cref_t, cref_t, cref_t> vovovov_t;
-      typedef details::T0oT1oT2oT3_define<T, cref_t, cref_t, cref_t,const_t> vovovoc_t;
-      typedef details::T0oT1oT2oT3_define<T, cref_t, cref_t,const_t, cref_t> vovocov_t;
-      typedef details::T0oT1oT2oT3_define<T, cref_t,const_t, cref_t, cref_t> vocovov_t;
-      typedef details::T0oT1oT2oT3_define<T,const_t, cref_t, cref_t, cref_t> covovov_t;
-
-      typedef details::T0oT1oT2oT3_define<T,const_t, cref_t,const_t, cref_t> covocov_t;
-      typedef details::T0oT1oT2oT3_define<T, cref_t,const_t, cref_t,const_t> vocovoc_t;
-      typedef details::T0oT1oT2oT3_define<T,const_t, cref_t, cref_t,const_t> covovoc_t;
-      typedef details::T0oT1oT2oT3_define<T, cref_t,const_t,const_t, cref_t> vococov_t;
-
-      struct scope_element
-      {
-         enum element_type
-         {
-            e_none    ,
-            e_variable,
-            e_vector  ,
-            e_vecelem ,
-            e_string
-         };
-
-         typedef variable_node_t* variable_node_ptr;
-         typedef details::vector_holder<T> vector_holder_t;
-         typedef vector_holder_t* vector_holder_ptr;
-
-         scope_element()
-         : name("???"),
-           size (std::numeric_limits<std::size_t>::max()),
-           index(std::numeric_limits<std::size_t>::max()),
-           depth(std::numeric_limits<std::size_t>::max()),
-           ref_count(0),
-           ip_index (0),
-           type (e_none),
-           active(false),
-           data    (0),
-           var_node(0),
-           vec_node(0)
-         {}
-
-         bool operator < (const scope_element& se) const
-         {
-            if (ip_index < se.ip_index)
-               return true;
-            else if (ip_index > se.ip_index)
-               return false;
-            else if (depth < se.depth)
-               return true;
-            else if (depth > se.depth)
-               return false;
-            else if (index < se.index)
-               return true;
-            else if (index > se.index)
-               return false;
-            else
-               return (name < se.name);
-         }
-
-         std::string  name;
-         std::size_t  size;
-         std::size_t  index;
-         std::size_t  depth;
-         std::size_t  ref_count;
-         std::size_t  ip_index;
-         element_type type;
-         bool         active;
-         void*        data;
-         variable_node_ptr var_node;
-         vector_holder_ptr vec_node;
-      };
-
-      class scope_element_manager
-      {
-      public:
-
-         typedef variable_node_t* variable_node_ptr;
-         typedef parser<T> parser_t;
-
-         scope_element_manager(parser<T>& p)
-         : parser_(p),
-           input_param_cnt_(0)
-         {}
-
-         inline std::size_t size() const
-         {
-            return element_.size();
-         }
-
-         inline bool empty() const
-         {
-            return element_.empty();
-         }
-
-         inline scope_element& get_element(const std::size_t& index)
-         {
-            if (index < element_.size())
-               return element_[index];
-            else
-               return null_element_;
-         }
-
-         inline scope_element& get_element(const std::string& var_name,
-                                           const std::size_t index = std::numeric_limits<std::size_t>::max())
-         {
-            for (std::size_t i = 0; i < element_.size(); ++i)
+            
+        private:
+            
+            bov_node(const bov_node<T,Operation>&);
+            bov_node<T,Operation>& operator=(const bov_node<T,Operation>&);
+            
+            const T& v_;
+            branch_t branch_[1];
+        };
+        
+        template <typename T, typename Operation>
+        class cob_node : public cob_base_node<T>
+        {
+        public:
+            
+            typedef expression_node<T>* expression_ptr;
+            typedef std::pair<expression_ptr,bool> branch_t;
+            typedef Operation operation_t;
+            
+            // variable op constant node
+            explicit cob_node(const T const_var, const expression_ptr brnch)
+            : c_(const_var)
             {
-               scope_element& se = element_[i];
-
-               if (se.depth > parser_.scope_depth_)
-                  return null_element_;
-               else if (
-                         (se.name  == var_name) &&
-                         (se.index == index)
-                       )
-                  return se;
+                init_branches<1>(branch_,brnch);
             }
-
-            return null_element_;
-         }
-
-         inline bool add_element(const scope_element& se)
-         {
-            for (std::size_t j = 0; j < element_.size(); ++j)
-            {
-               if (
-                    (element_[j].name  == se.name ) &&
-                    (element_[j].depth <= se.depth) &&
-                    (element_[j].index == se.index) &&
-                    (element_[j].size  == se.size )
-                  )
-                  return false;
+            
+            ~cob_node()
+            {
+                cleanup_branches::execute<T,1>(branch_);
             }
-
-            element_.push_back(se);
-            std::sort(element_.begin(),element_.end());
-
-            return true;
-         }
-
-         inline void deactivate(const std::size_t& scope_depth)
-         {
-            for (std::size_t j = 0; j < element_.size(); ++j)
+            
+            inline T value() const
             {
-               if (element_[j].depth >= scope_depth)
-               {
-                  element_[j].active = false;
-               }
+                return Operation::process(c_,branch_[0].first->value());
             }
-         }
-
-         void cleanup()
-         {
-            for (std::size_t i = 0; i < element_.size(); ++i)
-            {
-               if (element_[i].var_node)
-               {
-                  delete element_[i].var_node;
-               }
-
-               if (element_[i].vec_node)
-               {
-                  delete element_[i].vec_node;
-               }
-
-               T* data = (T*)(element_[i].data);
-
-               switch (element_[i].type)
-               {
-                  case scope_element::e_variable : delete    data; break;
-                  case scope_element::e_vector   : delete [] data; break;
-                  default                        : break;
-               }
+            
+            inline operator_type operation() const
+            {
+                return Operation::operation();
             }
-
-            element_.clear();
-
-            input_param_cnt_ = 0;
-         }
-
-         inline std::size_t next_ip_index()
-         {
-            return ++input_param_cnt_;
-         }
-
-         inline variable_node_ptr get_variable(const T& v)
-         {
-            for (std::size_t i = 0; i < element_.size(); ++i)
+            
+            inline const T c() const
             {
-               scope_element& se = element_[i];
-
-               if (se.active && se.var_node)
-               {
-                  if (&se.var_node->ref() == (&v))
-                  {
-                     return se.var_node;
-                  }
-               }
+                return c_;
             }
-
-            return variable_node_ptr(0);
-         }
-
-      private:
-
-         scope_element_manager& operator=(const scope_element_manager&);
-
-         parser_t& parser_;
-         std::vector<scope_element> element_;
-         scope_element null_element_;
-         std::size_t input_param_cnt_;
-      };
-
-      class scope_handler
-      {
-      public:
-
-         typedef parser<T> parser_t;
-
-         scope_handler(parser<T>& p)
-         : parser_(p)
-         {
-            parser_.scope_depth_++;
-            #ifdef exprtk_enable_debugging
-            std::string depth(2 * parser_.scope_depth_,'-');
-            exprtk_debug(("%s> Scope Depth: %02d\n",depth.c_str(),static_cast<int>(parser_.scope_depth_)));
-            #endif
-         }
-
-        ~scope_handler()
-         {
-            parser_.scope_depth_--;
-            parser_.sem_.deactivate(parser_.scope_depth_);
-            #ifdef exprtk_enable_debugging
-            std::string depth(2 * parser_.scope_depth_,'-');
-            exprtk_debug(("<%s Scope Depth: %02d\n",depth.c_str(),static_cast<int>(parser_.scope_depth_)));
-            #endif
-         }
-
-      private:
-
-         scope_handler& operator=(const scope_handler&);
-
-         parser_t& parser_;
-      };
-
-   public:
-
-      enum compilation_options
-      {
-         e_unknown            =    0,
-         e_replacer           =    1,
-         e_joiner             =    2,
-         e_numeric_check      =    4,
-         e_bracket_check      =    8,
-         e_sequence_check     =   16,
-         e_commutative_check  =   32,
-         e_strength_reduction =   64,
-         e_disable_vardef     =  128,
-         e_collect_vars       =  256,
-         e_collect_funcs      =  512,
-         e_collect_assings    = 1024
-      };
-
-      struct unknown_symbol_resolver
-      {
-
-         enum usr_symbol_type
-         {
-            e_usr_variable_type = 0,
-            e_usr_constant_type = 1
-         };
-
-         virtual ~unknown_symbol_resolver()
-         {}
-
-         virtual bool process(const std::string& /*unknown_symbol*/,
-                              usr_symbol_type& st,
-                              T& default_value,
-                              std::string& error_message)
-         {
-            st = e_usr_variable_type;
-            default_value = T(0);
-            error_message = "";
-
-            return true;
-         }
-      };
-
-      enum collect_type
-      {
-         e_ct_none        = 0,
-         e_ct_variables   = 1,
-         e_ct_functions   = 2,
-         e_ct_assignments = 4
-      };
-
-      enum symbol_type
-      {
-         e_st_unknown        = 0,
-         e_st_variable       = 1,
-         e_st_vector         = 2,
-         e_st_string         = 3,
-         e_st_function       = 4,
-         e_st_local_variable = 5,
-         e_st_local_vector   = 6,
-         e_st_local_string   = 7
-      };
-
-      class dependent_entity_collector
-      {
-      public:
-
-         typedef std::pair<std::string,symbol_type> symbol_t;
-         typedef std::vector<symbol_t> symbol_list_t;
-
-         dependent_entity_collector(const std::size_t options = e_ct_none)
-         : options_(options),
-           collect_variables_  ((options_ & e_ct_variables  ) == e_ct_variables  ),
-           collect_functions_  ((options_ & e_ct_functions  ) == e_ct_functions  ),
-           collect_assignments_((options_ & e_ct_assignments) == e_ct_assignments)
-         {}
-
-         template <typename Allocator,
-                   template <typename,typename> class Sequence>
-         inline std::size_t symbols(Sequence<symbol_t,Allocator>& symbols_list)
-         {
-            if (!collect_variables_ && !collect_functions_)
-               return 0;
-            else if (symbol_name_list_.empty())
-               return 0;
-
-            for (std::size_t i = 0; i < symbol_name_list_.size(); ++i)
+            
+            inline void set_c(const T new_c)
             {
-               std::string& s = symbol_name_list_[i].first;
-               std::transform(s.begin(),s.end(),s.begin(),static_cast<int(*)(int)>(std::tolower));
+                (*const_cast<T*>(&c_)) = new_c;
             }
-
-            std::sort(symbol_name_list_.begin(),symbol_name_list_.end());
-            std::unique_copy(symbol_name_list_.begin(),
-                             symbol_name_list_.end(),
-                             std::back_inserter(symbols_list));
-
-            return symbols_list.size();
-         }
-
-         template <typename Allocator,
-                   template <typename,typename> class Sequence>
-         inline std::size_t assignment_symbols(Sequence<symbol_t,Allocator>& assignment_list)
-         {
-            if (!collect_assignments_)
-               return 0;
-            else if (assignment_name_list_.empty())
-               return 0;
-
-            for (std::size_t i = 0; i < assignment_name_list_.size(); ++i)
+            
+            inline expression_node<T>* branch(const std::size_t&) const
             {
-               std::string& s = assignment_name_list_[i].first;
-               std::transform(s.begin(),s.end(),s.begin(),static_cast<int(*)(int)>(std::tolower));
+                return branch_[0].first;
             }
-
-            std::sort(assignment_name_list_.begin(),assignment_name_list_.end());
-            std::unique_copy(assignment_name_list_.begin(),
-                             assignment_name_list_.end(),
-                             std::back_inserter(assignment_list));
-
-            return assignment_list.size();
-         }
-
-         void clear()
-         {
-            symbol_name_list_    .clear();
-            assignment_name_list_.clear();
-         }
-
-         bool& collect_variables()
-         {
-            return collect_variables_;
-         }
-
-         bool& collect_functions()
-         {
-            return collect_functions_;
-         }
-
-         bool& collect_assignments()
-         {
-            return collect_assignments_;
-         }
-
-      private:
-
-         inline void add_symbol(const std::string& symbol, const symbol_type st)
-         {
-            switch (st)
-            {
-               case e_st_variable       :
-               case e_st_vector         :
-               case e_st_string         :
-               case e_st_local_variable :
-               case e_st_local_vector   :
-               case e_st_local_string   :
-               case e_st_function       :
-                  if (collect_variables_ || collect_functions_)
-                     symbol_name_list_.push_back(std::make_pair(symbol,st));
-                  break;
-
-               default                  : return;
+            
+            inline expression_node<T>* move_branch(const std::size_t&)
+            {
+                branch_[0].second = false;
+                return branch_[0].first;
             }
-         }
-
-         inline void add_assignment(const std::string& symbol, const symbol_type st)
-         {
-            switch (st)
-            {
-               case e_st_variable       :
-               case e_st_vector         :
-               case e_st_string         :
-                  if (collect_assignments_)
-                     assignment_name_list_.push_back(std::make_pair(symbol,st));
-                  break;
-
-               default                  : return;
+            
+        private:
+            
+            cob_node(const cob_node<T,Operation>&);
+            cob_node<T,Operation>& operator=(const cob_node<T,Operation>&);
+            
+            const T c_;
+            branch_t branch_[1];
+        };
+        
+        template <typename T, typename Operation>
+        class boc_node : public boc_base_node<T>
+        {
+        public:
+            
+            typedef expression_node<T>* expression_ptr;
+            typedef std::pair<expression_ptr,bool> branch_t;
+            typedef Operation operation_t;
+            
+            // variable op constant node
+            explicit boc_node(const expression_ptr brnch, const T const_var)
+            : c_(const_var)
+            {
+                init_branches<1>(branch_,brnch);
             }
-         }
-
-         std::size_t options_;
-         bool collect_variables_;
-         bool collect_functions_;
-         bool collect_assignments_;
-         symbol_list_t symbol_name_list_;
-         symbol_list_t assignment_name_list_;
-
-         friend class parser<T>;
-      };
-
-      static const std::size_t compile_all_opts = e_replacer          +
-                                                  e_joiner            +
-                                                  e_numeric_check     +
-                                                  e_bracket_check     +
-                                                  e_sequence_check    +
-                                                  e_commutative_check +
-                                                  e_strength_reduction;
-
-      parser(const std::size_t compile_options = compile_all_opts)
-      : compile_options_(compile_options),
-        resolve_unknown_symbol_(false),
-        vardef_disabled_((compile_options & e_disable_vardef) == e_disable_vardef),
-        scope_depth_(0),
-        unknown_symbol_resolver_(reinterpret_cast<unknown_symbol_resolver*>(0)),
-        #ifdef _MSC_VER
-        #pragma warning(push)
-        #pragma warning (disable:4355)
-        #endif
-        sem_(*this),
-        #ifdef _MSC_VER
-        #pragma warning(pop)
-        #endif
-        operator_joiner_2_(2),
-        operator_joiner_3_(3)
-      {
-         init_precompilation();
-
-         load_operations_map(base_ops_map_);
-         load_unary_operations_map(unary_op_map_);
-         load_binary_operations_map(binary_op_map_);
-         load_inv_binary_operations_map(inv_binary_op_map_);
-         load_sf3_map(sf3_map_);
-         load_sf4_map(sf4_map_);
-
-         expression_generator_.init_synthesize_map();
-         expression_generator_.set_parser(*this);
-         expression_generator_.set_uom(unary_op_map_);
-         expression_generator_.set_bom(binary_op_map_);
-         expression_generator_.set_ibom(inv_binary_op_map_);
-         expression_generator_.set_sf3m(sf3_map_);
-         expression_generator_.set_sf4m(sf4_map_);
-         expression_generator_.set_strength_reduction_state(strength_reduction_enabled());
-      }
-
-     ~parser()
-      {}
-
-      inline void init_precompilation()
-      {
-         if (collect_variables_enabled())
-            dec_.collect_variables() = true;
-
-         if (collect_functions_enabled())
-            dec_.collect_functions() = true;
-
-         if (collect_assignments_enabled())
-            dec_.collect_assignments() = true;
-
-         if (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);
-            helper_assembly_.token_modifier_list.clear();
-            helper_assembly_.register_modifier(&symbol_replacer_);
-         }
-
-         if (commutative_check_enabled())
-         {
-            for (std::size_t i = 0; i < details::reserved_words_size; ++i)
+            
+            ~boc_node()
             {
-               commutative_inserter_.ignore_symbol(details::reserved_words[i]);
+                cleanup_branches::execute<T,1>(branch_);
             }
-
-            helper_assembly_.token_inserter_list.clear();
-            helper_assembly_.register_inserter(&commutative_inserter_);
-         }
-
-         if (joiner_enabled())
-         {
-            helper_assembly_.token_joiner_list.clear();
-            helper_assembly_.register_joiner(&operator_joiner_2_);
-            helper_assembly_.register_joiner(&operator_joiner_3_);
-         }
-
-         if (
-              numeric_check_enabled () ||
-              bracket_check_enabled () ||
-              sequence_check_enabled()
-            )
-         {
-            helper_assembly_.token_scanner_list.clear();
-
-            if (numeric_check_enabled())
+            
+            inline T value() const
             {
-               helper_assembly_.register_scanner(&numeric_checker_);
+                return Operation::process(branch_[0].first->value(),c_);
             }
-
-            if (bracket_check_enabled())
+            
+            inline operator_type operation() const
             {
-               helper_assembly_.register_scanner(&bracket_checker_);
+                return Operation::operation();
             }
-
-            if (sequence_check_enabled())
+            
+            inline const T c() const
             {
-               helper_assembly_.register_scanner(&sequence_validator_);
+                return c_;
             }
-         }
-      }
-
-      inline bool compile(const std::string& expression_string, expression<T>& expr)
-      {
-         error_list_     .clear();
-         brkcnt_list_    .clear();
-         synthesis_error_.clear();
-         sem_            .cleanup();
-
-         expression_generator_.set_allocator(node_allocator_);
-
-         scope_depth_ = 0;
-
-         if (expression_string.empty())
-         {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          "ERR00 - Empty expression!"));
-
-            return false;
-         }
-
-         if (!lexer_.process(expression_string))
-         {
-            process_lexer_errors();
-            return false;
-         }
-
-         if (lexer_.empty())
-         {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          "ERR01 - Empty expression!"));
-
-            return false;
-         }
-
-         if (!run_assemblies())
-         {
-            return false;
-         }
-
-         symbol_table_ = expr.get_symbol_table();
-         dec_.clear();
-
-         lexer_.begin();
-         next_token();
-
-         expression_node_ptr e = parse_corpus();
-
-         if ((0 != e) && (token_t::e_eof == current_token_.type))
-         {
-            expr.set_expression(e);
-            register_local_vars(expr);
-
-            return !(!expr);
-         }
-         else
-         {
-            if (error_list_.empty())
+            
+            inline void set_c(const T new_c)
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token_,
-                             "ERR02 - Invalid expression encountered"));
+                (*const_cast<T*>(&c_)) = new_c;
             }
-
-            dec_.clear  ();
-            sem_.cleanup();
-
-            if (0 != e)
+            
+            inline expression_node<T>* branch(const std::size_t&) const
             {
-               delete e;
+                return branch_[0].first;
             }
-
-            return false;
-         }
-      }
-
-      void process_lexer_errors()
-      {
-         for (std::size_t i = 0; i < lexer_.size(); ++i)
-         {
-            if (lexer_[i].is_error())
+            
+            inline expression_node<T>* move_branch(const std::size_t&)
             {
-               std::string diagnostic = "ERR03 - ";
-
-               switch (lexer_[i].type)
-               {
-                  case lexer::token::e_error      : diagnostic += "General token error";
-                                                    break;
-
-                  case lexer::token::e_err_symbol : diagnostic += "Symbol error";
-                                                    break;
-
-                  case lexer::token::e_err_number : diagnostic += "Invalid numeric token";
-                                                    break;
-
-                  case lexer::token::e_err_string : diagnostic += "Invalid string token";
-                                                    break;
-
-                  case lexer::token::e_err_sfunc  : diagnostic += "Invalid special function token";
-                                                    break;
-
-                  default                         : diagnostic += "Unknown compiler error";
-               }
-
-               set_error(
-                  make_error(parser_error::e_lexer,
-                             lexer_[i],
-                             diagnostic + ": " + lexer_[i].value));
+                branch_[0].second = false;
+                return branch_[0].first;
             }
-         }
-      }
-
-      inline bool replacer_enabled() const
-      {
-         return ((compile_options_ & e_replacer) == e_replacer);
-      }
-
-      inline bool commutative_check_enabled() const
-      {
-         return ((compile_options_ & e_commutative_check) == e_commutative_check);
-      }
-
-      inline bool joiner_enabled() const
-      {
-         return ((compile_options_ & e_joiner) == e_joiner);
-      }
-
-      inline bool numeric_check_enabled() const
-      {
-         return ((compile_options_ & e_numeric_check) == e_numeric_check);
-      }
-
-      inline bool bracket_check_enabled() const
-      {
-         return ((compile_options_ & e_bracket_check) == e_bracket_check);
-      }
-
-      inline bool sequence_check_enabled() const
-      {
-         return ((compile_options_ & e_sequence_check) == e_sequence_check);
-      }
-
-      inline bool strength_reduction_enabled() const
-      {
-         return ((compile_options_ & e_strength_reduction) == e_strength_reduction);
-      }
-
-      inline bool collect_variables_enabled() const
-      {
-         return ((compile_options_ & e_collect_vars) == e_collect_vars);
-      }
-
-      inline bool collect_functions_enabled() const
-      {
-         return ((compile_options_ & e_collect_funcs) == e_collect_funcs);
-      }
-
-      inline bool collect_assignments_enabled() const
-      {
-         return ((compile_options_ & e_collect_assings) == e_collect_assings);
-      }
-
-      inline bool run_assemblies()
-      {
-         if (commutative_check_enabled())
-         {
-            helper_assembly_.run_inserters(lexer_);
-         }
-
-         if (joiner_enabled())
-         {
-            helper_assembly_.run_joiners(lexer_);
-         }
-
-         if (replacer_enabled())
-         {
-            helper_assembly_.run_modifiers(lexer_);
-         }
-
-         if (
-              numeric_check_enabled () ||
-              bracket_check_enabled () ||
-              sequence_check_enabled()
-            )
-         {
-            if (!helper_assembly_.run_scanners(lexer_))
-            {
-               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;
-
-                  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(),
-                                   "ERR04 - Mismatched brackets: '" + bracket_checker_ptr->error_token().value + "'"));
-                  }
-                  else if (0 != (numeric_checker_ptr = dynamic_cast<lexer::helper::numeric_checker*>(helper_assembly_.error_token_scanner)))
-                  {
-                     for (std::size_t i = 0; i < numeric_checker_ptr->error_count(); ++i)
-                     {
-                        lexer::token error_token = lexer_[numeric_checker_ptr->error_index(i)];
-
-                        set_error(
-                           make_error(parser_error::e_token,
-                                      error_token,
-                                      "ERR05 - Invalid numeric token: '" + error_token.value + "'"));
-                     }
-
-                     if (numeric_checker_ptr->error_count())
-                     {
-                        numeric_checker_ptr->clear_errors();
-                     }
-                  }
-                  else if (0 != (sequence_validator_ptr = dynamic_cast<lexer::helper::sequence_validator*>(helper_assembly_.error_token_scanner)))
-                  {
-                     for (std::size_t i = 0; i < sequence_validator_ptr->error_count(); ++i)
-                     {
-                        std::pair<lexer::token,lexer::token> error_token = sequence_validator_ptr->error(i);
-
-                        set_error(
-                           make_error(parser_error::e_token,
-                                      error_token.first,
-                                      "ERR06 - Invalid token sequence: '" +
-                                      error_token.first.value  + "' and '" +
-                                      error_token.second.value + "'"));
-                     }
-
-                     if (sequence_validator_ptr->error_count())
-                     {
-                        sequence_validator_ptr->clear_errors();
-                     }
-                  }
-               }
-
-               return false;
+            
+        private:
+            
+            boc_node(const boc_node<T,Operation>&);
+            boc_node<T,Operation>& operator=(const boc_node<T,Operation>&);
+            
+            const T c_;
+            branch_t branch_[1];
+        };
+        
+#ifndef exprtk_disable_string_capabilities
+        template <typename T, typename SType0, typename SType1, typename Operation>
+        class sos_node : public sos_base_node<T>
+        {
+        public:
+            
+            typedef expression_node<T>* expression_ptr;
+            typedef Operation operation_t;
+            
+            // string op string node
+            explicit sos_node(SType0 p0, SType1 p1)
+            : s0_(p0),
+            s1_(p1)
+            {}
+            
+            inline T value() const
+            {
+                return Operation::process(s0_,s1_);
             }
-         }
-
-         return true;
-      }
-
-      inline parser_error::type get_error(const std::size_t& index)
-      {
-         if (index < error_list_.size())
-            return error_list_[index];
-         else
-            throw std::invalid_argument("parser::get_error() - Invalid error index specificed");
-      }
-
-      inline std::string error() const
-      {
-         if (!error_list_.empty())
-         {
-            return error_list_[0].diagnostic;
-         }
-         else
-            return std::string("No Error");
-      }
-
-      inline std::size_t error_count() const
-      {
-         return error_list_.size();
-      }
-
-      inline dependent_entity_collector& dec()
-      {
-         return dec_;
-      }
-
-      inline bool replace_symbol(const std::string& old_symbol, const std::string& new_symbol)
-      {
-         if (!replacer_enabled())
-            return false;
-         else if (details::is_reserved_word(old_symbol))
-            return false;
-         else
-            return symbol_replacer_.add_replace(old_symbol,new_symbol,lexer::token::e_symbol);
-      }
-
-      inline bool remove_replace_symbol(const std::string& symbol)
-      {
-         if (!replacer_enabled())
-            return false;
-         else if (details::is_reserved_word(symbol))
-            return false;
-         else
-            return symbol_replacer_.remove(symbol);
-      }
-
-      inline void enable_unknown_symbol_resolver(unknown_symbol_resolver* usr = reinterpret_cast<unknown_symbol_resolver*>(0))
-      {
-         resolve_unknown_symbol_ = true;
-
-         if (usr)
-            unknown_symbol_resolver_ = usr;
-         else
-            unknown_symbol_resolver_ = &default_usr_;
-      }
-
-      inline void disable_unknown_symbol_resolver()
-      {
-         resolve_unknown_symbol_  = false;
-         unknown_symbol_resolver_ = &default_usr_;
-      }
-
-   private:
-
-      inline bool valid_base_operation(const std::string& symbol)
-      {
-         const std::size_t length = symbol.size();
-         if (
-              (length < 3) || // Shortest base op symbol length
-              (length > 9)    // Longest base op symbol length
-            )
-            return false;
-         else
-            return (base_ops_map_.end() != base_ops_map_.find(symbol));
-      }
-
-      inline bool valid_vararg_operation(const std::string& symbol)
-      {
-         static const std::string s_sum     = "sum" ;
-         static const std::string s_mul     = "mul" ;
-         static const std::string s_avg     = "avg" ;
-         static const std::string s_min     = "min" ;
-         static const std::string s_max     = "max" ;
-         static const std::string s_mand    = "mand";
-         static const std::string s_mor     = "mor" ;
-         static const std::string s_multi   = "~"   ;
-         static const std::string s_mswitch = "[*]" ;
-         return
-               (
-                  details::imatch(symbol,s_sum    ) ||
-                  details::imatch(symbol,s_mul    ) ||
-                  details::imatch(symbol,s_avg    ) ||
-                  details::imatch(symbol,s_min    ) ||
-                  details::imatch(symbol,s_max    ) ||
-                  details::imatch(symbol,s_mand   ) ||
-                  details::imatch(symbol,s_mor    ) ||
-                  details::imatch(symbol,s_multi  ) ||
-                  details::imatch(symbol,s_mswitch)
-               );
-      }
-
-      inline void store_token()
-      {
-         lexer_.store();
-         store_current_token_ = current_token_;
-      }
-
-      inline void restore_token()
-      {
-         lexer_.restore();
-         current_token_ = store_current_token_;
-      }
-
-      #ifndef exprtk_enable_debugging
-      inline void next_token()
-      {
-         current_token_ = lexer_.next_token();
-      }
-      #else
-      inline void next_token()
-      {
-         std::string ct_str = current_token_.value;
-         current_token_ = lexer_.next_token();
-         std::string depth(2 * scope_depth_,' ');
-         exprtk_debug(("%s"
-                       "prev[%s] --> curr[%s]\n",
-                       depth.c_str(),
-                       ct_str.c_str(),
-                       current_token_.value.c_str()));
-      }
-      #endif
-
-      inline const lexer::token& current_token() const
-      {
-         return current_token_;
-      }
-
-      inline expression_node_ptr parse_corpus()
-      {
-         std::vector<expression_node_ptr> arg_list;
-         expression_node_ptr result = error_node();
-
-         scoped_vec_delete<expression_node_t> sdd(*this,arg_list);
-
-         for (;;)
-         {
-            expression_node_ptr arg = parse_expression();
-
-            if (0 == arg)
-            {
-               if (error_list_.empty())
-               {
-                  set_error(
-                     make_error(parser_error::e_syntax,
-                                current_token_,
-                                "ERR07 - Invalid expression encountered"));
-               }
-
-               return error_node();
+            
+            inline typename expression_node<T>::node_type type() const
+            {
+                return Operation::type();
             }
-            else
-               arg_list.push_back(arg);
-
-            if (lexer_.finished())
-               break;
-            else if (token_is(token_t::e_eof,false))
+            
+            inline operator_type operation() const
             {
-               if (lexer_.finished())
-                  break;
-               else
-                  next_token();
+                return Operation::operation();
             }
-         }
-
-         result = simplify(arg_list);
-
-         sdd.delete_ptr = (0 == result);
-         return result;
-      }
-
-      static const precedence_level default_precedence = e_level00;
-
-      struct state_t
-      {
-         inline void set(const precedence_level& l,
-                         const precedence_level& r,
-                         const details::operator_type& o)
-         {
-            left  = l;
-            right = r;
-            operation = o;
-         }
-
-         inline void reset()
-         {
-            left  = e_level00;
-            right = e_level00;
-         }
-
-         precedence_level left;
-         precedence_level right;
-         details::operator_type operation;
-      };
-
-      inline expression_node_ptr parse_expression(precedence_level precedence = e_level00)
-      {
-         expression_node_ptr expression = parse_branch(precedence);
-
-         if (0 == expression)
-         {
-            return error_node();
-         }
-
-         bool break_loop = false;
-
-         state_t current_state;
-
-         for ( ; ; )
-         {
-            current_state.reset();
-
-            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;
-               default                : if (token_t::e_symbol == current_token_.type)
-                                        {
-                                           static const std::string s_and   =   "and";
-                                           static const std::string s_nand  =  "nand";
-                                           static const std::string s_or    =    "or";
-                                           static const std::string s_nor   =   "nor";
-                                           static const std::string s_xor   =   "xor";
-                                           static const std::string s_xnor  =  "xnor";
-                                           static const std::string s_in    =    "in";
-                                           static const std::string s_like  =  "like";
-                                           static const std::string s_ilike = "ilike";
-                                           static const std::string s_and1  =     "&";
-                                           static const std::string s_or1   =     "|";
-
-                                           if (details::imatch(current_token_.value,s_and))
-                                           {
-                                              current_state.set(e_level01,e_level02,details::e_and);
-                                              break;
-                                           }
-                                           else if (details::imatch(current_token_.value,s_and1))
-                                           {
-                                              #ifndef exprtk_disable_sc_andor
-                                              current_state.set(e_level01,e_level02,details::e_scand);
-                                              #else
-                                              current_state.set(e_level01,e_level02,details::e_and);
-                                              #endif
-                                              break;
-                                           }
-                                           else if (details::imatch(current_token_.value,s_nand))
-                                           {
-                                              current_state.set(e_level01,e_level02,details::e_nand);
-                                              break;
-                                           }
-                                           else if (details::imatch(current_token_.value,s_or))
-                                           {
-                                              current_state.set(e_level03,e_level04,details::e_or);
-                                              break;
-                                           }
-                                           else if (details::imatch(current_token_.value,s_or1))
-                                           {
-                                              #ifndef exprtk_disable_sc_andor
-                                              current_state.set(e_level03,e_level04,details::e_scor);
-                                              #else
-                                              current_state.set(e_level03,e_level04,details::e_or);
-                                              #endif
-                                              break;
-                                           }
-                                           else if (details::imatch(current_token_.value,s_nor))
-                                           {
-                                              current_state.set(e_level03,e_level04,details::e_nor);
-                                              break;
-                                           }
-                                           else if (details::imatch(current_token_.value,s_xor))
-                                           {
-                                              current_state.set(e_level03,e_level04,details::e_xor);
-                                              break;
-                                           }
-                                           else if (details::imatch(current_token_.value,s_xnor))
-                                           {
-                                              current_state.set(e_level03,e_level04,details::e_xnor);
-                                              break;
-                                           }
-                                           else if (details::imatch(current_token_.value,s_in))
-                                           {
-                                              current_state.set(e_level03,e_level04,details::e_in);
-                                              break;
-                                           }
-                                           else if (details::imatch(current_token_.value,s_like))
-                                           {
-                                              current_state.set(e_level03,e_level04,details::e_like);
-                                              break;
-                                           }
-                                           else if (details::imatch(current_token_.value,s_ilike))
-                                           {
-                                              current_state.set(e_level03,e_level04,details::e_ilike);
-                                              break;
-                                           }
-                                        }
-
-                                        break_loop = true;
+            
+            inline std::string& s0()
+            {
+                return s0_;
             }
-
-            if (break_loop)
+            
+            inline std::string& s1()
             {
-               parse_pending_string_rangesize(expression);
-               break;
+                return s1_;
             }
-            else if (current_state.left < precedence)
-               break;
-
-            lexer::token prev_token = current_token_;
-
-            next_token();
-
-            expression_node_ptr right_branch   = error_node();
-            expression_node_ptr new_expression = error_node();
-
-            if ((right_branch = parse_expression(current_state.right)))
+            
+        protected:
+            
+            SType0 s0_;
+            SType1 s1_;
+            
+        private:
+            
+            sos_node(sos_node<T,SType0,SType1,Operation>&);
+            sos_node<T,SType0,SType1,Operation>& operator=(sos_node<T,SType0,SType1,Operation>&);
+        };
+        
+        template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation>
+        class str_xrox_node : public sos_base_node<T>
+        {
+        public:
+            
+            typedef expression_node<T>* expression_ptr;
+            typedef Operation operation_t;
+            
+            // string-range op string node
+            explicit str_xrox_node(SType0 p0, SType1 p1, RangePack rp0)
+            : s0_(p0),
+            s1_(p1),
+            rp0_(rp0)
+            {}
+            
+            ~str_xrox_node()
             {
-               new_expression = expression_generator_
-                                  (
-                                    current_state.operation,
-                                    expression,
-                                    right_branch
-                                  );
+                rp0_.free();
             }
-
-            if (0 == new_expression)
-            {
-               if (error_list_.empty())
-               {
-                  set_error(
-                     make_error(parser_error::e_syntax,
-                                prev_token,
-                                !synthesis_error_.empty() ?
-                                synthesis_error_ :
-                                "ERR08 - General parsing error at token: '" + prev_token.value + "'"));
-               }
-
-               free_node(node_allocator_,expression);
-
-               return error_node();
+            
+            inline T value() const
+            {
+                std::size_t r0 = 0;
+                std::size_t r1 = 0;
+                
+                if (rp0_(r0,r1,s0_.size()))
+                    return Operation::process(s0_.substr(r0,(r1 - r0) + 1),s1_);
+                else
+                    return T(0);
             }
-            else
+            
+            inline typename expression_node<T>::node_type type() const
             {
-               expression = new_expression;
-
-               if (token_is(token_t::e_ternary,false) && (precedence == e_level00))
-               {
-                  expression = parse_ternary_conditional_statement(expression);
-               }
-
-               parse_pending_string_rangesize(expression);
+                return Operation::type();
             }
-         }
-
-         return expression;
-      }
-
-      bool simplify_unary_negation_branch(expression_node_ptr& node)
-      {
-         {
-            typedef details::unary_branch_node<T,details::neg_op<T> > ubn_t;
-            ubn_t* n = dynamic_cast<ubn_t*>(node);
-
-            if (n)
+            
+            inline operator_type operation() const
             {
-               expression_node_ptr un_r = n->branch(0);
-               n->release();
-               free_node(node_allocator_,node);
-               node = un_r;
-
-               return true;
+                return Operation::operation();
             }
-         }
-
-         {
-            typedef details::unary_variable_node<T,details::neg_op<T> > ubn_t;
-
-            ubn_t* n = dynamic_cast<ubn_t*>(node);
-
-            if (n)
+            
+            inline std::string& s0()
             {
-               const T& v = n->v();
-               expression_node_ptr return_node = error_node();
-
-               if (
-                    (return_node = symbol_table_.get_variable(v)) ||
-                    (return_node = sem_         .get_variable(v))
-                  )
-               {
-                  free_node(node_allocator_,node);
-                  node = return_node;
-
-                  return true;
-               }
-               else
-               {
-                  set_error(
-                     make_error(parser_error::e_syntax,
-                                current_token_,
-                                "ERR09 - Failed to find variable node in symbol table"));
-                  free_node(node_allocator_,node);
-
-                  return false;
-               }
+                return s0_;
             }
-         }
-
-         return false;
-      }
-
-      static inline expression_node_ptr error_node()
-      {
-         return reinterpret_cast<expression_node_ptr>(0);
-      }
-
-      template <typename Type, std::size_t N>
-      struct scoped_delete
-      {
-         typedef Type* ptr_t;
-
-         scoped_delete(parser<T>& pr, ptr_t& p)
-         : delete_ptr(true),
-           parser_(pr),
-           p_(&p)
-         {}
-
-         scoped_delete(parser<T>& pr, ptr_t (&p)[N])
-         : delete_ptr(true),
-           parser_(pr),
-           p_(&p[0])
-         {}
-
-        ~scoped_delete()
-         {
-            if (delete_ptr)
+            
+            inline std::string& s1()
             {
-               for (std::size_t i = 0; i < N; ++i)
-               {
-                  free_node(parser_.node_allocator_,p_[i]);
-               }
+                return s1_;
             }
-         }
-
-         bool delete_ptr;
-         parser<T>& parser_;
-         ptr_t* p_;
-
-      private:
-
-         scoped_delete<Type,N>& operator=(const scoped_delete<Type,N>&);
-      };
-
-      template <typename Type>
-      struct scoped_deq_delete
-      {
-         typedef Type* ptr_t;
-
-         scoped_deq_delete(parser<T>& pr, std::deque<ptr_t>& deq)
-         : delete_ptr(true),
-           parser_(pr),
-           deq_(deq)
-         {}
-
-        ~scoped_deq_delete()
-         {
-            if (delete_ptr && !deq_.empty())
-            {
-               for (std::size_t i = 0; i < deq_.size(); ++i)
-               {
-                  free_node(parser_.node_allocator_,deq_[i]);
-               }
-
-               deq_.clear();
+            
+        protected:
+            
+            SType0    s0_;
+            SType1    s1_;
+            RangePack rp0_;
+            
+        private:
+            
+            str_xrox_node(str_xrox_node<T,SType0,SType1,RangePack,Operation>&);
+            str_xrox_node<T,SType0,SType1,RangePack,Operation>& operator=(str_xrox_node<T,SType0,SType1,RangePack,Operation>&);
+        };
+        
+        template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation>
+        class str_xoxr_node : public sos_base_node<T>
+        {
+        public:
+            
+            typedef expression_node<T>* expression_ptr;
+            typedef Operation operation_t;
+            
+            // string op string range node
+            explicit str_xoxr_node(SType0 p0, SType1 p1, RangePack rp1)
+            : s0_ (p0 ),
+            s1_ (p1 ),
+            rp1_(rp1)
+            {}
+            
+            ~str_xoxr_node()
+            {
+                rp1_.free();
             }
-         }
-
-         bool delete_ptr;
-         parser<T>& parser_;
-         std::deque<ptr_t>& deq_;
-
-      private:
-
-         scoped_deq_delete<Type>& operator=(const scoped_deq_delete<Type>&);
-      };
-
-      template <typename Type>
-      struct scoped_vec_delete
-      {
-         typedef Type* ptr_t;
-
-         scoped_vec_delete(parser<T>& pr, std::vector<ptr_t>& vec)
-         : delete_ptr(true),
-           parser_(pr),
-           vec_(vec)
-         {}
-
-        ~scoped_vec_delete()
-         {
-            if (delete_ptr && !vec_.empty())
-            {
-               for (std::size_t i = 0; i < vec_.size(); ++i)
-               {
-                  free_node(parser_.node_allocator_,vec_[i]);
-               }
-
-               vec_.clear();
+            
+            inline T value() const
+            {
+                std::size_t r0 = 0;
+                std::size_t r1 = 0;
+                
+                if (rp1_(r0,r1,s1_.size()))
+                    return Operation::process(s0_,s1_.substr(r0,(r1 - r0) + 1));
+                else
+                    return T(0);
             }
-         }
-
-         bool delete_ptr;
-         parser<T>& parser_;
-         std::vector<ptr_t>& vec_;
-
-      private:
-
-         scoped_vec_delete<Type>& operator=(const scoped_vec_delete<Type>&);
-      };
-
-      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);
-
-         switch (function->param_count)
-         {
-            case  0 : func_node = parse_function_call_0  (function,function_name); break;
-            case  1 : func_node = parse_function_call< 1>(function,function_name); break;
-            case  2 : func_node = parse_function_call< 2>(function,function_name); break;
-            case  3 : func_node = parse_function_call< 3>(function,function_name); break;
-            case  4 : func_node = parse_function_call< 4>(function,function_name); break;
-            case  5 : func_node = parse_function_call< 5>(function,function_name); break;
-            case  6 : func_node = parse_function_call< 6>(function,function_name); break;
-            case  7 : func_node = parse_function_call< 7>(function,function_name); break;
-            case  8 : func_node = parse_function_call< 8>(function,function_name); break;
-            case  9 : func_node = parse_function_call< 9>(function,function_name); break;
-            case 10 : func_node = parse_function_call<10>(function,function_name); break;
-            case 11 : func_node = parse_function_call<11>(function,function_name); break;
-            case 12 : func_node = parse_function_call<12>(function,function_name); break;
-            case 13 : func_node = parse_function_call<13>(function,function_name); break;
-            case 14 : func_node = parse_function_call<14>(function,function_name); break;
-            case 15 : func_node = parse_function_call<15>(function,function_name); break;
-            case 16 : func_node = parse_function_call<16>(function,function_name); break;
-            case 17 : func_node = parse_function_call<17>(function,function_name); break;
-            case 18 : func_node = parse_function_call<18>(function,function_name); break;
-            case 19 : func_node = parse_function_call<19>(function,function_name); break;
-            case 20 : func_node = parse_function_call<20>(function,function_name); break;
-            default : {
-                         set_error(
-                            make_error(parser_error::e_syntax,
-                                       current_token_,
-                                       "ERR10 - Invalid number of parameters for function: '" + function_name + "'"));
-
-                         return error_node();
-                      }
-         }
-
-         if (func_node)
-            return func_node;
-         else
-         {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token_,
-                          "ERR11 - Failed to generate call to function: '" + function_name + "'"));
-
-            return error_node();
-         }
-      }
-
-      template <std::size_t NumberofParameters>
-      inline expression_node_ptr parse_function_call(ifunction<T>* function, const std::string& function_name)
-      {
-         if (0 == NumberofParameters)
-         {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token_,
-                          "ERR12 - Expecting ifunction '" + function_name + "' to have non-zero parameter count"));
-
-            return error_node();
-         }
-
-         expression_node_ptr branch[NumberofParameters];
-         expression_node_ptr result  = error_node();
-
-         std::fill_n(branch,NumberofParameters,reinterpret_cast<expression_node_ptr>(0));
-         scoped_delete<expression_node_t,NumberofParameters> sd(*this,branch);
-
-         next_token();
-
-         if (!token_is(token_t::e_lbracket))
-         {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token_,
-                          "ERR13 - Expecting argument list for function: '" + function_name + "'"));
-
-            return error_node();
-         }
-
-         for (int i = 0; i < static_cast<int>(NumberofParameters); ++i)
-         {
-            branch[i] = parse_expression();
-
-            if (0 == branch[i])
+            
+            inline typename expression_node<T>::node_type type() const
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token_,
-                             "ERR14 - Failed to parse argument " + details::to_str(i) + " for function: '" + function_name + "'"));
-
-               return error_node();
+                return Operation::type();
             }
-            else if (i < static_cast<int>(NumberofParameters - 1))
+            
+            inline operator_type operation() const
             {
-               if (!token_is(token_t::e_comma))
-               {
-                  set_error(
-                     make_error(parser_error::e_syntax,
-                                current_token_,
-                                "ERR15 - Invalid number of arguments for function: '" + function_name + "'"));
-
-                  return error_node();
-               }
+                return Operation::operation();
             }
-         }
-
-         if (!token_is(token_t::e_rbracket))
-         {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token_,
-                          "ERR16 - Invalid number of arguments for function: '" + function_name + "'"));
-
-            return error_node();
-         }
-         else
-            result = expression_generator_.function(function,branch);
-
-         sd.delete_ptr = false;
-
-         return result;
-      }
-
-      inline expression_node_ptr parse_function_call_0(ifunction<T>* function, const std::string& function_name)
-      {
-         expression_node_ptr result = expression_generator_.function(function);
-         next_token();
-         if (
-               token_is(token_t::e_lbracket) &&
-              !token_is(token_t::e_rbracket)
-            )
-         {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token_,
-                          "ERR17 - Expecting '()' to proceed call to function: '" + function_name + "'"));
-
-            free_node(node_allocator_,result);
-
-            return error_node();
-         }
-         else
-            return result;
-      }
-
-      template <std::size_t MaxNumberofParameters>
-      inline int parse_base_function_call(expression_node_ptr (&param_list)[MaxNumberofParameters])
-      {
-         std::fill_n(param_list,MaxNumberofParameters,reinterpret_cast<expression_node_ptr>(0));
-
-         scoped_delete<expression_node_t,MaxNumberofParameters> sd(*this,param_list);
-
-         next_token();
-
-         if (!token_is(token_t::e_lbracket))
-         {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token_,
-                          "ERR18 - Expected a '(' at start of function call, instead got: '" + current_token_.value + "'"));
-
-            return 0;
-         }
-
-         int param_index = 0;
-
-         for (; param_index < static_cast<int>(MaxNumberofParameters); ++param_index)
-         {
-            param_list[param_index] = parse_expression();
-
-            if (0 == param_list[param_index])
+            
+            inline std::string& s0()
             {
-               return 0;
+                return s0_;
             }
-            else if (token_is(token_t::e_rbracket))
-               break;
-            else if (token_is(token_t::e_comma))
-               continue;
-            else
+            
+            inline std::string& s1()
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token_,
-                             "ERR19 - Expected a ',' between function input parameters, instead got: '" + current_token_.value + "'"));
-
-               return 0;
+                return s1_;
             }
-         }
-
-         sd.delete_ptr = false;
-
-         return (param_index + 1);
-      }
-
-      inline expression_node_ptr parse_base_operation()
-      {
-         typedef std::pair<base_ops_map_t::iterator,base_ops_map_t::iterator> map_range_t;
-
-         const std::string operation_name = current_token_.value;
-         map_range_t itr_range = base_ops_map_.equal_range(operation_name);
-
-         if (0 == std::distance(itr_range.first,itr_range.second))
-         {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token_,
-                          "ERR20 - No entry found for base operation: " + operation_name));
-
-            return error_node();
-         }
-
-         const std::size_t MaxNumberofParameters = 6;
-         expression_node_ptr param_list[MaxNumberofParameters] = {0};
-
-         std::size_t parameter_count = parse_base_function_call(param_list);
-
-         if (0 == parameter_count)
-         {
-            return error_node();
-         }
-         else if (parameter_count <= 6)
-         {
-            for (base_ops_map_t::iterator itr = itr_range.first; itr != itr_range.second; ++itr)
+            
+        protected:
+            
+            SType0    s0_;
+            SType1    s1_;
+            RangePack rp1_;
+            
+        private:
+            
+            str_xoxr_node(str_xoxr_node<T,SType0,SType1,RangePack,Operation>&);
+            str_xoxr_node<T,SType0,SType1,RangePack,Operation>& operator=(str_xoxr_node<T,SType0,SType1,RangePack,Operation>&);
+        };
+        
+        template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation>
+        class str_xroxr_node : public sos_base_node<T>
+        {
+        public:
+            
+            typedef expression_node<T>* expression_ptr;
+            typedef Operation operation_t;
+            
+            // string-range op string-range node
+            explicit str_xroxr_node(SType0 p0, SType1 p1, RangePack rp0, RangePack rp1)
+            : s0_ (p0 ),
+            s1_ (p1 ),
+            rp0_(rp0),
+            rp1_(rp1)
+            {}
+            
+            ~str_xroxr_node()
+            {
+                rp0_.free();
+                rp1_.free();
+            }
+            
+            inline T value() const
+            {
+                std::size_t r0_0 = 0;
+                std::size_t r0_1 = 0;
+                std::size_t r1_0 = 0;
+                std::size_t r1_1 = 0;
+                if (
+                    rp0_(r0_0,r1_0,s0_.size()) &&
+                    rp1_(r0_1,r1_1,s1_.size())
+                    )
+                {
+                    return Operation::process(
+                                              s0_.substr(r0_0,(r1_0 - r0_0) + 1),
+                                              s1_.substr(r0_1,(r1_1 - r0_1) + 1)
+                                              );
+                }
+                else
+                    return T(0);
+            }
+            
+            inline typename expression_node<T>::node_type type() const
+            {
+                return Operation::type();
+            }
+            
+            inline operator_type operation() const
+            {
+                return Operation::operation();
+            }
+            
+            inline std::string& s0()
+            {
+                return s0_;
+            }
+            
+            inline std::string& s1()
+            {
+                return s1_;
+            }
+            
+        protected:
+            
+            SType0    s0_;
+            SType1    s1_;
+            RangePack rp0_;
+            RangePack rp1_;
+            
+        private:
+            
+            str_xroxr_node(str_xroxr_node<T,SType0,SType1,RangePack,Operation>&);
+            str_xroxr_node<T,SType0,SType1,RangePack,Operation>& operator=(str_xroxr_node<T,SType0,SType1,RangePack,Operation>&);
+        };
+        
+        template <typename T, typename Operation>
+        class str_sogens_node : public binary_node<T>
+        {
+        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;
+            
+            str_sogens_node(const operator_type& opr,
+                            expression_ptr branch0,
+                            expression_ptr branch1)
+            : binary_node<T>(opr,branch0,branch1),
+            str0_base_ptr_ (0),
+            str1_base_ptr_ (0),
+            str0_range_ptr_(0),
+            str1_range_ptr_(0)
+            {
+                if (is_generally_string_node(binary_node<T>::branch_[0].first))
+                {
+                    str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
+                    
+                    if (0 == str0_base_ptr_)
+                        return;
+                    
+                    irange_ptr range_ptr = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first);
+                    
+                    if (0 == range_ptr)
+                        return;
+                    
+                    str0_range_ptr_ = &(range_ptr->range_ref());
+                }
+                
+                if (is_generally_string_node(binary_node<T>::branch_[1].first))
+                {
+                    str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);
+                    
+                    if (0 == str1_base_ptr_)
+                        return;
+                    
+                    irange_ptr range_ptr = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
+                    
+                    if (0 == range_ptr)
+                        return;
+                    
+                    str1_range_ptr_ = &(range_ptr->range_ref());
+                }
+            }
+            
+            inline T value() const
+            {
+                if (
+                    str0_base_ptr_  &&
+                    str1_base_ptr_  &&
+                    str0_range_ptr_ &&
+                    str1_range_ptr_
+                    )
+                {
+                    binary_node<T>::branch_[0].first->value();
+                    binary_node<T>::branch_[1].first->value();
+                    
+                    std::size_t str0_r0 = 0;
+                    std::size_t str0_r1 = 0;
+                    
+                    std::size_t str1_r0 = 0;
+                    std::size_t str1_r1 = 0;
+                    
+                    range_t& range0 = (*str0_range_ptr_);
+                    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())
+                        )
+                    {
+                        return Operation::process(
+                                                  str0_base_ptr_->str().substr(str0_r0,(str0_r1 - str0_r0) + 1),
+                                                  str1_base_ptr_->str().substr(str1_r0,(str1_r1 - str1_r0) + 1)
+                                                  );
+                    }
+                }
+                
+                return std::numeric_limits<T>::quiet_NaN();
+            }
+            
+            inline typename expression_node<T>::node_type type() const
+            {
+                return Operation::type();
+            }
+            
+            inline operator_type operation() const
+            {
+                return Operation::operation();
+            }
+            
+        private:
+            
+            str_sogens_node(str_sogens_node<T,Operation>&);
+            str_sogens_node<T,Operation>& operator=(str_sogens_node<T,Operation>&);
+            
+            str_base_ptr str0_base_ptr_;
+            str_base_ptr str1_base_ptr_;
+            range_ptr    str0_range_ptr_;
+            range_ptr    str1_range_ptr_;
+        };
+        
+        template <typename T, typename SType0, typename SType1, typename SType2, typename Operation>
+        class sosos_node : public sosos_base_node<T>
+        {
+        public:
+            
+            typedef expression_node<T>* expression_ptr;
+            typedef Operation operation_t;
+            
+            // variable op variable node
+            explicit sosos_node(SType0 p0, SType1 p1, SType2 p2)
+            : s0_(p0),
+            s1_(p1),
+            s2_(p2)
+            {}
+            
+            inline T value() const
             {
-               details::base_operation_t& operation = itr->second;
-
-               if (operation.num_params == parameter_count)
-               {
-                  switch (parameter_count)
-                  {
-                     #define base_opr_case(N)                                       \
-                     case N : {                                                     \
-                                 expression_node_ptr pl##N[N] = {0};                \
-                                 std::copy(param_list,param_list + N,pl##N);        \
-                                 lodge_symbol(operation_name,e_st_function);        \
-                                 return expression_generator_(operation.type,pl##N);\
-                              }                                                     \
-
-                     base_opr_case(1)
-                     base_opr_case(2)
-                     base_opr_case(3)
-                     base_opr_case(4)
-                     base_opr_case(5)
-                     base_opr_case(6)
-                     #undef base_opr_case
-                  }
-               }
-            }
-         }
-
-         for (std::size_t i = 0; i < MaxNumberofParameters; ++i)
-         {
-            free_node(node_allocator_,param_list[i]);
-         }
-
-         set_error(
-            make_error(parser_error::e_syntax,
-                       current_token_,
-                       "ERR21 - Invalid number of parameters for call to function: '" + operation_name + "'"));
-
-         return error_node();
-      }
-
-      inline expression_node_ptr parse_conditional_statement_01(expression_node_ptr condition)
-      {
-         // Parse: [if][(][condition][,][consequent][,][alternative][)]
-
-         expression_node_ptr consequent  = error_node();
-         expression_node_ptr alternative = error_node();
-
-         bool result = true;
-
-         if (!token_is(token_t::e_comma))
-         {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token_,
-                          "ERR22 - Expected ',' between if-statement condition and consequent"));
-            result = false;
-         }
-         else if (0 == (consequent = parse_expression()))
-         {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token_,
-                          "ERR23 - Failed to parse consequent for if-statement"));
-            result = false;
-         }
-         else if (!token_is(token_t::e_comma))
-         {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token_,
-                          "ERR24 - Expected ',' between if-statement consequent and alternative"));
-            result = false;
-         }
-         else if (0 == (alternative = parse_expression()))
-         {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token_,
-                          "ERR25 - Failed to parse alternative for if-statement"));
-            result = false;
-         }
-         else if (!token_is(token_t::e_rbracket))
-         {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token_,
-                          "ERR26 - Expected ')' at the end of if-statement"));
-            result = false;
-         }
-
-         if (!result)
-         {
-            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);
-      }
-
-      inline expression_node_ptr parse_conditional_statement_02(expression_node_ptr condition)
-      {
-         expression_node_ptr consequent  = error_node();
-         expression_node_ptr alternative = error_node();
-
-         bool result = true;
-
-         if (token_is(token_t::e_lcrlbracket,false))
-         {
-            if (0 == (consequent = parse_multi_sequence("if-statement-01")))
-            {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token_,
-                             "ERR27 - Failed to parse body of consequent for if-statement"));
-               result = false;
-            }
-         }
-         else
-         {
-            if (
-                 commutative_check_enabled() &&
-                 token_is(token_t::e_mul,false)
-               )
+                return Operation::process(s0_,s1_,s2_);
+            }
+            
+            inline typename expression_node<T>::node_type type() const
             {
-               next_token();
+                return Operation::type();
             }
-
-            if (0 != (consequent = parse_expression()))
+            
+            inline operator_type operation() const
             {
-               if (!token_is(token_t::e_eof))
-               {
-                  set_error(
-                     make_error(parser_error::e_syntax,
-                                current_token_,
-                                "ERR28 - Expected ';' at the end of the consequent for if-statement"));
-                  result = false;
-               }
+                return Operation::operation();
             }
-            else
+            
+            inline std::string& s0()
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token_,
-                             "ERR29 - Failed to parse body of consequent for if-statement"));
-               result = false;
+                return s0_;
             }
-         }
-
-         if (result)
-         {
-            if (details::imatch(current_token_.value,"else"))
+            
+            inline std::string& s1()
             {
-               next_token();
-
-               if (token_is(token_t::e_lcrlbracket,false))
-               {
-                  if (0 == (alternative = parse_multi_sequence("else-statement-01")))
-                  {
-                     set_error(
-                        make_error(parser_error::e_syntax,
-                                   current_token_,
-                                   "ERR30 - Failed to parse body of the 'else' for if-statement"));
-                     result = false;
-                  }
-               }
-               else if (details::imatch(current_token_.value,"if"))
-               {
-                  if (0 == (alternative = parse_conditional_statement()))
-                  {
-                     set_error(
-                        make_error(parser_error::e_syntax,
-                                   current_token_,
-                                   "ERR31 - Failed to parse body of if-else statement"));
-                     result = false;
-                  }
-               }
-               else if (0 != (alternative = parse_expression()))
-               {
-                  if (!token_is(token_t::e_eof))
-                  {
-                     set_error(
-                        make_error(parser_error::e_syntax,
-                                   current_token_,
-                                   "ERR32 - Expected ';' at the end of the 'else-if' for the if-statement"));
-                     result = false;
-                  }
-               }
-               else
-               {
-                  set_error(
-                     make_error(parser_error::e_syntax,
-                                current_token_,
-                                "ERR33 - Failed to parse body of the 'else' for if-statement"));
-                  result = false;
-               }
-            }
-         }
-
-         if (!result)
-         {
-            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);
-      }
-
-      inline expression_node_ptr parse_conditional_statement()
-      {
-         expression_node_ptr condition   = error_node();
-
-         next_token();
-
-         if (!token_is(token_t::e_lbracket))
-         {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token_,
-                          "ERR34 - Expected '(' at start of if-statement, instead got: '" + current_token_.value + "'"));
-
-            return error_node();
-         }
-         else if (0 == (condition = parse_expression()))
-         {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token_,
-                          "ERR35 - Failed to parse condition for if-statement"));
-
-            return error_node();
-         }
-         else if (token_is(token_t::e_comma,false))
-         {
-            // if (x,y,z)
-            return parse_conditional_statement_01(condition);
-         }
-         else if (token_is(token_t::e_rbracket))
-         {
-            // 00. if (x) y;
-            // 01. if (x) y; else z;
-            // 02. if (x) y; else {z0; ... zn;}
-            // 03. if (x) y; else if (z) w;
-            // 04. if (x) y; else if (z) w; else u;
-            // 05. if (x) y; else if (z) w; else {u0; ... un;}
-            // 06. if (x) y; else if (z) {w0; ... wn;}
-            // 07. if (x) {y0; ... yn;}
-            // 08. if (x) {y0; ... yn;} else z;
-            // 09. if (x) {y0; ... yn;} else {z0; ... zn;};
-            // 10. if (x) {y0; ... yn;} else if (z) w;
-            // 11. if (x) {y0; ... yn;} else if (z) w; else u;
-            // 12. if (x) {y0; ... nex;} else if (z) w; else {u0 ... un;}
-            // 13. if (x) {y0; ... yn;} else if (z) {w0; ... wn;}
-            return parse_conditional_statement_02(condition);
-         }
-
-         set_error(
-            make_error(parser_error::e_syntax,
-                       current_token_,
-                       "ERR36 - Invalid if-statement"));
-
-         free_node(node_allocator_,condition);
-
-         return error_node();
-      }
-
-      inline expression_node_ptr parse_ternary_conditional_statement(expression_node_ptr condition)
-      {
-         // Parse: [condition][?][consequent][:][alternative]
-         expression_node_ptr consequent  = error_node();
-         expression_node_ptr alternative = error_node();
-
-         bool result = true;
-
-         if (0 == condition)
-         {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token_,
-                          "ERR37 - Encountered invalid condition branch for ternary if-statement"));
-
-            return error_node();
-         }
-         else if (!token_is(token_t::e_ternary))
-         {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token_,
-                          "ERR38 - Expected '?' after condition of ternary if-statement"));
-
-            result = false;
-         }
-         else if (0 == (consequent = parse_expression()))
-         {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token_,
-                          "ERR39 - Failed to parse consequent for if-statement"));
-
-            result = false;
-         }
-         else if (!token_is(token_t::e_colon))
-         {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token_,
-                          "ERR40 - Expected ':' between ternary if-statement consequent and alternative"));
-
-            result = false;
-         }
-         else if (0 == (alternative = parse_expression()))
-         {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token_,
-                          "ERR41 - Failed to parse alternative for if-statement"));
-
-            result = false;
-         }
-
-         if (!result)
-         {
-            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);
-      }
-
-      inline expression_node_ptr parse_while_loop()
-      {
-         // Parse: [while][(][test expr][)][{][expression][}]
-         expression_node_ptr condition   = error_node();
-         expression_node_ptr branch      = error_node();
-         expression_node_ptr result_node = error_node();
-
-         bool result = true;
-
-         next_token();
-
-         if (!token_is(token_t::e_lbracket))
-         {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token_,
-                          "ERR42 - Expected '(' at start of while-loop condition statement"));
-
-            return error_node();
-         }
-         else if (0 == (condition = parse_expression()))
-         {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token_,
-                          "ERR43 - Failed to parse condition for while-loop"));
-
-            return error_node();
-         }
-         else if (!token_is(token_t::e_rbracket))
-         {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token_,
-                          "ERR44 - Expected ')' at end of while-loop condition statement"));
-            result = false;
-         }
-
-         brkcnt_list_.push_front(false);
-
-         if (result)
-         {
-            if (0 == (branch = parse_multi_sequence("while-loop")))
-            {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token_,
-                             "ERR45 - Failed to parse body of while-loop"));
-               result = false;
-            }
-            else if (0 == (result_node = expression_generator_.while_loop(condition,
-                                                                          branch,
-                                                                          brkcnt_list_.front())))
-            {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token_,
-                             "ERR46 - Failed to synthesize while-loop"));
-               result = false;
-            }
-         }
-
-         if (!result)
-         {
-            free_node(node_allocator_,     branch);
-            free_node(node_allocator_,  condition);
-            free_node(node_allocator_,result_node);
-
-            brkcnt_list_.pop_front();
-
-            return error_node();
-         }
-         else
-            return result_node;
-      }
-
-      inline expression_node_ptr parse_repeat_until_loop()
-      {
-         // Parse: [repeat][{][expression][}][until][(][test expr][)]
-         expression_node_ptr condition = error_node();
-         expression_node_ptr branch    = error_node();
-         next_token();
-
-         std::vector<expression_node_ptr> arg_list;
-         scoped_vec_delete<expression_node_t> sdd(*this,arg_list);
-
-         brkcnt_list_.push_front(false);
-
-         if (details::imatch(current_token_.value,"until"))
-         {
-            next_token();
-            branch = node_allocator_.allocate<details::null_node<T> >();
-         }
-         else
-         {
-            token_t::token_type seperator = token_t::e_eof;
-
-            scope_handler sh(*this);
-
-            for (;;)
+                return s1_;
+            }
+            
+            inline std::string& s2()
             {
-               expression_node_ptr arg = parse_expression();
-
-               if (0 == arg)
-                  return error_node();
-               else
-                  arg_list.push_back(arg);
-
-               if (details::imatch(current_token_.value,"until"))
-               {
-                  next_token();
-                  break;
-               }
-
-               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_,
-                                "ERR47 - Expected '" + token_t::to_str(seperator) + "' for body of repeat until loop"));
-
-                  return error_node();
-               }
-
-               if (details::imatch(current_token_.value,"until"))
-               {
-                  next_token();
-                  break;
-               }
+                return s2_;
             }
-
-            branch = simplify(arg_list);
-
-            if ((sdd.delete_ptr = (0 == branch)))
+            
+        protected:
+            
+            SType0 s0_;
+            SType1 s1_;
+            SType2 s2_;
+            
+        private:
+            
+            sosos_node(sosos_node<T,SType0,SType1,SType2,Operation>&);
+            sosos_node<T,SType0,SType1,SType2,Operation>& operator=(sosos_node<T,SType0,SType1,SType2,Operation>&);
+        };
+#endif
+        
+        template <typename T, typename PowOp>
+        class ipow_node : public expression_node<T>
+        {
+        public:
+            
+            typedef expression_node<T>* expression_ptr;
+            typedef PowOp operation_t;
+            
+            explicit ipow_node(const T& v)
+            : v_(v)
+            {}
+            
+            inline T value() const
             {
-               brkcnt_list_.pop_front();
-
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token_,
-                             "ERR48 - Failed to parse body of repeat until loop"));
-
-               return error_node();
+                return PowOp::result(v_);
             }
-         }
-
-         if (!token_is(token_t::e_lbracket))
-         {
-            brkcnt_list_.pop_front();
-
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token_,
-                          "ERR49 - Expected '(' before condition statement of repeat until loop"));
-
-            free_node(node_allocator_,branch);
-
-            return error_node();
-         }
-         else if (0 == (condition = parse_expression()))
-         {
-            brkcnt_list_.pop_front();
-
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token_,
-                          "ERR50 - Failed to parse condition for repeat until loop"));
-
-            free_node(node_allocator_,branch);
-
-            return error_node();
-         }
-         else if (!token_is(token_t::e_rbracket))
-         {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token_,
-                          "ERR51 - Expected ')' after condition of repeat until loop"));
-
-            free_node(node_allocator_,    branch);
-            free_node(node_allocator_, condition);
-
-            brkcnt_list_.pop_front();
-
-            return error_node();
-         }
-
-         expression_node_ptr result;
-
-         result = expression_generator_
-                     .repeat_until_loop(condition,branch,brkcnt_list_.front());
-
-         if (0 == result)
-         {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token_,
-                          "ERR52 - Failed to synthesize repeat until loop"));
-
-            free_node(node_allocator_, condition);
-            brkcnt_list_.pop_front();
-
-            return error_node();
-         }
-         else
-         {
-            brkcnt_list_.pop_front();
-            return result;
-         }
-      }
-
-      inline expression_node_ptr parse_for_loop()
-      {
-         expression_node_ptr initialiser = error_node();
-         expression_node_ptr condition   = error_node();
-         expression_node_ptr incrementor = error_node();
-         expression_node_ptr loop_body   = error_node();
-
-         scope_element* se = 0;
-         bool result       = true;
-         std::string loop_counter_symbol;
-
-         next_token();
-
-         scope_handler sh(*this);
-
-         if (!token_is(token_t::e_lbracket))
-         {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token_,
-                          "ERR53 - Expected '(' at start of for-loop"));
-
-            return error_node();
-         }
-
-         if (!token_is(token_t::e_eof))
-         {
-            if (
-                 !token_is(token_t::e_symbol,false) &&
-                 details::imatch(current_token_.value,"var")
-               )
+            
+            inline typename expression_node<T>::node_type type() const
             {
-               next_token();
-
-               if (!token_is(token_t::e_symbol,false))
-               {
-                  set_error(
-                     make_error(parser_error::e_syntax,
-                                current_token_,
-                                "ERR54 - Expected a variable at the start of initialiser section of for-loop"));
-
-                  return error_node();
-               }
-               else if (!peek_token_is(token_t::e_assign))
-               {
-                  set_error(
-                     make_error(parser_error::e_syntax,
-                                current_token_,
-                                "ERR55 - Expected variable assignment of initialiser section of for-loop"));
-
-                  return error_node();
-               }
-
-               loop_counter_symbol = current_token_.value;
-
-               se = &sem_.get_element(loop_counter_symbol);
-
-               if ((se->name == loop_counter_symbol) && se->active)
-               {
-                  set_error(
-                     make_error(parser_error::e_syntax,
-                                current_token_,
-                                "ERR56 - For-loop variable '" + loop_counter_symbol+ "' is being shadowed by a previous declaration"));
-
-                  return error_node();
-               }
-               else if (!symbol_table_.is_variable(loop_counter_symbol))
-               {
-                  if (
-                       !se->active &&
-                       (se->name == loop_counter_symbol) &&
-                       (se->type ==  scope_element::e_variable)
-                     )
-                  {
-                     se->active = true;
-                     se->ref_count++;
-                  }
-                  else
-                  {
-                     scope_element nse;
-                     nse.name     = loop_counter_symbol;
-                     nse.type     = scope_element::e_variable;
-                     nse.depth    = scope_depth_;
-                     nse.data     = new T(T(0));
-                     nse.var_node = new variable_node_t(*(T*)(nse.data));
-
-                     if (!sem_.add_element(nse))
-                     {
-                        set_error(
-                           make_error(parser_error::e_syntax,
-                                      current_token_,
-                                      "ERR57 - Failed to add new local variable '" + loop_counter_symbol + "' to SEM"));
-
-                        result = false;
-
-                     }
-                     else
-                        exprtk_debug(("parse_for_loop() - INFO - Added new local variable: %s\n",nse.name.c_str()));
-                  }
-               }
+                return expression_node<T>::e_ipow;
             }
-
-            if (0 == (initialiser = parse_expression()))
+            
+        private:
+            
+            ipow_node(const ipow_node<T,PowOp>&);
+            ipow_node<T,PowOp>& operator=(const ipow_node<T,PowOp>&);
+            
+            const T& v_;
+        };
+        
+        template <typename T, typename PowOp>
+        class bipow_node : public expression_node<T>
+        {
+        public:
+            
+            typedef expression_node<T>* expression_ptr;
+            typedef std::pair<expression_ptr, bool> branch_t;
+            typedef PowOp operation_t;
+            
+            explicit bipow_node(expression_ptr brnch)
+            {
+                init_branches<1>(branch_, brnch);
+            }
+            
+            ~bipow_node()
+            {
+                cleanup_branches::execute<T,1>(branch_);
+            }
+            
+            inline T value() const
+            {
+                return PowOp::result(branch_[0].first->value());
+            }
+            
+            inline typename expression_node<T>::node_type type() const
+            {
+                return expression_node<T>::e_ipow;
+            }
+            
+        private:
+            
+            bipow_node(const bipow_node<T,PowOp>&);
+            bipow_node<T,PowOp>& operator=(const bipow_node<T,PowOp>&);
+            
+            branch_t branch_[1];
+        };
+        
+        template <typename T, typename PowOp>
+        class ipowinv_node : public expression_node<T>
+        {
+        public:
+            
+            typedef expression_node<T>* expression_ptr;
+            typedef PowOp operation_t;
+            
+            explicit ipowinv_node(const T& v)
+            : v_(v)
+            {}
+            
+            inline T value() const
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token_,
-                             "ERR58 - Failed to parse initialiser of for-loop"));
-               result = false;
+                return (T(1) / PowOp::result(v_));
             }
-
-            if (!token_is(token_t::e_eof))
+            
+            inline typename expression_node<T>::node_type type() const
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token_,
-                             "ERR59 - Expected ';' after initialiser of for-loop"));
-               result = false;
+                return expression_node<T>::e_ipowinv;
             }
-         }
-
-         if (!token_is(token_t::e_eof))
-         {
-            if (0 == (condition = parse_expression()))
+            
+        private:
+            
+            ipowinv_node(const ipowinv_node<T,PowOp>&);
+            ipowinv_node<T,PowOp>& operator=(const ipowinv_node<T,PowOp>&);
+            
+            const T& v_;
+        };
+        
+        template <typename T, typename PowOp>
+        class bipowninv_node : public expression_node<T>
+        {
+        public:
+            
+            typedef expression_node<T>* expression_ptr;
+            typedef std::pair<expression_ptr, bool> branch_t;
+            typedef PowOp operation_t;
+            
+            explicit bipowninv_node(expression_ptr brnch)
+            {
+                init_branches<1>(branch_, brnch);
+            }
+            
+            ~bipowninv_node()
+            {
+                cleanup_branches::execute<T,1>(branch_);
+            }
+            
+            inline T value() const
+            {
+                return (T(1) / PowOp::result(branch_[0].first->value()));
+            }
+            
+            inline typename expression_node<T>::node_type type() const
+            {
+                return expression_node<T>::e_ipowinv;
+            }
+            
+        private:
+            
+            bipowninv_node(const bipowninv_node<T,PowOp>&);
+            bipowninv_node<T,PowOp>& operator=(const bipowninv_node<T,PowOp>&);
+            
+            branch_t branch_[1];
+        };
+        
+        template <typename T>
+        inline bool is_vov_node(const expression_node<T>* node)
+        {
+            return (0 != dynamic_cast<const vov_base_node<T>*>(node));
+        }
+        
+        template <typename T>
+        inline bool is_cov_node(const expression_node<T>* node)
+        {
+            return (0 != dynamic_cast<const cov_base_node<T>*>(node));
+        }
+        
+        template <typename T>
+        inline bool is_voc_node(const expression_node<T>* node)
+        {
+            return (0 != dynamic_cast<const voc_base_node<T>*>(node));
+        }
+        
+        template <typename T>
+        inline bool is_cob_node(const expression_node<T>* node)
+        {
+            return (0 != dynamic_cast<const cob_base_node<T>*>(node));
+        }
+        
+        template <typename T>
+        inline bool is_boc_node(const expression_node<T>* node)
+        {
+            return (0 != dynamic_cast<const boc_base_node<T>*>(node));
+        }
+        
+        template <typename T>
+        inline bool is_t0ot1ot2_node(const expression_node<T>* node)
+        {
+            return (0 != dynamic_cast<const T0oT1oT2_base_node<T>*>(node));
+        }
+        
+        template <typename T>
+        inline bool is_t0ot1ot2ot3_node(const expression_node<T>* node)
+        {
+            return (0 != dynamic_cast<const T0oT1oT2oT3_base_node<T>*>(node));
+        }
+        
+        template <typename T>
+        inline bool is_uv_node(const expression_node<T>* node)
+        {
+            return (0 != dynamic_cast<const uv_base_node<T>*>(node));
+        }
+        
+        template <typename T>
+        inline bool is_string_node(const expression_node<T>* node)
+        {
+            return node && (expression_node<T>::e_stringvar == node->type());
+        }
+        
+        template <typename T>
+        inline bool is_string_range_node(const expression_node<T>* node)
+        {
+            return node && (expression_node<T>::e_stringvarrng == node->type());
+        }
+        
+        template <typename T>
+        inline bool is_const_string_node(const expression_node<T>* node)
+        {
+            return node && (expression_node<T>::e_stringconst == node->type());
+        }
+        
+        template <typename T>
+        inline bool is_const_string_range_node(const expression_node<T>* node)
+        {
+            return node && (expression_node<T>::e_cstringvarrng == node->type());
+        }
+        
+        template <typename T>
+        inline bool is_string_assignment_node(const expression_node<T>* node)
+        {
+            return node && (expression_node<T>::e_strass == node->type());
+        }
+        
+        template <typename T>
+        inline bool is_string_concat_node(const expression_node<T>* node)
+        {
+            return node && (expression_node<T>::e_strconcat == node->type());
+        }
+        
+        template <typename T>
+        inline bool is_string_function_node(const expression_node<T>* node)
+        {
+            return node && (expression_node<T>::e_strfunction == node->type());
+        }
+        
+        template <typename T>
+        inline bool is_string_condition_node(const expression_node<T>* node)
+        {
+            return node && (expression_node<T>::e_strcondition == node->type());
+        }
+        
+        template <typename T>
+        inline bool is_string_ccondition_node(const expression_node<T>* node)
+        {
+            return node && (expression_node<T>::e_strccondition == node->type());
+        }
+        
+        template <typename T>
+        inline bool is_genricstring_range_node(const expression_node<T>* node)
+        {
+            return node && (expression_node<T>::e_strgenrange == node->type());
+        }
+        
+        template <typename T>
+        inline bool is_generally_string_node(const expression_node<T>* node)
+        {
+            if (node)
+            {
+                switch (node->type())
+                {
+                    case expression_node<T>::e_stringvar     :
+                    case expression_node<T>::e_stringconst   :
+                    case expression_node<T>::e_stringvarrng  :
+                    case expression_node<T>::e_cstringvarrng :
+                    case expression_node<T>::e_strgenrange   :
+                    case expression_node<T>::e_strass        :
+                    case expression_node<T>::e_strconcat     :
+                    case expression_node<T>::e_strfunction   :
+                    case expression_node<T>::e_strcondition  :
+                    case expression_node<T>::e_strccondition : return true;
+                    default                                  : return false;
+                }
+            }
+            
+            return false;
+        }
+        
+        class node_allocator
+        {
+        public:
+            
+            template <typename ResultNode, typename OpType, typename ExprNode>
+            inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[1])
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token_,
-                             "ERR60 - Failed to parse condition of for-loop"));
-               result = false;
+                return allocate<ResultNode>(operation,branch[0]);
             }
-            else if (!token_is(token_t::e_eof))
+            
+            template <typename ResultNode, typename OpType, typename ExprNode>
+            inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[2])
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token_,
-                             "ERR61 - Expected ';' after condition section of for-loop"));
-               result = false;
+                return allocate<ResultNode>(operation,branch[0],branch[1]);
             }
-         }
-
-         if (!token_is(token_t::e_rbracket))
-         {
-            if (0 == (incrementor = parse_expression()))
+            
+            template <typename ResultNode, typename OpType, typename ExprNode>
+            inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[3])
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token_,
-                             "ERR62 - Failed to parse incrementor of for-loop"));
-               result = false;
+                return allocate<ResultNode>(operation,branch[0],branch[1],branch[2]);
             }
-            else if (!token_is(token_t::e_rbracket))
+            
+            template <typename ResultNode, typename OpType, typename ExprNode>
+            inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[4])
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token_,
-                             "ERR63 - Expected ')' after incrementor section of for-loop"));
-               result = false;
+                return allocate<ResultNode>(operation,branch[0],branch[1],branch[2],branch[3]);
             }
-         }
-
-         if (result)
-         {
-            brkcnt_list_.push_front(false);
-            if (0 == (loop_body = parse_multi_sequence("for-loop")))
+            
+            template <typename ResultNode, typename OpType, typename ExprNode>
+            inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[5])
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token_,
-                             "ERR64 - Failed to parse body of for-loop"));
-               result = false;
+                return allocate<ResultNode>(operation,branch[0],branch[1],branch[2],branch[3],branch[4]);
             }
-         }
-
-         if (!result)
-         {
-            if (se)
+            
+            template <typename ResultNode, typename OpType, typename ExprNode>
+            inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[6])
             {
-               se->ref_count--;
+                return allocate<ResultNode>(operation,branch[0],branch[1],branch[2],branch[3],branch[4],branch[5]);
             }
-
-            sem_.cleanup();
-
-            free_node(node_allocator_,initialiser);
-            free_node(node_allocator_,  condition);
-            free_node(node_allocator_,incrementor);
-            free_node(node_allocator_,  loop_body);
-
-            if (!brkcnt_list_.empty())
+            
+            template <typename node_type>
+            inline expression_node<typename node_type::value_type>* allocate() const
             {
-               brkcnt_list_.pop_front();
+                return new node_type();
             }
-
-            return error_node();
-         }
-         else
-         {
-            expression_node_ptr result_node =
-                   expression_generator_.for_loop(initialiser,
-                                                  condition,
-                                                  incrementor,
-                                                  loop_body,
-                                                  brkcnt_list_.front());
-            brkcnt_list_.pop_front();
-
-            return result_node;
-         }
-      }
-
-      inline expression_node_ptr parse_switch_statement()
-      {
-         std::vector<expression_node_ptr> arg_list;
-         expression_node_ptr result = error_node();
-
-         if (!details::imatch(current_token_.value,"switch"))
-         {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token_,
-                          "ERR65 - Expected keyword 'switch'"));
-
-            return error_node();
-         }
-
-         scoped_vec_delete<expression_node_t> svd(*this,arg_list);
-
-         next_token();
-
-         if (!token_is(token_t::e_lcrlbracket))
-         {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token_,
-                          "ERR66 - Expected '{' for call to switch statement"));
-
-            return error_node();
-         }
-
-         for ( ; ; )
-         {
-            if (!details::imatch("case",current_token_.value))
-            {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token_,
-                             "ERR67 - Expected either a 'case' or 'default' statement"));
-
-               return error_node();
+            
+            template <typename node_type,
+            typename Type,
+            typename Allocator,
+            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);
             }
-
-            next_token();
-
-            expression_node_ptr condition = parse_expression();
-
-            if (0 == condition)
-               return error_node();
-            else if (!token_is(token_t::e_colon))
+            
+            template <typename node_type, typename T1>
+            inline expression_node<typename node_type::value_type>* allocate(T1& t1) const
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token_,
-                             "ERR68 - Expected ':' for case of switch statement"));
-
-               return error_node();
+                return new node_type(t1);
             }
-
-            expression_node_ptr consequent = parse_expression();
-
-            if (0 == consequent)
-               return error_node();
-            else if (!token_is(token_t::e_eof))
+            
+            template <typename node_type, typename T1>
+            inline expression_node<typename node_type::value_type>* allocate_c(const T1& t1) const
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token_,
-                             "ERR69 - Expected ';' at end of case for switch statement"));
-
-               return error_node();
+                return new node_type(t1);
             }
-
-            // Can we optimize away the case statement?
-            if (is_constant_node(condition) && is_false(condition))
+            
+            template <typename node_type,
+            typename T1, typename T2>
+            inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2) const
             {
-               free_node(node_allocator_, condition);
-               free_node(node_allocator_,consequent);
-
-               condition  = 0;
-               consequent = 0;
-            }
-            else
-            {
-               arg_list.push_back(condition);
-               arg_list.push_back(consequent);
-            }
-
-            if (details::imatch("default",current_token_.value))
-            {
-               next_token();
-               if (!token_is(token_t::e_colon))
-               {
-                  set_error(
-                     make_error(parser_error::e_syntax,
-                                current_token_,
-                                "ERR70 - Expected ':' for default of switch statement"));
-
-                  return error_node();
-               }
-
-               expression_node_ptr default_statement = parse_expression();
-
-               if (0 == default_statement)
-                  return error_node();
-               else if (!token_is(token_t::e_eof))
-               {
-                  set_error(
-                     make_error(parser_error::e_syntax,
-                                current_token_,
-                                "ERR71 - Expected ';' at end of default for switch statement"));
-
-                  return error_node();
-               }
-
-               arg_list.push_back(default_statement);
-               break;
-            }
-         }
-
-         if (!token_is(token_t::e_rcrlbracket))
-         {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token_,
-                          "ERR72 - Expected '}' at end of switch statement"));
-
-            return error_node();
-         }
-
-         result = expression_generator_.switch_statement(arg_list);
-
-         svd.delete_ptr = (0 == result);
-
-         return result;
-      }
-
-      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_,
-                          "ERR73 - Expected token '[*]'"));
-
-            return error_node();
-         }
-
-         scoped_vec_delete<expression_node_t> svd(*this,arg_list);
-
-         next_token();
-
-         if (!token_is(token_t::e_lcrlbracket))
-         {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token_,
-                          "ERR74 - Expected '{' for call to [*] statement"));
-
-            return error_node();
-         }
-
-         for ( ; ; )
-         {
-            if (!details::imatch("case",current_token_.value))
-            {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token_,
-                             "ERR75 - Expected a 'case' statement for multi-switch"));
-
-               return error_node();
+                return new node_type(t1,t2);
             }
-
-            next_token();
-
-            expression_node_ptr condition = parse_expression();
-
-            if (0 == condition)
-               return error_node();
-
-            if (!token_is(token_t::e_colon))
+            
+            template <typename node_type,
+            typename T1, typename T2>
+            inline expression_node<typename node_type::value_type>* allocate_cr(const T1& t1, T2& t2) const
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token_,
-                             "ERR76 - Expected ':' for case of [*] statement"));
-
-               return error_node();
+                return new node_type(t1,t2);
             }
-
-            expression_node_ptr consequent = parse_expression();
-
-            if (0 == consequent)
-               return error_node();
-
-            if (!token_is(token_t::e_eof))
+            
+            template <typename node_type,
+            typename T1, typename T2>
+            inline expression_node<typename node_type::value_type>* allocate_rc(T1& t1, const T2& t2) const
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token_,
-                             "ERR77 - Expected ';' at end of case for [*] statement"));
-
-               return error_node();
+                return new node_type(t1,t2);
             }
-
-            // Can we optimize away the case statement?
-            if (is_constant_node(condition) && is_false(condition))
+            
+            template <typename node_type,
+            typename T1, typename T2>
+            inline expression_node<typename node_type::value_type>* allocate_rr(T1& t1, T2& t2) const
             {
-               free_node(node_allocator_, condition);
-               free_node(node_allocator_,consequent);
-
-               condition  = 0;
-               consequent = 0;
+                return new node_type(t1,t2);
             }
-            else
+            
+            template <typename node_type,
+            typename T1, typename T2>
+            inline expression_node<typename node_type::value_type>* allocate_tt(T1 t1, T2 t2) const
             {
-               arg_list.push_back(condition);
-               arg_list.push_back(consequent);
+                return new node_type(t1,t2);
             }
-
-            if (token_is(token_t::e_rcrlbracket,false))
+            
+            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
             {
-               break;
+                return new node_type(t1,t2,t3);
             }
-         }
-
-         if (!token_is(token_t::e_rcrlbracket))
-         {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token_,
-                          "ERR78 - Expected '}' at end of [*] statement"));
-
-            return error_node();
-         }
-
-         result = expression_generator_.multi_switch_statement(arg_list);
-
-         svd.delete_ptr = (0 == result);
-
-         return result;
-      }
-
-      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;
-
-         if (details::imatch(symbol,"~"))
-         {
-            next_token();
-            return parse_multi_sequence();
-         }
-         else if (details::imatch(symbol,"[*]"))
-         {
-            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
-         {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token_,
-                          "ERR79 - Unsupported vararg function: " + symbol));
-
-            return error_node();
-         }
-
-         scoped_vec_delete<expression_node_t> sdd(*this,arg_list);
-
-         next_token();
-         if (!token_is(token_t::e_lbracket))
-         {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token_,
-                          "ERR80 - Expected '(' for call to vararg function: " + symbol));
-
-            return error_node();
-         }
-
-         for ( ; ; )
-         {
-            expression_node_ptr arg = parse_expression();
-
-            if (0 == arg)
-               return error_node();
-            else
-               arg_list.push_back(arg);
-
-            if (token_is(token_t::e_rbracket))
-               break;
-            else if (!token_is(token_t::e_comma))
+            
+            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
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token_,
-                             "ERR81 - Expected ',' for call to vararg function: " + symbol));
-
-               return error_node();
+                return new node_type(t1,t2,t3,t4);
             }
-         }
-
-         result = expression_generator_.vararg_function(opt_type,arg_list);
-
-         sdd.delete_ptr = (0 == result);
-         return result;
-      }
-
-      inline expression_node_ptr parse_string_range_statement(expression_node_ptr& expression)
-      {
-         if (!token_is(token_t::e_lsqrbracket))
-         {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token_,
-                          "ERR82 - Expected '[' as start of string range definition"));
-
-            free_node(node_allocator_,expression);
-
-            return error_node();
-         }
-         else if (token_is(token_t::e_rsqrbracket))
-         {
-            return node_allocator_.allocate<details::string_size_node<T> >(expression);
-         }
-
-         range_t rp;
-
-         if (!parse_range(rp,true))
-         {
-            free_node(node_allocator_,expression);
-
-            return error_node();
-         }
-
-         expression_node_ptr result = expression_generator_(expression,rp);
-
-         if (0 == result)
-         {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token_,
-                          "ERR83 - Failed to generate string range node"));
-
-            free_node(node_allocator_,expression);
-         }
-
-         rp.clear();
-
-         return result;
-      }
-
-      inline void parse_pending_string_rangesize(expression_node_ptr& expression)
-      {
-         const std::size_t max_rangesize_parses = 100;
-         std::size_t i = 0;
-
-         while
-            (
-               (0 != expression)                      &&
-               (i++ < max_rangesize_parses)           &&
-               error_list_.empty()                    &&
-               token_is(token_t::e_lsqrbracket,false) &&
-               is_generally_string_node(expression)
-            )
-         {
-            expression = parse_string_range_statement(expression);
-         }
-      }
-
-      template <typename Allocator,
-                template <typename,typename> class Sequence>
-      inline expression_node_ptr simplify(Sequence<expression_node_ptr,Allocator>& expression_list)
-      {
-         if (expression_list.empty())
-            return error_node();
-         else if (1 == expression_list.size())
-            return expression_list[0];
-
-         Sequence<expression_node_ptr,Allocator> tmp_expression_list;
-
-         for (std::size_t i = 0; i < (expression_list.size() - 1); ++i)
-         {
-            if (is_variable_node(expression_list[i]))
-               continue;
-            else if (
-                      is_constant_node(expression_list[i]) ||
-                      is_null_node    (expression_list[i])
-                    )
+            
+            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);
+            }
+            
+            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);
+            }
+            
+            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);
+            }
+            
+            template <typename node_type,
+            typename T1, typename T2, typename T3>
+            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);
+            }
+            
+            template <typename node_type,
+            typename T1, typename T2,
+            typename T3, typename T4>
+            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);
+            }
+            
+            template <typename node_type,
+            typename T1, typename T2,
+            typename T3, typename T4, typename T5>
+            inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
+                                                                             const T3& t3, const T4& t4,
+                                                                             const T5& t5) const
+            {
+                return new node_type(t1,t2,t3,t4,t5);
+            }
+            
+            template <typename node_type,
+            typename T1, typename T2,
+            typename T3, typename T4, typename T5, typename T6>
+            inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
+                                                                             const T3& t3, const T4& t4,
+                                                                             const T5& t5, const T6& t6) const
+            {
+                return new node_type(t1,t2,t3,t4,t5,t6);
+            }
+            
+            template <typename node_type,
+            typename T1, typename T2,
+            typename T3, typename T4,
+            typename T5, typename T6, typename T7>
+            inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
+                                                                             const T3& t3, const T4& t4,
+                                                                             const T5& t5, const T6& t6,
+                                                                             const T7& t7) const
+            {
+                return new node_type(t1,t2,t3,t4,t5,t6,t7);
+            }
+            
+            template <typename node_type,
+            typename T1, typename T2,
+            typename T3, typename T4,
+            typename T5, typename T6,
+            typename T7, typename T8>
+            inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
+                                                                             const T3& t3, const T4& t4,
+                                                                             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);
+            }
+            
+            template <typename node_type,
+            typename T1, typename T2,
+            typename T3, typename T4,
+            typename T5, typename T6,
+            typename T7, typename T8, typename T9>
+            inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
+                                                                             const T3& t3, const T4& t4,
+                                                                             const T5& t5, const T6& t6,
+                                                                             const T7& t7, const T8& t8,
+                                                                             const T9& t9) const
+            {
+                return new node_type(t1,t2,t3,t4,t5,t6,t7,t8,t9);
+            }
+            
+            template <typename node_type,
+            typename T1, typename T2,
+            typename T3, typename T4,
+            typename T5, typename T6,
+            typename T7, typename T8,
+            typename T9, typename T10>
+            inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const  T2&  t2,
+                                                                             const T3& t3, const  T4&  t4,
+                                                                             const T5& t5, const  T6&  t6,
+                                                                             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);
+            }
+            
+            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);
+            }
+            
+            template <typename node_type,
+            typename T1, typename T2,
+            typename T3, typename T4>
+            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);
+            }
+            
+            template <typename node_type,
+            typename T1, typename T2,
+            typename T3, typename T4,
+            typename T5>
+            inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2,
+                                                                                  T3 t3, T4 t4,
+                                                                                  T5 t5) const
+            {
+                return new node_type(t1,t2,t3,t4,t5);
+            }
+            
+            template <typename node_type,
+            typename T1, typename T2,
+            typename T3, typename T4,
+            typename T5, typename T6, typename T7>
+            inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2,
+                                                                                  T3 t3, T4 t4,
+                                                                                  T5 t5, T6 t6,
+                                                                                  T7 t7) const
+            {
+                return new node_type(t1,t2,t3,t4,t5,t6,t7);
+            }
+            
+            template <typename T>
+            void inline free(expression_node<T>*& e) const
             {
-               free_node(node_allocator_,expression_list[i]);
-               continue;
+                delete e;
+                e = 0;
             }
-            else
-               tmp_expression_list.push_back(expression_list[i]);
-         }
-
-         tmp_expression_list.push_back(expression_list.back());
-         expression_list.swap(tmp_expression_list);
-
-         if (1 == expression_list.size())
-            return expression_list[0];
-         else
-            return expression_generator_.vararg_function(details::e_multi,expression_list);
-      }
-
-      inline expression_node_ptr parse_multi_sequence(const std::string& source = "")
-      {
-         token_t::token_type close_bracket = token_t::e_rcrlbracket;
-         token_t::token_type seperator     = token_t::e_eof;
-
-         if (!token_is(token_t::e_lcrlbracket))
-         {
-            if (token_is(token_t::e_lbracket))
+        };
+        
+        inline void load_operations_map(std::multimap<std::string,details::base_operation_t,details::ilesscompare>& m)
+        {
+#define register_op(Symbol,Type,Args)                                               \
+m.insert(std::make_pair(std::string(Symbol),details::base_operation_t(Type,Args))); \
+
+            register_op(      "abs",e_abs     , 1)
+            register_op(     "acos",e_acos    , 1)
+            register_op(    "acosh",e_acosh   , 1)
+            register_op(     "asin",e_asin    , 1)
+            register_op(    "asinh",e_asinh   , 1)
+            register_op(     "atan",e_atan    , 1)
+            register_op(    "atanh",e_atanh   , 1)
+            register_op(     "ceil",e_ceil    , 1)
+            register_op(      "cos",e_cos     , 1)
+            register_op(     "cosh",e_cosh    , 1)
+            register_op(      "exp",e_exp     , 1)
+            register_op(    "expm1",e_expm1   , 1)
+            register_op(    "floor",e_floor   , 1)
+            register_op(      "log",e_log     , 1)
+            register_op(    "log10",e_log10   , 1)
+            register_op(     "log2",e_log2    , 1)
+            register_op(    "log1p",e_log1p   , 1)
+            register_op(    "round",e_round   , 1)
+            register_op(      "sin",e_sin     , 1)
+            register_op(     "sinc",e_sinc    , 1)
+            register_op(     "sinh",e_sinh    , 1)
+            register_op(      "sec",e_sec     , 1)
+            register_op(      "csc",e_csc     , 1)
+            register_op(     "sqrt",e_sqrt    , 1)
+            register_op(      "tan",e_tan     , 1)
+            register_op(     "tanh",e_tanh    , 1)
+            register_op(      "cot",e_cot     , 1)
+            register_op(  "rad2deg",e_r2d     , 1)
+            register_op(  "deg2rad",e_d2r     , 1)
+            register_op( "deg2grad",e_d2g     , 1)
+            register_op( "grad2deg",e_g2d     , 1)
+            register_op(      "sgn",e_sgn     , 1)
+            register_op(      "not",e_notl    , 1)
+            register_op(      "erf",e_erf     , 1)
+            register_op(     "erfc",e_erfc    , 1)
+            register_op(     "ncdf",e_ncdf    , 1)
+            register_op(     "frac",e_frac    , 1)
+            register_op(    "trunc",e_trunc   , 1)
+            register_op(    "atan2",e_atan2   , 2)
+            register_op(      "mod",e_mod     , 2)
+            register_op(     "logn",e_logn    , 2)
+            register_op(      "pow",e_pow     , 2)
+            register_op(     "root",e_root    , 2)
+            register_op(   "roundn",e_roundn  , 2)
+            register_op(    "equal",e_equal   , 2)
+            register_op("not_equal",e_nequal  , 2)
+            register_op(    "hypot",e_hypot   , 2)
+            register_op(      "shr",e_shr     , 2)
+            register_op(      "shl",e_shl     , 2)
+            register_op(    "clamp",e_clamp   , 3)
+            register_op(   "iclamp",e_iclamp  , 3)
+            register_op(  "inrange",e_inrange , 3)
+#undef register_op
+        }
+        
+    } // namespace details
+    
+    class function_traits
+    {
+    public:
+        
+        function_traits()
+        : allow_zero_parameters_(false),
+        has_side_effects_(true),
+        min_num_args_(0),
+        max_num_args_(std::numeric_limits<std::size_t>::max())
+        {}
+        
+        inline bool& allow_zero_parameters()
+        {
+            return allow_zero_parameters_;
+        }
+        
+        inline bool& has_side_effects()
+        {
+            return has_side_effects_;
+        }
+        
+        std::size_t& min_num_args()
+        {
+            return min_num_args_;
+        }
+        
+        std::size_t& max_num_args()
+        {
+            return max_num_args_;
+        }
+        
+    private:
+        
+        bool allow_zero_parameters_;
+        bool has_side_effects_;
+        std::size_t min_num_args_;
+        std::size_t max_num_args_;
+    };
+    
+    template <typename FunctionType>
+    void enable_zero_parameters(FunctionType& func)
+    {
+        func.allow_zero_parameters() = true;
+        
+        if (0 != func.min_num_args())
+        {
+            func.min_num_args() = 0;
+        }
+    }
+    
+    template <typename FunctionType>
+    void disable_zero_parameters(FunctionType& func)
+    {
+        func.allow_zero_parameters() = false;
+    }
+    
+    template <typename FunctionType>
+    void enable_has_side_effects(FunctionType& func)
+    {
+        func.has_side_effects() = true;
+    }
+    
+    template <typename FunctionType>
+    void disable_has_side_effects(FunctionType& func)
+    {
+        func.has_side_effects() = false;
+    }
+    
+    template <typename FunctionType>
+    void set_min_num_args(FunctionType& func, const std::size_t& num_args)
+    {
+        func.min_num_args() = num_args;
+        
+        if ((0 != func.min_num_args()) && func.allow_zero_parameters())
+            func.allow_zero_parameters() = false;
+    }
+    
+    template <typename FunctionType>
+    void set_max_num_args(FunctionType& func, const std::size_t& num_args)
+    {
+        func.max_num_args() = num_args;
+    }
+    
+    template <typename T>
+    class ifunction : public function_traits
+    {
+    public:
+        
+        explicit ifunction(const std::size_t& pc)
+        : param_count(pc)
+        {}
+        
+        virtual ~ifunction()
+        {}
+        
+#define empty_method_body                      \
+{                                              \
+return std::numeric_limits<T>::quiet_NaN(); \
+}                                              \
+
+        inline virtual T operator()()
+        empty_method_body
+        
+        inline virtual T operator()(const T&)
+        empty_method_body
+        
+        inline virtual T operator()(const T&,const T&)
+        empty_method_body
+        
+        inline virtual T operator()(const T&, const T&, const T&)
+        empty_method_body
+        
+        inline virtual T operator()(const T&, const T&, const T&, const T&)
+        empty_method_body
+        
+        inline virtual T operator()(const T&, const T&, const T&, const T&, const T&)
+        empty_method_body
+        
+        inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&)
+        empty_method_body
+        
+        inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&)
+        empty_method_body
+        
+        inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
+        empty_method_body
+        
+        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
+        
+        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
+        
+        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
+        
+        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
+        
+        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
+        
+        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
+        
+        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
+        
+        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
+        
+        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
+        
+        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
+        
+        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
+        
+        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
+        
+#undef empty_method_body
+        
+        std::size_t param_count;
+    };
+    
+    template <typename T>
+    class ivararg_function : public function_traits
+    {
+    public:
+        
+        virtual ~ivararg_function()
+        {}
+        
+        inline virtual T operator()(const std::vector<T>&)
+        {
+            exprtk_debug(("ivararg_function::operator() - Operator has not been overridden.\n"));
+            return std::numeric_limits<T>::quiet_NaN();
+        }
+    };
+    
+    template <typename T>
+    class igeneric_function : public function_traits
+    {
+    public:
+        
+        enum return_type
+        {
+            e_rtrn_scalar = 0,
+            e_rtrn_string = 1
+        };
+        
+        typedef T type;
+        typedef type_store<T> generic_type;
+        typedef typename generic_type::parameter_list parameter_list_t;
+        
+        igeneric_function(const std::string& param_seq = "", const return_type rtr_type = e_rtrn_scalar)
+        : parameter_sequence(param_seq),
+        rtrn_type(rtr_type)
+        {}
+        
+        virtual ~igeneric_function()
+        {}
+        
+#define igeneric_function_empty_body(N)        \
+{                                              \
+exprtk_debug(("igeneric_function::operator() - Operator has not been overridden. ["#N"]\n")); \
+return std::numeric_limits<T>::quiet_NaN(); \
+}                                              \
+
+        // f(i_0,i_1,....,i_N) --> Scalar
+        inline virtual T operator()(parameter_list_t)
+        igeneric_function_empty_body(1)
+        
+        // f(i_0,i_1,....,i_N) --> String
+        inline virtual T operator()(std::string&, parameter_list_t)
+        igeneric_function_empty_body(2)
+        
+        // f(psi,i_0,i_1,....,i_N) --> Scalar
+        inline virtual T operator()(const std::size_t&, parameter_list_t)
+        igeneric_function_empty_body(3)
+        
+        // f(psi,i_0,i_1,....,i_N) --> String
+        inline virtual T operator()(const std::size_t&, std::string&, parameter_list_t)
+        igeneric_function_empty_body(4)
+        
+        std::string parameter_sequence;
+        return_type rtrn_type;
+    };
+    
+    template <typename T> class parser;
+    template <typename T> class expression_helper;
+    
+    template <typename T>
+    class symbol_table
+    {
+    public:
+        
+        typedef T (*ff1_functor)(T);
+        typedef T (*ff2_functor)(T,T);
+        typedef T (*ff3_functor)(T,T,T);
+        typedef T (*ff4_functor)(T,T,T,T);
+        typedef T (*ff5_functor)(T,T,T,T,T);
+        typedef T (*ff6_functor)(T,T,T,T,T,T);
+        
+    protected:
+        
+        struct freefunc1 : public exprtk::ifunction<T>
+        {
+            using exprtk::ifunction<T>::operator();
+            
+            freefunc1(ff1_functor ff) : exprtk::ifunction<T>(1), f(ff) {}
+            inline T operator()(const T& v0)
+            { return f(v0); }
+            ff1_functor f;
+        };
+        
+        struct freefunc2 : public exprtk::ifunction<T>
+        {
+            using exprtk::ifunction<T>::operator();
+            
+            freefunc2(ff2_functor ff) : exprtk::ifunction<T>(2), f(ff) {}
+            inline T operator()(const T& v0, const T& v1)
+            { return f(v0,v1); }
+            ff2_functor f;
+        };
+        
+        struct freefunc3 : public exprtk::ifunction<T>
+        {
+            using exprtk::ifunction<T>::operator();
+            
+            freefunc3(ff3_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); }
+            ff3_functor f;
+        };
+        
+        struct freefunc4 : public exprtk::ifunction<T>
+        {
+            using exprtk::ifunction<T>::operator();
+            
+            freefunc4(ff4_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); }
+            ff4_functor f;
+        };
+        
+        struct freefunc5 : public exprtk::ifunction<T>
+        {
+            using exprtk::ifunction<T>::operator();
+            
+            freefunc5(ff5_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); }
+            ff5_functor f;
+        };
+        
+        struct freefunc6 : public exprtk::ifunction<T>
+        {
+            using exprtk::ifunction<T>::operator();
+            
+            freefunc6(ff6_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); }
+            ff6_functor f;
+        };
+        
+        template <typename Type, typename RawType>
+        struct type_store
+        {
+            typedef details::expression_node<T>*        expression_ptr;
+            typedef typename details::variable_node<T>  variable_node_t;
+            typedef ifunction<T>                        ifunction_t;
+            typedef ivararg_function<T>                 ivararg_function_t;
+            typedef igeneric_function<T>                igeneric_function_t;
+            typedef details::vector_holder<T>           vector_t;
+#ifndef exprtk_disable_string_capabilities
+            typedef typename details::stringvar_node<T> stringvar_node_t;
+#endif
+            
+            typedef Type type_t;
+            typedef type_t* type_ptr;
+            typedef std::pair<bool,type_ptr> type_pair_t;
+            typedef std::map<std::string,type_pair_t,details::ilesscompare> type_map_t;
+            typedef typename type_map_t::iterator tm_itr_t;
+            typedef typename type_map_t::const_iterator tm_const_itr_t;
+            
+            enum { lut_size = 256 };
+            
+            type_map_t  map;
+            std::size_t size;
+            
+            type_store()
+            : size(0)
+            {}
+            
+            inline bool symbol_exists(const std::string& symbol_name) const
+            {
+                if (symbol_name.empty())
+                    return false;
+                else if (map.end() != map.find(symbol_name))
+                    return true;
+                else
+                    return false;
+            }
+            
+            template <typename PtrType>
+            inline std::string entity_name(const PtrType& ptr) const
+            {
+                if (map.empty())
+                    return std::string();
+                
+                tm_const_itr_t itr = map.begin();
+                
+                while (map.end() != itr)
+                {
+                    if (itr->second.second == ptr)
+                    {
+                        return itr->first;
+                    }
+                    else
+                        ++itr;
+                }
+                
+                return std::string();
+            }
+            
+            inline bool is_constant(const std::string& symbol_name) const
+            {
+                if (symbol_name.empty())
+                    return false;
+                else
+                {
+                    tm_const_itr_t itr = map.find(symbol_name);
+                    
+                    if (map.end() == itr)
+                        return false;
+                    else
+                        return (*itr).second.first;
+                }
+            }
+            
+            template <typename Tie, typename RType>
+            inline bool add_impl(const std::string& symbol_name, RType t, const bool is_const)
+            {
+                if (symbol_name.size() > 1)
+                {
+                    for (std::size_t i = 0; i < details::reserved_symbols_size; ++i)
+                    {
+                        if (details::imatch(symbol_name,details::reserved_symbols[i]))
+                        {
+                            return false;
+                        }
+                    }
+                }
+                
+                tm_itr_t itr = map.find(symbol_name);
+                
+                if (map.end() == itr)
+                {
+                    map[symbol_name] = Tie::make(t,is_const);
+                    ++size;
+                }
+                
+                return true;
+            }
+            
+            struct tie_array
+            {
+                static inline std::pair<bool,vector_t*> make(std::pair<T*,std::size_t> v, const bool is_const = false)
+                {
+                    return std::make_pair(is_const,new vector_t(v.first,v.second));
+                }
+            };
+            
+            struct tie_stdvec
+            {
+                template <typename Allocator>
+                static inline std::pair<bool,vector_t*> make(std::vector<T,Allocator>& v, const bool is_const = false)
+                {
+                    return std::make_pair(is_const,new vector_t(v));
+                }
+            };
+            
+            struct tie_vecview
             {
-               close_bracket = token_t::e_rbracket;
-               seperator     = token_t::e_comma;
-            }
-            else
+                static inline std::pair<bool,vector_t*> make(exprtk::vector_view<T>& v, const bool is_const = false)
+                {
+                    return std::make_pair(is_const,new vector_t(v));
+                }
+            };
+            
+            struct tie_stddeq
+            {
+                template <typename Allocator>
+                static inline std::pair<bool,vector_t*> make(std::deque<T,Allocator>& v, const bool is_const = false)
+                {
+                    return std::make_pair(is_const,new vector_t(v));
+                }
+            };
+            
+            template <std::size_t v_size>
+            inline bool add(const std::string& symbol_name, T (&v)[v_size], const bool is_const = false)
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token_,
-                             "ERR84 - Expected '" + token_t::to_str(close_bracket) + "' for call to multi-sequence" +
-                             ((!source.empty()) ? std::string(" section of " + source): "")));
-
-               return error_node();
+                return add_impl<tie_array,std::pair<T*,std::size_t> >(symbol_name,std::make_pair(v,v_size),is_const);
             }
-         }
-         else if (token_is(token_t::e_rcrlbracket))
-         {
-            return node_allocator_.allocate<details::null_node<T> >();
-         }
-
-         std::vector<expression_node_ptr> arg_list;
-         expression_node_ptr result = error_node();
-
-         scoped_vec_delete<expression_node_t> sdd(*this,arg_list);
-
-         scope_handler sh(*this);
-
-         for (;;)
-         {
-            expression_node_ptr arg = parse_expression();
-
-            if (0 == arg)
-               return error_node();
-            else
-               arg_list.push_back(arg);
-
-            if (token_is(close_bracket))
-               break;
-
-            bool is_next_close = peek_token_is(close_bracket);
-
-            if (!token_is(seperator) && is_next_close)
+            
+            inline bool add(const std::string& symbol_name, T* v, const std::size_t v_size, const bool is_const = false)
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token_,
-                             "ERR85 - Expected '" + details::to_str(seperator) + "' for call to multi-sequence section of " + source));
-
-               return error_node();
+                return add_impl<tie_array,std::pair<T*,std::size_t> >(symbol_name,std::make_pair(v,v_size),is_const);
             }
-
-            if (token_is(close_bracket))
-               break;
-         }
-
-         result = simplify(arg_list);
-
-         sdd.delete_ptr = (0 == result);
-         return result;
-      }
-
-      inline bool parse_range(range_t& rp, const bool skip_lsqr = false)
-      {
-         // Examples of valid ranges:
-         // 1. [1:5]     -> 1..5
-         // 2. [ :5]     -> 0..5
-         // 3. [1: ]     -> 1..end
-         // 4. [x:y]     -> x..y where x <= y
-         // 5. [x+1:y/2] -> x+1..y/2 where x+1 <= y/2
-         // 6. [ :y]     -> 0..y where 0 <= y
-         // 7. [x: ]     -> x..end where x <= end
-
-         rp.clear();
-
-         if (!skip_lsqr && !token_is(token_t::e_lsqrbracket))
-         {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token_,
-                          "ERR86 - Expected '[' for start of range"));
-
-            return false;
-         }
-
-         if (token_is(token_t::e_colon))
-         {
-            rp.n0_c.first  = true;
-            rp.n0_c.second = 0;
-            rp.cache.first = 0;
-         }
-         else
-         {
-            expression_node_ptr r0 = parse_expression();
-
-            if (0 == r0)
+            
+            template <typename Allocator>
+            inline bool add(const std::string& symbol_name, std::vector<T,Allocator>& v, const bool is_const = false)
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token_,
-                             "ERR87 - Failed parse begin section of range"));
-
-               return false;
-
+                return add_impl<tie_stdvec,std::vector<T,Allocator>&>(symbol_name,v,is_const);
             }
-            else if (is_constant_node(r0))
+            
+            inline bool add(const std::string& symbol_name, exprtk::vector_view<T>& v, const bool is_const = false)
             {
-               T r0_value = r0->value();
-
-               if (r0_value >= T(0))
-               {
-                  rp.n0_c.first  = true;
-                  rp.n0_c.second = static_cast<std::size_t>(details::numeric::to_int64(r0_value));
-                  rp.cache.first = rp.n0_c.second;
-               }
-
-               free_node(node_allocator_,r0);
-
-               if (r0_value < T(0))
-               {
-                  set_error(
-                     make_error(parser_error::e_syntax,
-                                current_token_,
-                                "ERR88 - Range lower bound less than zero! Constraint: r0 >= 0"));
-
-                  return false;
-               }
+                return add_impl<tie_vecview,exprtk::vector_view<T>&>(symbol_name,v,is_const);
             }
-            else
-            {
-               rp.n0_e.first  = true;
-               rp.n0_e.second = r0;
+            
+            template <typename Allocator>
+            inline bool add(const std::string& symbol_name, std::deque<T,Allocator>& v, const bool is_const = false)
+            {
+                return add_impl<tie_stddeq,std::deque<T,Allocator>&>(symbol_name,v,is_const);
+            }
+            
+            inline bool add(const std::string& symbol_name, RawType& t, const bool is_const = false)
+            {
+                struct tie
+                {
+                    static inline std::pair<bool,variable_node_t*> make(T& t,const bool is_const = false)
+                    {
+                        return std::make_pair(is_const,new variable_node_t(t));
+                    }
+                    
+#ifndef exprtk_disable_string_capabilities
+                    static inline std::pair<bool,stringvar_node_t*> make(std::string& t,const bool is_const = false)
+                    {
+                        return std::make_pair(is_const,new stringvar_node_t(t));
+                    }
+#endif
+                    
+                    static inline std::pair<bool,function_t*> make(function_t& t, const bool is_constant = false)
+                    {
+                        return std::make_pair(is_constant,&t);
+                    }
+                    
+                    static inline std::pair<bool,vararg_function_t*> make(vararg_function_t& t, const bool is_const = false)
+                    {
+                        return std::make_pair(is_const,&t);
+                    }
+                    
+                    static inline std::pair<bool,generic_function_t*> make(generic_function_t& t, const bool is_constant = false)
+                    {
+                        return std::make_pair(is_constant,&t);
+                    }
+                };
+                
+                tm_itr_t itr = map.find(symbol_name);
+                
+                if (map.end() == itr)
+                {
+                    map[symbol_name] = tie::make(t,is_const);
+                    ++size;
+                }
+                
+                return true;
+            }
+            
+            inline type_ptr get(const std::string& symbol_name) const
+            {
+                tm_const_itr_t itr = map.find(symbol_name);
+                
+                if (map.end() == itr)
+                    return reinterpret_cast<type_ptr>(0);
+                else
+                    return itr->second.second;
+            }
+            
+            template <typename TType, typename TRawType, typename PtrType>
+            struct ptr_match
+            {
+                static inline bool test(const PtrType, const void*)
+                {
+                    return false;
+                }
+            };
+            
+            template <typename TType, typename TRawType>
+            struct ptr_match<TType,TRawType,variable_node_t*>
+            {
+                static inline bool test(const variable_node_t* p, const void* ptr)
+                {
+                    exprtk_debug(("ptr_match::test() - %p <--> %p\n",(void*)(&(p->ref())),ptr));
+                    return (&(p->ref()) == ptr);
+                }
+            };
+            
+            inline type_ptr get_from_varptr(const void* ptr) const
+            {
+                tm_const_itr_t itr = map.begin();
+                
+                while (map.end() != itr)
+                {
+                    type_ptr ret_ptr = itr->second.second;
+                    
+                    if (ptr_match<Type,RawType,type_ptr>::test(ret_ptr,ptr))
+                    {
+                        return ret_ptr;
+                    }
+                    
+                    ++itr;
+                }
+                
+                return type_ptr(0);
+            }
+            
+            inline bool remove(const std::string& symbol_name, const bool delete_node = true)
+            {
+                tm_itr_t itr = map.find(symbol_name);
+                
+                if (map.end() != itr)
+                {
+                    struct deleter
+                    {
+                        static inline void process(std::pair<bool,variable_node_t*>& n)  { delete n.second; }
+                        static inline void process(std::pair<bool,vector_t*>& n)         { delete n.second; }
+#ifndef exprtk_disable_string_capabilities
+                        static inline void process(std::pair<bool,stringvar_node_t*>& n) { delete n.second; }
+#endif
+                        static inline void process(std::pair<bool,function_t*>&)         {                  }
+                    };
+                    
+                    if (delete_node)
+                    {
+                        deleter::process((*itr).second);
+                    }
+                    
+                    map.erase(itr);
+                    --size;
+                    
+                    return true;
+                }
+                else
+                    return false;
+            }
+            
+            inline RawType& type_ref(const std::string& symbol_name)
+            {
+                struct init_type
+                {
+                    static inline double set(double)           { return (0.0);           }
+                    static inline double set(long double)      { return (0.0);           }
+                    static inline float  set(float)            { return (0.0f);          }
+                    static inline std::string set(std::string) { return std::string(""); }
+                };
+                
+                static RawType null_type = init_type::set(RawType());
+                
+                tm_const_itr_t itr = map.find(symbol_name);
+                
+                if (map.end() == itr)
+                    return null_type;
+                else
+                    return itr->second.second->ref();
+            }
+            
+            inline void clear(const bool delete_node = true)
+            {
+                struct deleter
+                {
+                    static inline void process(std::pair<bool,variable_node_t*>& n)  { delete n.second; }
+                    static inline void process(std::pair<bool,vector_t*>& n)         { delete n.second; }
+                    static inline void process(std::pair<bool,function_t*>&)         {                  }
+#ifndef exprtk_disable_string_capabilities
+                    static inline void process(std::pair<bool,stringvar_node_t*>& n) { delete n.second; }
+#endif
+                };
+                
+                if (!map.empty())
+                {
+                    if (delete_node)
+                    {
+                        tm_itr_t itr = map.begin();
+                        tm_itr_t end = map.end();
+                        
+                        while (end != itr)
+                        {
+                            deleter::process((*itr).second);
+                            ++itr;
+                        }
+                    }
+                    
+                    map.clear();
+                }
+                
+                size = 0;
+            }
+            
+            template <typename Allocator,
+            template <typename, typename> class Sequence>
+            inline std::size_t get_list(Sequence<std::pair<std::string,RawType>,Allocator>& list) const
+            {
+                std::size_t count = 0;
+                
+                if (!map.empty())
+                {
+                    tm_const_itr_t itr = map.begin();
+                    tm_const_itr_t end = map.end();
+                    
+                    while (end != itr)
+                    {
+                        list.push_back(std::make_pair((*itr).first,itr->second.second->ref()));
+                        ++itr;
+                        ++count;
+                    }
+                }
+                
+                return count;
+            }
+            
+            template <typename Allocator,
+            template <typename, typename> class Sequence>
+            inline std::size_t get_list(Sequence<std::string,Allocator>& vlist) const
+            {
+                std::size_t count = 0;
+                
+                if (!map.empty())
+                {
+                    tm_const_itr_t itr = map.begin();
+                    tm_const_itr_t end = map.end();
+                    
+                    while (end != itr)
+                    {
+                        vlist.push_back((*itr).first);
+                        ++itr;
+                        ++count;
+                    }
+                }
+                
+                return count;
             }
-
-            if (!token_is(token_t::e_colon))
+        };
+        
+        typedef details::expression_node<T>* expression_ptr;
+        typedef typename details::variable_node<T> variable_t;
+        typedef typename details::vector_holder<T> vector_holder_t;
+        typedef variable_t* variable_ptr;
+#ifndef exprtk_disable_string_capabilities
+        typedef typename details::stringvar_node<T> stringvar_t;
+        typedef stringvar_t* stringvar_ptr;
+#endif
+        typedef ifunction        <T> function_t;
+        typedef ivararg_function <T> vararg_function_t;
+        typedef igeneric_function<T> generic_function_t;
+        typedef function_t* function_ptr;
+        typedef vararg_function_t*  vararg_function_ptr;
+        typedef generic_function_t* generic_function_ptr;
+        
+        static const std::size_t lut_size = 256;
+        
+        // Symbol Table Holder
+        struct control_block
+        {
+            struct st_data
+            {
+                type_store<typename details::variable_node<T>,T> variable_store;
+#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<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;
+                
+                st_data()
+                {
+                    for (std::size_t i = 0; i < details::reserved_words_size; ++i)
+                    {
+                        reserved_symbol_table_.insert(details::reserved_words[i]);
+                    }
+                    
+                    for (std::size_t i = 0; i < details::reserved_symbols_size; ++i)
+                    {
+                        reserved_symbol_table_.insert(details::reserved_symbols[i]);
+                    }
+                }
+                
+                ~st_data()
+                {
+                    for (std::size_t i = 0; i < free_function_list_.size(); ++i)
+                    {
+                        delete free_function_list_[i];
+                    }
+                }
+                
+                inline bool is_reserved_symbol(const std::string& symbol) const
+                {
+                    return (reserved_symbol_table_.end() != reserved_symbol_table_.find(symbol));
+                }
+                
+                std::list<T>               local_symbol_list_;
+                std::list<std::string>     local_stringvar_list_;
+                std::set<std::string>      reserved_symbol_table_;
+                std::vector<ifunction<T>*> free_function_list_;
+            };
+            
+            control_block()
+            : ref_count(1),
+            data_(new st_data)
+            {}
+            
+            control_block(st_data* data)
+            : ref_count(1),
+            data_(data)
+            {}
+            
+            ~control_block()
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token_,
-                             "ERR89 - Expected ':' for break  in range"));
-
-               rp.free();
-               return false;
+                if (data_ && (0 == ref_count))
+                {
+                    delete data_;
+                    data_ = 0;
+                }
             }
-         }
-
-         if (token_is(token_t::e_rsqrbracket))
-         {
-            rp.n1_c.first  = true;
-            rp.n1_c.second = std::numeric_limits<std::size_t>::max();
-         }
-         else
-         {
-            expression_node_ptr r1 = parse_expression();
-
-            if (0 == r1)
+            
+            static inline control_block* create()
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token_,
-                             "ERR90 - Failed parse end section of range"));
-
-               rp.free();
-               return false;
-
+                return new control_block;
             }
-            else if (is_constant_node(r1))
+            
+            template <typename SymTab>
+            static inline void destroy(control_block*& cntrl_blck, SymTab* sym_tab)
             {
-               T r1_value = r1->value();
-
-               if (r1_value >= T(0))
-               {
-                  rp.n1_c.first   = true;
-                  rp.n1_c.second  = static_cast<std::size_t>(details::numeric::to_int64(r1_value));
-                  rp.cache.second = rp.n1_c.second;
-               }
-
-               free_node(node_allocator_,r1);
-
-               if (r1_value < T(0))
-               {
-                  set_error(
-                     make_error(parser_error::e_syntax,
-                                current_token_,
-                                "ERR91 - Range upper bound less than zero! Constraint: r1 >= 0"));
-
-                  return false;
-               }
-            }
+                if (cntrl_blck)
+                {
+                    if (
+                        (0 !=   cntrl_blck->ref_count) &&
+                        (0 == --cntrl_blck->ref_count)
+                        )
+                    {
+                        if (sym_tab)
+                            sym_tab->clear();
+                        
+                        delete cntrl_blck;
+                    }
+                    
+                    cntrl_blck = 0;
+                }
+            }
+            
+            std::size_t ref_count;
+            st_data* data_;
+        };
+        
+    public:
+        
+        symbol_table()
+        : control_block_(control_block::create())
+        {
+            clear();
+        }
+        
+        ~symbol_table()
+        {
+            control_block::destroy(control_block_,this);
+        }
+        
+        symbol_table(const symbol_table<T>& st)
+        {
+            control_block_ = st.control_block_;
+            control_block_->ref_count++;
+        }
+        
+        inline symbol_table<T>& operator=(const symbol_table<T>& st)
+        {
+            if (this != &st)
+            {
+                control_block::destroy(control_block_,reinterpret_cast<symbol_table<T>*>(0));
+                
+                control_block_ = st.control_block_;
+                control_block_->ref_count++;
+            }
+            
+            return *this;
+        }
+        
+        inline bool operator==(const symbol_table<T>& st)
+        {
+            return (this == &st) || (control_block_ == st.control_block_);
+        }
+        
+        inline void clear_variables(const bool delete_node = true)
+        {
+            local_data().variable_store.clear(delete_node);
+        }
+        
+        inline void clear_functions()
+        {
+            local_data().function_store.clear();
+        }
+        
+        inline void clear_strings()
+        {
+#ifndef exprtk_disable_string_capabilities
+            local_data().stringvar_store.clear();
+#endif
+        }
+        
+        inline void clear_vectors()
+        {
+            local_data().vector_store.clear();
+        }
+        
+        inline void clear()
+        {
+            if (!valid()) return;
+            clear_variables();
+            clear_functions();
+            clear_strings  ();
+            clear_vectors  ();
+        }
+        
+        inline std::size_t variable_count() const
+        {
+            if (valid())
+                return local_data().variable_store.size;
             else
-            {
-               rp.n1_e.first  = true;
-               rp.n1_e.second = r1;
-            }
-
-            if (!token_is(token_t::e_rsqrbracket))
-            {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token_,
-                             "ERR92 - Expected ']' for start of range"));
-
-               rp.free();
-               return false;
-            }
-         }
-
-         if (rp.const_range())
-         {
-            std::size_t r0 = 0;
-            std::size_t r1 = 0;
-
-            bool rp_result = rp(r0,r1);
-
-            if (!rp_result || (r0 > r1))
-            {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token_,
-                             "ERR93 - Invalid range, Constraint: r0 <= r1"));
-
-               return false;
-            }
-         }
-
-         return true;
-      }
-
-      inline void lodge_symbol(const std::string& symbol,
-                               const symbol_type st)
-      {
-         dec_.add_symbol(symbol,st);
-      }
-
-      inline expression_node_ptr parse_string()
-      {
-         const std::string symbol = current_token_.value;
-
-         if (!symbol_table_.is_conststr_stringvar(symbol))
-         {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token_,
-                          "ERR94 - Unknown string symbol"));
-
-            return error_node();
-         }
-
-         expression_node_ptr result = symbol_table_.get_stringvar(symbol);
-
-         typedef details::stringvar_node<T>* strvar_node_t;
-         strvar_node_t const_str_node = static_cast<strvar_node_t>(0);
-
-         const bool is_const_string = symbol_table_.is_constant_string(symbol);
-
-         if (is_const_string)
-         {
-            const_str_node = static_cast<strvar_node_t>(result);
-            result = expression_generator_(const_str_node->str());
-         }
-
-         lodge_symbol(symbol,e_st_string);
-
-         if (peek_token_is(token_t::e_lsqrbracket))
-         {
-            next_token();
-
-            if (peek_token_is(token_t::e_rsqrbracket))
-            {
-               next_token();
-               next_token();
-
-               if (const_str_node)
-               {
-                  free_node(node_allocator_,result);
-
-                  return expression_generator_(T(const_str_node->size()));
-               }
-               else
-                  return node_allocator_.allocate<details::stringvar_size_node<T> >
-                            (static_cast<details::stringvar_node<T>*>(result)->ref());
-            }
-
-            range_t rp;
-
-            if (!parse_range(rp))
-            {
-               free_node(node_allocator_,result);
-
-               return error_node();
-            }
-            else if (const_str_node)
-            {
-               free_node(node_allocator_,result);
-               result = expression_generator_(const_str_node->ref(),rp);
-            }
+                return 0;
+        }
+        
+#ifndef exprtk_disable_string_capabilities
+        inline std::size_t stringvar_count() const
+        {
+            if (valid())
+                return local_data().stringvar_store.size;
             else
-               result = expression_generator_(static_cast<details::stringvar_node<T>*>(result)->ref(),rp);
-
-            if (result)
-               rp.clear();
-         }
-         else
-            next_token();
-
-         return result;
-      }
-
-      inline expression_node_ptr parse_const_string()
-      {
-         const std::string const_str = current_token_.value;
-         expression_node_ptr result = expression_generator_(const_str);
-
-         if (peek_token_is(token_t::e_lsqrbracket))
-         {
-            next_token();
-
-            if (peek_token_is(token_t::e_rsqrbracket))
-            {
-               next_token();
-               next_token();
-
-               free_node(node_allocator_,result);
-
-               return expression_generator_(T(const_str.size()));
-            }
-
-            range_t rp;
-
-            if (!parse_range(rp))
-            {
-               free_node(node_allocator_,result);
-
-               return error_node();
-            }
-
-            free_node(node_allocator_,result);
-
-            if (rp.n1_c.first && (rp.n1_c.second == std::numeric_limits<std::size_t>::max()))
-            {
-               rp.n1_c.second  = const_str.size() - 1;
-               rp.cache.second = rp.n1_c.second;
-            }
-
-            if (
-                 (rp.n0_c.first && (rp.n0_c.second >= const_str.size())) ||
-                 (rp.n1_c.first && (rp.n1_c.second >= const_str.size()))
-               )
-            {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token_,
-                             "ERR95 - Overflow in range for string: '" + const_str + "'[" +
-                             (rp.n0_c.first ? details::to_str(rp.n0_c.second) : "?") + ":" +
-                             (rp.n1_c.first ? details::to_str(rp.n1_c.second) : "?") + "]"));
-
-               return error_node();
-            }
-
-            result = expression_generator_(const_str,rp);
-
-            if (result)
-               rp.clear();
-         }
-         else
-            next_token();
-
-         return result;
-      }
-
-      inline expression_node_ptr parse_vector()
-      {
-         const std::string symbol = current_token_.value;
-
-         vector_holder_ptr vec = vector_holder_ptr(0);
-
-         const scope_element& se = sem_.get_element(symbol);
-
-         if (
-              (se.name != symbol)       ||
-              (se.depth > scope_depth_) ||
-              (scope_element::e_vector != se.type)
-            )
-         {
-            if (0 == (vec = symbol_table_.get_vector(symbol)))
-            {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token_,
-                             "ERR96 - Symbol '" + symbol+ " not a vector"));
-
-               return error_node();
+                return 0;
+        }
+#endif
+        
+        inline std::size_t function_count() const
+        {
+            if (valid())
+                return local_data().function_store.size;
+            else
+                return 0;
+        }
+        
+        inline std::size_t vector_count() const
+        {
+            if (valid())
+                return local_data().vector_store.size;
+            else
+                return 0;
+        }
+        
+        inline variable_ptr get_variable(const std::string& variable_name) const
+        {
+            if (!valid())
+                return reinterpret_cast<variable_ptr>(0);
+            else if (!valid_symbol(variable_name))
+                return reinterpret_cast<variable_ptr>(0);
+            else
+                return local_data().variable_store.get(variable_name);
+        }
+        
+        inline variable_ptr get_variable(const T& var_ref) const
+        {
+            if (!valid())
+                return reinterpret_cast<variable_ptr>(0);
+            else
+                return local_data().variable_store.get_from_varptr(
+                                                                   reinterpret_cast<const void*>(&var_ref));
+        }
+        
+#ifndef exprtk_disable_string_capabilities
+        inline stringvar_ptr get_stringvar(const std::string& string_name) const
+        {
+            if (!valid())
+                return reinterpret_cast<stringvar_ptr>(0);
+            else if (!valid_symbol(string_name))
+                return reinterpret_cast<stringvar_ptr>(0);
+            else
+                return local_data().stringvar_store.get(string_name);
+        }
+#endif
+        
+        inline function_ptr get_function(const std::string& function_name) const
+        {
+            if (!valid())
+                return reinterpret_cast<function_ptr>(0);
+            else if (!valid_symbol(function_name))
+                return reinterpret_cast<function_ptr>(0);
+            else
+                return local_data().function_store.get(function_name);
+        }
+        
+        inline vararg_function_ptr get_vararg_function(const std::string& vararg_function_name) const
+        {
+            if (!valid())
+                return reinterpret_cast<vararg_function_ptr>(0);
+            else if (!valid_symbol(vararg_function_name))
+                return reinterpret_cast<vararg_function_ptr>(0);
+            else
+                return local_data().vararg_function_store.get(vararg_function_name);
+        }
+        
+        inline generic_function_ptr get_generic_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().generic_function_store.get(function_name);
+        }
+        
+        inline generic_function_ptr get_string_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().string_function_store.get(function_name);
+        }
+        
+        typedef vector_holder_t* vector_holder_ptr;
+        
+        inline vector_holder_ptr get_vector(const std::string& vector_name) const
+        {
+            if (!valid())
+                return reinterpret_cast<vector_holder_ptr>(0);
+            else if (!valid_symbol(vector_name))
+                return reinterpret_cast<vector_holder_ptr>(0);
+            else
+                return local_data().vector_store.get(vector_name);
+        }
+        
+        inline T& variable_ref(const std::string& symbol_name)
+        {
+            static T null_var = T(0);
+            if (!valid())
+                return null_var;
+            else if (!valid_symbol(symbol_name))
+                return null_var;
+            else
+                return local_data().variable_store.type_ref(symbol_name);
+        }
+        
+#ifndef exprtk_disable_string_capabilities
+        inline std::string& stringvar_ref(const std::string& symbol_name)
+        {
+            static std::string null_stringvar;
+            if (!valid())
+                return null_stringvar;
+            else if (!valid_symbol(symbol_name))
+                return null_stringvar;
+            else
+                return local_data().stringvar_store.type_ref(symbol_name);
+        }
+#endif
+        
+        inline bool is_constant_node(const std::string& symbol_name) const
+        {
+            if (!valid())
+                return false;
+            else if (!valid_symbol(symbol_name))
+                return false;
+            else
+                return local_data().variable_store.is_constant(symbol_name);
+        }
+        
+#ifndef exprtk_disable_string_capabilities
+        inline bool is_constant_string(const std::string& symbol_name) const
+        {
+            if (!valid())
+                return false;
+            else if (!valid_symbol(symbol_name))
+                return false;
+            else if (!local_data().stringvar_store.symbol_exists(symbol_name))
+                return false;
+            else
+                return local_data().stringvar_store.is_constant(symbol_name);
+        }
+#endif
+        
+        inline bool create_variable(const std::string& variable_name, const T& value = T(0))
+        {
+            if (!valid())
+                return false;
+            else if (!valid_symbol(variable_name))
+                return false;
+            else if (symbol_exists(variable_name))
+                return false;
+            
+            local_data().local_symbol_list_.push_back(value);
+            T& t = local_data().local_symbol_list_.back();
+            
+            return add_variable(variable_name,t);
+        }
+        
+#ifndef exprtk_disable_string_capabilities
+        inline bool create_stringvar(const std::string& stringvar_name, const std::string& value = std::string(""))
+        {
+            if (!valid())
+                return false;
+            else if (!valid_symbol(stringvar_name))
+                return false;
+            else if (symbol_exists(stringvar_name))
+                return false;
+            
+            local_data().local_stringvar_list_.push_back(value);
+            std::string& s = local_data().local_stringvar_list_.back();
+            
+            return add_stringvar(stringvar_name,s);
+        }
+#endif
+        
+        inline bool add_variable(const std::string& variable_name, T& t, const bool is_constant = false)
+        {
+            if (!valid())
+                return false;
+            else if (!valid_symbol(variable_name))
+                return false;
+            else if (symbol_exists(variable_name))
+                return false;
+            else
+                return local_data().variable_store.add(variable_name,t,is_constant);
+        }
+        
+        inline bool add_constant(const std::string& constant_name, const T& value)
+        {
+            if (!valid())
+                return false;
+            else if (!valid_symbol(constant_name))
+                return false;
+            else if (symbol_exists(constant_name))
+                return false;
+            
+            local_data().local_symbol_list_.push_back(value);
+            T& t = local_data().local_symbol_list_.back();
+            
+            return add_variable(constant_name,t,true);
+        }
+        
+#ifndef exprtk_disable_string_capabilities
+        inline bool add_stringvar(const std::string& stringvar_name, std::string& s, const bool is_constant = false)
+        {
+            if (!valid())
+                return false;
+            else if (!valid_symbol(stringvar_name))
+                return false;
+            else if (symbol_exists(stringvar_name))
+                return false;
+            else
+                return local_data().stringvar_store.add(stringvar_name,s,is_constant);
+        }
+#endif
+        
+        inline bool add_function(const std::string& function_name, function_t& function)
+        {
+            if (!valid())
+                return false;
+            else if (!valid_symbol(function_name))
+                return false;
+            else if (symbol_exists(function_name))
+                return false;
+            else
+                return local_data().function_store.add(function_name,function);
+        }
+        
+        inline bool add_function(const std::string& vararg_function_name, vararg_function_t& vararg_function)
+        {
+            if (!valid())
+                return false;
+            else if (!valid_symbol(vararg_function_name))
+                return false;
+            else if (symbol_exists(vararg_function_name))
+                return false;
+            else
+                return local_data().vararg_function_store.add(vararg_function_name,vararg_function);
+        }
+        
+        inline bool add_function(const std::string& function_name, generic_function_t& function)
+        {
+            if (!valid())
+                return false;
+            else if (!valid_symbol(function_name))
+                return false;
+            else if (symbol_exists(function_name))
+                return false;
+            else if (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
+                return false;
+        }
+        
+        inline bool add_function(const std::string& function_name, ff1_functor function)
+        {
+            if (!valid())
+                return false;
+            else if (!valid_symbol(function_name))
+                return false;
+            else if (symbol_exists(function_name))
+                return false;
+            
+            exprtk::ifunction<T>* ifunc = new freefunc1(function);
+            
+            local_data().free_function_list_.push_back(ifunc);
+            
+            return add_function(function_name,(*local_data().free_function_list_.back()));
+        }
+        
+        inline bool add_function(const std::string& function_name, ff2_functor function)
+        {
+            if (!valid())
+                return false;
+            else if (!valid_symbol(function_name))
+                return false;
+            else if (symbol_exists(function_name))
+                return false;
+            
+            exprtk::ifunction<T>* ifunc = new freefunc2(function);
+            
+            local_data().free_function_list_.push_back(ifunc);
+            
+            return add_function(function_name,(*local_data().free_function_list_.back()));
+        }
+        
+        inline bool add_function(const std::string& function_name, ff3_functor function)
+        {
+            if (!valid())
+                return false;
+            else if (!valid_symbol(function_name))
+                return false;
+            else if (symbol_exists(function_name))
+                return false;
+            
+            exprtk::ifunction<T>* ifunc = new freefunc3(function);
+            
+            local_data().free_function_list_.push_back(ifunc);
+            
+            return add_function(function_name,(*local_data().free_function_list_.back()));
+        }
+        
+        inline bool add_function(const std::string& function_name, ff4_functor function)
+        {
+            if (!valid())
+                return false;
+            else if (!valid_symbol(function_name))
+                return false;
+            else if (symbol_exists(function_name))
+                return false;
+            
+            exprtk::ifunction<T>* ifunc = new freefunc4(function);
+            
+            local_data().free_function_list_.push_back(ifunc);
+            
+            return add_function(function_name,(*local_data().free_function_list_.back()));
+        }
+        
+        inline bool add_function(const std::string& function_name, ff5_functor function)
+        {
+            if (!valid())
+                return false;
+            else if (!valid_symbol(function_name))
+                return false;
+            else if (symbol_exists(function_name))
+                return false;
+            
+            exprtk::ifunction<T>* ifunc = new freefunc5(function);
+            
+            local_data().free_function_list_.push_back(ifunc);
+            
+            return add_function(function_name,(*local_data().free_function_list_.back()));
+        }
+        
+        inline bool add_function(const std::string& function_name, ff6_functor function)
+        {
+            if (!valid())
+                return false;
+            else if (!valid_symbol(function_name))
+                return false;
+            else if (symbol_exists(function_name))
+                return false;
+            
+            exprtk::ifunction<T>* ifunc = new freefunc6(function);
+            
+            local_data().free_function_list_.push_back(ifunc);
+            
+            return add_function(function_name,(*local_data().free_function_list_.back()));
+        }
+        
+        inline bool add_reserved_function(const std::string& function_name, function_t& function)
+        {
+            if (!valid())
+                return false;
+            else if (!valid_symbol(function_name,false))
+                return false;
+            else if (symbol_exists(function_name,false))
+                return false;
+            else
+                return local_data().function_store.add(function_name,function);
+        }
+        
+        inline bool add_reserved_function(const std::string& vararg_function_name, vararg_function_t& vararg_function)
+        {
+            if (!valid())
+                return false;
+            else if (!valid_symbol(vararg_function_name,false))
+                return false;
+            else if (symbol_exists(vararg_function_name,false))
+                return false;
+            else
+                return local_data().vararg_function_store.add(vararg_function_name,vararg_function);
+        }
+        
+        inline bool add_reserved_function(const std::string& function_name, generic_function_t& function)
+        {
+            if (!valid())
+                return false;
+            else if (!valid_symbol(function_name,false))
+                return false;
+            else if (symbol_exists(function_name,false))
+                return false;
+            else if (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
+                return false;
+        }
+        
+        template <std::size_t N>
+        inline bool add_vector(const std::string& vector_name, T (&v)[N])
+        {
+            if (!valid())
+                return false;
+            else if (!valid_symbol(vector_name))
+                return false;
+            else if (symbol_exists(vector_name))
+                return false;
+            else
+                return local_data().vector_store.add(vector_name,v);
+        }
+        
+        inline bool add_vector(const std::string& vector_name, T* v, const std::size_t& v_size)
+        {
+            if (!valid())
+                return false;
+            else if (!valid_symbol(vector_name))
+                return false;
+            else if (symbol_exists(vector_name))
+                return false;
+            else
+                return local_data().vector_store.add(vector_name,v,v_size);
+        }
+        
+        template <typename Allocator>
+        inline bool add_vector(const std::string& vector_name, std::vector<T,Allocator>& v)
+        {
+            if (!valid())
+                return false;
+            else if (!valid_symbol(vector_name))
+                return false;
+            else if (symbol_exists(vector_name))
+                return false;
+            else
+                return local_data().vector_store.add(vector_name,v);
+        }
+        
+        inline bool add_vector(const std::string& vector_name, exprtk::vector_view<T>& v)
+        {
+            if (!valid())
+                return false;
+            else if (!valid_symbol(vector_name))
+                return false;
+            else if (symbol_exists(vector_name))
+                return false;
+            else
+                return local_data().vector_store.add(vector_name,v);
+        }
+        
+        inline bool remove_variable(const std::string& variable_name, const bool delete_node = true)
+        {
+            if (!valid())
+                return false;
+            else
+                return local_data().variable_store.remove(variable_name, delete_node);
+        }
+        
+#ifndef exprtk_disable_string_capabilities
+        inline bool remove_stringvar(const std::string& string_name)
+        {
+            if (!valid())
+                return false;
+            else
+                return local_data().stringvar_store.remove(string_name);
+        }
+#endif
+        
+        inline bool remove_function(const std::string& function_name)
+        {
+            if (!valid())
+                return false;
+            else
+                return local_data().function_store.remove(function_name);
+        }
+        
+        inline bool remove_vararg_function(const std::string& vararg_function_name)
+        {
+            if (!valid())
+                return false;
+            else
+                return local_data().vararg_function_store.remove(vararg_function_name);
+        }
+        
+        inline bool remove_vector(const std::string& vector_name)
+        {
+            if (!valid())
+                return false;
+            else
+                return local_data().vector_store.remove(vector_name);
+        }
+        
+        inline bool add_constants()
+        {
+            return add_pi      () &&
+            add_epsilon () &&
+            add_infinity();
+        }
+        
+        inline bool add_pi()
+        {
+            static const T local_pi = T(details::numeric::constant::pi);
+            return add_constant("pi",local_pi);
+        }
+        
+        inline bool add_epsilon()
+        {
+            static const T local_epsilon = details::numeric::details::epsilon_type<T>::value();
+            return add_constant("epsilon",local_epsilon);
+        }
+        
+        inline bool add_infinity()
+        {
+            static const T local_infinity = std::numeric_limits<T>::infinity();
+            return add_constant("inf",local_infinity);
+        }
+        
+        template <typename Package>
+        inline bool add_package(Package& package)
+        {
+            return package.register_package(*this);
+        }
+        
+        template <typename Allocator,
+        template <typename, typename> class Sequence>
+        inline std::size_t get_variable_list(Sequence<std::pair<std::string,T>,Allocator>& vlist) const
+        {
+            if (!valid())
+                return 0;
+            else
+                return local_data().variable_store.get_list(vlist);
+        }
+        
+        template <typename Allocator,
+        template <typename, typename> class Sequence>
+        inline std::size_t get_variable_list(Sequence<std::string,Allocator>& vlist) const
+        {
+            if (!valid())
+                return 0;
+            else
+                return local_data().variable_store.get_list(vlist);
+        }
+        
+#ifndef exprtk_disable_string_capabilities
+        template <typename Allocator,
+        template <typename, typename> class Sequence>
+        inline std::size_t get_stringvar_list(Sequence<std::pair<std::string,std::string>,Allocator>& svlist) const
+        {
+            if (!valid())
+                return 0;
+            else
+                return local_data().stringvar_store.get_list(svlist);
+        }
+        
+        template <typename Allocator,
+        template <typename, typename> class Sequence>
+        inline std::size_t get_stringvar_list(Sequence<std::string,Allocator>& svlist) const
+        {
+            if (!valid())
+                return 0;
+            else
+                return local_data().stringvar_store.get_list(svlist);
+        }
+#endif
+        
+        template <typename Allocator,
+        template <typename, typename> class Sequence>
+        inline std::size_t get_vector_list(Sequence<std::string,Allocator>& vlist) const
+        {
+            if (!valid())
+                return 0;
+            else
+                return local_data().vector_store.get_list(vlist);
+        }
+        
+        inline bool symbol_exists(const std::string& symbol_name, const bool check_reserved_symb = true) const
+        {
+            /*
+             Function will return true if symbol_name exists as either a
+             reserved symbol, variable, stringvar or function name in any
+             of the type stores.
+             */
+            if (!valid())
+                return false;
+            else if (local_data().variable_store.symbol_exists(symbol_name))
+                return true;
+#ifndef exprtk_disable_string_capabilities
+            else if (local_data().stringvar_store.symbol_exists(symbol_name))
+                return true;
+#endif
+            else if (local_data().function_store.symbol_exists(symbol_name))
+                return true;
+            else if (check_reserved_symb && local_data().is_reserved_symbol(symbol_name))
+                return true;
+            else
+                return false;
+        }
+        
+        inline bool is_variable(const std::string& variable_name) const
+        {
+            if (!valid())
+                return false;
+            else
+                return local_data().variable_store.symbol_exists(variable_name);
+        }
+        
+#ifndef exprtk_disable_string_capabilities
+        inline bool is_stringvar(const std::string& stringvar_name) const
+        {
+            if (!valid())
+                return false;
+            else
+                return local_data().stringvar_store.symbol_exists(stringvar_name);
+        }
+        
+        inline bool is_conststr_stringvar(const std::string& symbol_name) const
+        {
+            if (!valid())
+                return false;
+            else if (!valid_symbol(symbol_name))
+                return false;
+            else if (!local_data().stringvar_store.symbol_exists(symbol_name))
+                return false;
+            
+            return (
+                    local_data().stringvar_store.symbol_exists(symbol_name) ||
+                    local_data().stringvar_store.is_constant  (symbol_name)
+                    );
+        }
+#endif
+        
+        inline bool is_function(const std::string& function_name) const
+        {
+            if (!valid())
+                return false;
+            else
+                return local_data().function_store.symbol_exists(function_name);
+        }
+        
+        inline bool is_vararg_function(const std::string& vararg_function_name) const
+        {
+            if (!valid())
+                return false;
+            else
+                return local_data().vararg_function_store.symbol_exists(vararg_function_name);
+        }
+        
+        inline bool is_vector(const std::string& vector_name) const
+        {
+            if (!valid())
+                return false;
+            else
+                return local_data().vector_store.symbol_exists(vector_name);
+        }
+        
+        inline std::string get_variable_name(const expression_ptr& ptr) const
+        {
+            return local_data().variable_store.entity_name(ptr);
+        }
+        
+        inline std::string get_vector_name(const vector_holder_ptr& ptr) const
+        {
+            return local_data().vector_store.entity_name(ptr);
+        }
+        
+#ifndef exprtk_disable_string_capabilities
+        inline std::string get_stringvar_name(const expression_ptr& ptr) const
+        {
+            return local_data().stringvar_store.entity_name(ptr);
+        }
+        
+        inline std::string get_conststr_stringvar_name(const expression_ptr& ptr) const
+        {
+            return local_data().stringvar_store.entity_name(ptr);
+        }
+#endif
+        
+        inline bool valid() const
+        {
+            // Symbol table sanity check.
+            return control_block_ && control_block_->data_;
+        }
+        
+        inline void load_from(const symbol_table<T>& st)
+        {
+            {
+                std::vector<std::string> name_list;
+                
+                st.local_data().function_store.get_list(name_list);
+                
+                if (!name_list.empty())
+                {
+                    for (std::size_t i = 0; i < name_list.size(); ++i)
+                    {
+                        exprtk::ifunction<T>& ifunc = *st.get_function(name_list[i]);
+                        add_function(name_list[i],ifunc);
+                    }
+                }
+            }
+            
+            {
+                std::vector<std::string> name_list;
+                
+                st.local_data().vararg_function_store.get_list(name_list);
+                
+                if (!name_list.empty())
+                {
+                    for (std::size_t i = 0; i < name_list.size(); ++i)
+                    {
+                        exprtk::ivararg_function<T>& ivafunc = *st.get_vararg_function(name_list[i]);
+                        add_function(name_list[i],ivafunc);
+                    }
+                }
+            }
+            
+            {
+                std::vector<std::string> name_list;
+                
+                st.local_data().generic_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_generic_function(name_list[i]);
+                        add_function(name_list[i],ifunc);
+                    }
+                }
+            }
+            
+            {
+                std::vector<std::string> name_list;
+                
+                st.local_data().string_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_string_function(name_list[i]);
+                        add_function(name_list[i],ifunc);
+                    }
+                }
+            }
+        }
+        
+    private:
+        
+        inline bool valid_symbol(const std::string& symbol, const bool check_reserved_symb = true) const
+        {
+            if (symbol.empty())
+                return false;
+            else if (!details::is_letter(symbol[0]))
+                return false;
+            else if (symbol.size() > 1)
+            {
+                for (std::size_t i = 1; i < symbol.size(); ++i)
+                {
+                    if (
+                        !details::is_letter_or_digit(symbol[i]) &&
+                        ('_' != symbol[i])
+                        )
+                    {
+                        if (('.' == symbol[i]) && (i < (symbol.size() - 1)))
+                            continue;
+                        else
+                            return false;
+                    }
+                }
+            }
+            
+            return (check_reserved_symb) ? (!local_data().is_reserved_symbol(symbol)) : true;
+        }
+        
+        inline bool valid_function(const std::string& symbol) const
+        {
+            if (symbol.empty())
+                return false;
+            else if (!details::is_letter(symbol[0]))
+                return false;
+            else if (symbol.size() > 1)
+            {
+                for (std::size_t i = 1; i < symbol.size(); ++i)
+                {
+                    if (
+                        !details::is_letter_or_digit(symbol[i]) &&
+                        ('_' != symbol[i])
+                        )
+                    {
+                        if (('.' == symbol[i]) && (i < (symbol.size() - 1)))
+                            continue;
+                        else
+                            return false;
+                    }
+                }
             }
-         }
-         else
-            vec = se.vec_node;
-
-         expression_node_ptr index_expr = error_node();
-
-         next_token();
-
-         if (!token_is(token_t::e_lsqrbracket))
-         {
-            return node_allocator_.allocate<vector_node_t>(vec);
-         }
-         else if (token_is(token_t::e_rsqrbracket))
-         {
-            return expression_generator_(T(vec->size()));
-         }
-         else if (0 == (index_expr = parse_expression()))
-         {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token_,
-                          "ERR97 - Failed to parse index for vector: '" + symbol + "'"));
-
-            return error_node();
-         }
-         else if (!token_is(token_t::e_rsqrbracket))
-         {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token_,
-                          "ERR98 - Expected ']' for index of vector: '" + symbol + "'"));
-
-            free_node(node_allocator_,index_expr);
-
-            return error_node();
-         }
-
-         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)
-      {
-         std::vector<expression_node_ptr> arg_list;
-         expression_node_ptr result = error_node();
-
-         scoped_vec_delete<expression_node_t> sdd(*this,arg_list);
-
-         next_token();
-
-         if (token_is(token_t::e_lbracket))
-         {
-            if (!token_is(token_t::e_rbracket))
+            
+            return true;
+        }
+        
+        typedef typename control_block::st_data local_data_t;
+        
+        inline local_data_t& local_data()
+        {
+            return *(control_block_->data_);
+        }
+        
+        inline const local_data_t& local_data() const
+        {
+            return *(control_block_->data_);
+        }
+        
+        control_block* control_block_;
+        
+        friend class parser<T>;
+    };
+    
+    template <typename T>
+    class function_compositor;
+    
+    template <typename T>
+    class expression
+    {
+    private:
+        
+        typedef details::expression_node<T>*  expression_ptr;
+        typedef details::vector_holder<T>* vector_holder_ptr;
+        typedef std::vector<symbol_table<T> >  symtab_list_t;
+        
+        struct control_block
+        {
+            enum data_type
+            {
+                e_unknown  ,
+                e_expr     ,
+                e_vecholder,
+                e_data     ,
+                e_vecdata  ,
+                e_string
+            };
+            
+            struct data_pack
+            {
+                data_pack()
+                : pointer(0),
+                type(e_unknown),
+                size(0)
+                {}
+                
+                data_pack(void* ptr, data_type dt, std::size_t sz = 0)
+                : pointer(ptr),
+                type(dt),
+                size(sz)
+                {}
+                
+                void*       pointer;
+                data_type   type;
+                std::size_t size;
+            };
+            
+            typedef std::vector<data_pack> local_data_list_t;
+            typedef results_context<T>     results_context_t;
+            
+            control_block()
+            : ref_count(0),
+            expr     (0),
+            results  (0),
+            retinv_null(false),
+            return_invoked(&retinv_null)
+            {}
+            
+            control_block(expression_ptr e)
+            : ref_count(1),
+            expr     (e),
+            results  (0),
+            retinv_null(false),
+            return_invoked(&retinv_null)
+            {}
+            
+            ~control_block()
+            {
+                if (expr && details::branch_deletable(expr))
+                {
+                    delete expr;
+                    expr = reinterpret_cast<expression_ptr>(0);
+                }
+                
+                if (!local_data_list.empty())
+                {
+                    for (std::size_t i = 0; i < local_data_list.size(); ++i)
+                    {
+                        switch (local_data_list[i].type)
+                        {
+                            case e_expr      : delete reinterpret_cast<expression_ptr>(local_data_list[i].pointer);
+                                break;
+                                
+                            case e_vecholder : delete reinterpret_cast<vector_holder_ptr>(local_data_list[i].pointer);
+                                break;
+                                
+                            case e_data      : delete (T*)(local_data_list[i].pointer);
+                                break;
+                                
+                            case e_vecdata   : delete [] (T*)(local_data_list[i].pointer);
+                                break;
+                                
+                            case e_string    : delete (std::string*)(local_data_list[i].pointer);
+                                break;
+                                
+                            default          : break;
+                        }
+                    }
+                }
+                
+                if (results)
+                {
+                    delete results;
+                }
+            }
+            
+            static inline control_block* create(expression_ptr e)
+            {
+                return new control_block(e);
+            }
+            
+            static inline void destroy(control_block*& cntrl_blck)
+            {
+                if (cntrl_blck)
+                {
+                    if (
+                        (0 !=   cntrl_blck->ref_count) &&
+                        (0 == --cntrl_blck->ref_count)
+                        )
+                    {
+                        delete cntrl_blck;
+                    }
+                    
+                    cntrl_blck = 0;
+                }
+            }
+            
+            std::size_t ref_count;
+            expression_ptr expr;
+            local_data_list_t local_data_list;
+            results_context_t* results;
+            bool  retinv_null;
+            bool* return_invoked;
+            
+            friend class function_compositor<T>;
+        };
+        
+    public:
+        
+        expression()
+        : control_block_(0)
+        {
+            set_expression(new details::null_node<T>());
+        }
+        
+        expression(const expression<T>& e)
+        : control_block_(e.control_block_),
+        symbol_table_list_(e.symbol_table_list_)
+        {
+            control_block_->ref_count++;
+        }
+        
+        inline expression<T>& operator=(const expression<T>& e)
+        {
+            if (this != &e)
+            {
+                if (control_block_)
+                {
+                    if (
+                        (0 !=   control_block_->ref_count) &&
+                        (0 == --control_block_->ref_count)
+                        )
+                    {
+                        delete control_block_;
+                    }
+                    
+                    control_block_ = 0;
+                }
+                
+                control_block_ = e.control_block_;
+                control_block_->ref_count++;
+                symbol_table_list_ = e.symbol_table_list_;
+            }
+            
+            return *this;
+        }
+        
+        inline bool operator==(const expression<T>& e)
+        {
+            return (this == &e);
+        }
+        
+        inline bool operator!() const
+        {
+            return (
+                    (0 == control_block_      ) ||
+                    (0 == control_block_->expr)
+                    );
+        }
+        
+        inline expression<T>& release()
+        {
+            control_block::destroy(control_block_);
+            
+            return *this;
+        }
+        
+        ~expression()
+        {
+            control_block::destroy(control_block_);
+        }
+        
+        inline T value() const
+        {
+            return control_block_->expr->value();
+        }
+        
+        inline T operator()() const
+        {
+            return value();
+        }
+        
+        inline operator T() const
+        {
+            return value();
+        }
+        
+        inline operator bool() const
+        {
+            return details::is_true(value());
+        }
+        
+        inline void register_symbol_table(symbol_table<T>& st)
+        {
+            symbol_table_list_.push_back(st);
+        }
+        
+        inline const symbol_table<T>& get_symbol_table(const std::size_t& index = 0) const
+        {
+            return symbol_table_list_[index];
+        }
+        
+        inline symbol_table<T>& get_symbol_table(const std::size_t& index = 0)
+        {
+            return symbol_table_list_[index];
+        }
+        
+        typedef results_context<T> results_context_t;
+        
+        inline const results_context_t& results() const
+        {
+            if (control_block_->results)
+                return (*control_block_->results);
+            else
             {
-               for ( ; ; )
-               {
-                  expression_node_ptr arg = parse_expression();
-
-                  if (0 == arg)
-                     return error_node();
-                  else
-                     arg_list.push_back(arg);
-
-                  if (token_is(token_t::e_rbracket))
-                     break;
-                  else if (!token_is(token_t::e_comma))
-                  {
-                     set_error(
-                        make_error(parser_error::e_syntax,
-                                   current_token_,
-                                   "ERR99 - Expected ',' for call to vararg function: " + vararg_function_name));
-
-                     return error_node();
-                  }
-               }
+                static const results_context_t null_results;
+                return null_results;
+            }
+        }
+        
+        inline bool return_invoked() const
+        {
+            return (*control_block_->return_invoked);
+        }
+        
+    private:
+        
+        inline symtab_list_t get_symbol_table_list() const
+        {
+            return symbol_table_list_;
+        }
+        
+        inline void set_expression(const expression_ptr expr)
+        {
+            if (expr)
+            {
+                if (control_block_)
+                {
+                    if (0 == --control_block_->ref_count)
+                    {
+                        delete control_block_;
+                    }
+                }
+                
+                control_block_ = control_block::create(expr);
+            }
+        }
+        
+        inline void register_local_var(expression_ptr expr)
+        {
+            if (expr)
+            {
+                if (control_block_)
+                {
+                    control_block_->
+                    local_data_list.push_back(
+                                              typename expression<T>::control_block::
+                                              data_pack(reinterpret_cast<void*>(expr),
+                                                        control_block::e_expr));
+                }
+            }
+        }
+        
+        inline void register_local_var(vector_holder_ptr vec_holder)
+        {
+            if (vec_holder)
+            {
+                if (control_block_)
+                {
+                    control_block_->
+                    local_data_list.push_back(
+                                              typename expression<T>::control_block::
+                                              data_pack(reinterpret_cast<void*>(vec_holder),
+                                                        control_block::e_vecholder));
+                }
+            }
+        }
+        
+        inline void register_local_data(void* data, const std::size_t& size = 0, const std::size_t data_mode = 0)
+        {
+            if (data)
+            {
+                if (control_block_)
+                {
+                    typename control_block::data_type dt = control_block::e_data;
+                    
+                    switch (data_mode)
+                    {
+                        case 0 : dt = control_block::e_data;    break;
+                        case 1 : dt = control_block::e_vecdata; break;
+                        case 2 : dt = control_block::e_string;  break;
+                    }
+                    
+                    control_block_->
+                    local_data_list.push_back(
+                                              typename expression<T>::control_block::
+                                              data_pack(reinterpret_cast<void*>(data),dt,size));
+                }
+            }
+        }
+        
+        inline const typename control_block::local_data_list_t& local_data_list()
+        {
+            if (control_block_)
+            {
+                return control_block_->local_data_list;
             }
-         }
-
-         result = expression_generator_.vararg_function_call(vararg_function,arg_list);
-
-         sdd.delete_ptr = (0 == result);
-
-         return result;
-      }
-
-      class type_checker
-      {
-      public:
-
-         typedef parser<T> parser_t;
-         typedef std::vector<std::string> param_seq_list_t;
-
-         type_checker(parser_t& p,
-                      const std::string& func_name,
-                      const std::string& param_seq)
-         : invalid_state_(true),
-           parser_(p),
-           function_name_(func_name)
-         {
-            split(param_seq);
-         }
-
-         bool verify(const std::string& param_seq, std::size_t& pseq_index)
-         {
-            if (param_seq_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)
+            else
             {
-               std::size_t diff_index = 0;
-               char        diff_value = 0;
-
-               bool result = details::sequence_match(param_seq_list_[i],
-                                                     param_seq,
-                                                     diff_index,diff_value);
-
-              if (result)
-              {
-                 pseq_index = i;
-                 return true;
-              }
-              else
-                 error_list.push_back(std::make_pair(diff_index,diff_value));
+                static typename control_block::local_data_list_t null_local_data_list;
+                return null_local_data_list;
+            }
+        }
+        
+        inline void register_return_results(results_context_t* rc)
+        {
+            if (control_block_ && rc)
+            {
+                control_block_->results = rc;
+            }
+        }
+        
+        inline void set_retinvk(bool* retinvk_ptr)
+        {
+            if (control_block_)
+            {
+                control_block_->return_invoked = retinvk_ptr;
+            }
+        }
+        
+        control_block* control_block_;
+        symtab_list_t      symbol_table_list_;
+        
+        friend class parser<T>;
+        friend class expression_helper<T>;
+        friend class function_compositor<T>;
+    };
+    
+    template <typename T>
+    class expression_helper
+    {
+    public:
+        
+        static inline bool is_constant(const expression<T>& expr)
+        {
+            return details::is_constant_node(expr.control_block_->expr);
+        }
+        
+        static inline bool is_variable(const expression<T>& expr)
+        {
+            return details::is_variable_node(expr.control_block_->expr);
+        }
+        
+        static inline bool is_unary(const expression<T>& expr)
+        {
+            return details::is_unary_node(expr.control_block_->expr);
+        }
+        
+        static inline bool is_binary(const expression<T>& expr)
+        {
+            return details::is_binary_node(expr.control_block_->expr);
+        }
+        
+        static inline bool is_function(const expression<T>& expr)
+        {
+            return details::is_function(expr.control_block_->expr);
+        }
+        
+        static inline bool is_null(const expression<T>& expr)
+        {
+            return details::is_null_node(expr.control_block_->expr);
+        }
+    };
+    
+    template <typename T>
+    inline bool is_valid(const expression<T>& expr)
+    {
+        return !expression_helper<T>::is_null(expr);
+    }
+    
+    namespace parser_error
+    {
+        enum error_mode
+        {
+            e_unknown = 0,
+            e_syntax  = 1,
+            e_token   = 2,
+            e_numeric = 4,
+            e_symtab  = 5,
+            e_lexer   = 6,
+            e_helper  = 7
+        };
+        
+        struct type
+        {
+            type()
+            : mode(parser_error::e_unknown),
+            line_no  (0),
+            column_no(0)
+            {}
+            
+            lexer::token token;
+            error_mode mode;
+            std::string diagnostic;
+            std::string error_line;
+            std::size_t line_no;
+            std::size_t column_no;
+        };
+        
+        inline type make_error(error_mode mode, const std::string& diagnostic = "")
+        {
+            type t;
+            t.mode       = mode;
+            t.token.type = lexer::token::e_error;
+            t.diagnostic = diagnostic;
+            exprtk_debug(("%s\n",diagnostic .c_str()));
+            return t;
+        }
+        
+        inline type make_error(error_mode mode, const lexer::token& tk, const std::string& diagnostic = "")
+        {
+            type t;
+            t.mode       = mode;
+            t.token      = tk;
+            t.diagnostic = diagnostic;
+            exprtk_debug(("%s\n",diagnostic .c_str()));
+            return t;
+        }
+        
+        inline std::string to_str(error_mode mode)
+        {
+            switch (mode)
+            {
+                case e_unknown : return std::string("Unknown Error");
+                case e_syntax  : return std::string("Syntax Error" );
+                case e_token   : return std::string("Token Error"  );
+                case e_numeric : return std::string("Numeric Error");
+                case e_symtab  : return std::string("Symbol Error" );
+                case e_lexer   : return std::string("Lexer Error"  );
+                case e_helper  : return std::string("Helper Error" );
+                default        : return std::string("Unknown Error");
+            }
+        }
+        
+        inline bool update_error(type& error, const std::string& expression)
+        {
+            if (
+                expression.empty()                         ||
+                (error.token.position > expression.size()) ||
+                (std::numeric_limits<std::size_t>::max() == error.token.position)
+                )
+            {
+                return false;
+            }
+            
+            std::size_t error_line_start = 0;
+            
+            for (std::size_t i = error.token.position; i > 0; --i)
+            {
+                const details::char_t c = expression[i];
+                
+                if (('\n' == c) || ('\r' == c))
+                {
+                    error_line_start = i + 1;
+                    break;
+                }
+            }
+            
+            std::size_t next_nl_position = std::min(expression.size(),
+                                                    expression.find_first_of('\n',error.token.position + 1));
+            
+            error.column_no  = error.token.position - error_line_start;
+            error.error_line = expression.substr(error_line_start,
+                                                 next_nl_position - error_line_start);
+            
+            error.line_no = 0;
+            
+            for (std::size_t i = 0; i < next_nl_position; ++i)
+            {
+                if ('\n' == expression[i])
+                    ++error.line_no;
+            }
+            
+            return true;
+        }
+        
+        inline void dump_error(const type& error)
+        {
+            printf("Position: %02d   Type: [%s]   Msg: %s\n",
+                   static_cast<int>(error.token.position),
+                   exprtk::parser_error::to_str(error.mode).c_str(),
+                   error.diagnostic.c_str());
+        }
+    }
+    
+    template <typename T>
+    class parser : public lexer::parser_helper
+    {
+    private:
+        
+        enum precedence_level
+        {
+            e_level00,
+            e_level01,
+            e_level02,
+            e_level03,
+            e_level04,
+            e_level05,
+            e_level06,
+            e_level07,
+            e_level08,
+            e_level09,
+            e_level10,
+            e_level11,
+            e_level12,
+            e_level13,
+            e_level14
+        };
+        
+        typedef const T&                                               cref_t;
+        typedef const T                                               const_t;
+        typedef ifunction                <T>                                F;
+        typedef ivararg_function         <T>                              VAF;
+        typedef igeneric_function        <T>                               GF;
+        typedef ifunction                <T>                      ifunction_t;
+        typedef ivararg_function         <T>               ivararg_function_t;
+        typedef igeneric_function        <T>              igeneric_function_t;
+        typedef details::expression_node <T>                expression_node_t;
+        typedef details::literal_node    <T>                   literal_node_t;
+        typedef details::unary_node      <T>                     unary_node_t;
+        typedef details::binary_node     <T>                    binary_node_t;
+        typedef details::trinary_node    <T>                   trinary_node_t;
+        typedef details::quaternary_node <T>                quaternary_node_t;
+        typedef details::conditional_node<T>               conditional_node_t;
+        typedef details::cons_conditional_node<T>     cons_conditional_node_t;
+        typedef details::while_loop_node <T>                while_loop_node_t;
+        typedef details::repeat_until_loop_node<T>   repeat_until_loop_node_t;
+        typedef details::for_loop_node   <T>                  for_loop_node_t;
+#ifndef exprtk_disable_break_continue
+        typedef details::while_loop_bc_node <T>          while_loop_bc_node_t;
+        typedef details::repeat_until_loop_bc_node<T> repeat_until_loop_bc_node_t;
+        typedef details::for_loop_bc_node<T>               for_loop_bc_node_t;
+#endif
+        typedef details::switch_node     <T>                    switch_node_t;
+        typedef details::variable_node   <T>                  variable_node_t;
+        typedef details::vector_elem_node<T>               vector_elem_node_t;
+        typedef details::rebasevector_elem_node<T>   rebasevector_elem_node_t;
+        typedef details::rebasevector_celem_node<T> rebasevector_celem_node_t;
+        typedef details::vector_node     <T>                    vector_node_t;
+        typedef details::range_pack      <T>                          range_t;
+#ifndef exprtk_disable_string_capabilities
+        typedef details::stringvar_node     <T>              stringvar_node_t;
+        typedef details::string_literal_node<T>         string_literal_node_t;
+        typedef details::string_range_node  <T>           string_range_node_t;
+        typedef details::const_string_range_node<T> const_string_range_node_t;
+        typedef details::generic_string_range_node<T> generic_string_range_node_t;
+        typedef details::string_concat_node <T>          string_concat_node_t;
+        typedef details::assignment_string_node<T>   assignment_string_node_t;
+        typedef details::assignment_string_range_node<T> assignment_string_range_node_t;
+        typedef details::conditional_string_node<T>  conditional_string_node_t;
+        typedef details::cons_conditional_str_node<T> cons_conditional_str_node_t;
+#endif
+        typedef details::assignment_node<T>                 assignment_node_t;
+        typedef details::assignment_vec_elem_node       <T> assignment_vec_elem_node_t;
+        typedef details::assignment_rebasevec_elem_node <T> assignment_rebasevec_elem_node_t;
+        typedef details::assignment_rebasevec_celem_node<T> assignment_rebasevec_celem_node_t;
+        typedef details::assignment_vec_node     <T>    assignment_vec_node_t;
+        typedef details::assignment_vecvec_node  <T> assignment_vecvec_node_t;
+        typedef details::scand_node<T>                           scand_node_t;
+        typedef details::scor_node<T>                             scor_node_t;
+        typedef lexer::token                                          token_t;
+        typedef expression_node_t*                        expression_node_ptr;
+        typedef symbol_table<T>                                symbol_table_t;
+        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 details::operator_type operator_t;
+        
+        typedef std::map<operator_t,  unary_functor_t>   unary_op_map_t;
+        typedef std::map<operator_t, binary_functor_t>  binary_op_map_t;
+        typedef std::map<operator_t,trinary_functor_t> trinary_op_map_t;
+        
+        typedef std::map<std::string,std::pair<trinary_functor_t   ,operator_t> > sf3_map_t;
+        typedef std::map<std::string,std::pair<quaternary_functor_t,operator_t> > sf4_map_t;
+        
+        typedef std::map<binary_functor_t,operator_t> inv_binary_op_map_t;
+        typedef std::multimap<std::string,details::base_operation_t,details::ilesscompare> base_ops_map_t;
+        typedef std::set<std::string,details::ilesscompare> disabled_func_set_t;
+        
+        typedef details::T0oT1_define<T, cref_t, cref_t> vov_t;
+        typedef details::T0oT1_define<T,const_t, cref_t> cov_t;
+        typedef details::T0oT1_define<T, cref_t,const_t> voc_t;
+        
+        typedef details::T0oT1oT2_define<T, cref_t, cref_t, cref_t> vovov_t;
+        typedef details::T0oT1oT2_define<T, cref_t, cref_t,const_t> vovoc_t;
+        typedef details::T0oT1oT2_define<T, cref_t,const_t, cref_t> vocov_t;
+        typedef details::T0oT1oT2_define<T,const_t, cref_t, cref_t> covov_t;
+        typedef details::T0oT1oT2_define<T,const_t, cref_t,const_t> covoc_t;
+        typedef details::T0oT1oT2_define<T,const_t,const_t, cref_t> cocov_t;
+        typedef details::T0oT1oT2_define<T,cref_t,const_t, const_t> vococ_t;
+        
+        typedef details::T0oT1oT2oT3_define<T, cref_t, cref_t, cref_t, cref_t> vovovov_t;
+        typedef details::T0oT1oT2oT3_define<T, cref_t, cref_t, cref_t,const_t> vovovoc_t;
+        typedef details::T0oT1oT2oT3_define<T, cref_t, cref_t,const_t, cref_t> vovocov_t;
+        typedef details::T0oT1oT2oT3_define<T, cref_t,const_t, cref_t, cref_t> vocovov_t;
+        typedef details::T0oT1oT2oT3_define<T,const_t, cref_t, cref_t, cref_t> covovov_t;
+        
+        typedef details::T0oT1oT2oT3_define<T,const_t, cref_t,const_t, cref_t> covocov_t;
+        typedef details::T0oT1oT2oT3_define<T, cref_t,const_t, cref_t,const_t> vocovoc_t;
+        typedef details::T0oT1oT2oT3_define<T,const_t, cref_t, cref_t,const_t> covovoc_t;
+        typedef details::T0oT1oT2oT3_define<T, cref_t,const_t,const_t, cref_t> vococov_t;
+        
+        typedef results_context<T> results_context_t;
+        
+        typedef parser_helper prsrhlpr_t;
+        
+        struct scope_element
+        {
+            enum element_type
+            {
+                e_none    ,
+                e_variable,
+                e_vector  ,
+                e_vecelem ,
+                e_string
+            };
+            
+            typedef details::vector_holder<T> vector_holder_t;
+            typedef variable_node_t*        variable_node_ptr;
+            typedef vector_holder_t*        vector_holder_ptr;
+            typedef expression_node_t*    expression_node_ptr;
+#ifndef exprtk_disable_string_capabilities
+            typedef stringvar_node_t*      stringvar_node_ptr;
+#endif
+            
+            scope_element()
+            : name("???"),
+            size (std::numeric_limits<std::size_t>::max()),
+            index(std::numeric_limits<std::size_t>::max()),
+            depth(std::numeric_limits<std::size_t>::max()),
+            ref_count(0),
+            ip_index (0),
+            type (e_none),
+            active(false),
+            data    (0),
+            var_node(0),
+            vec_node(0)
+#ifndef exprtk_disable_string_capabilities
+            ,str_node(0)
+#endif
+            {}
+            
+            bool operator < (const scope_element& se) const
+            {
+                if (ip_index < se.ip_index)
+                    return true;
+                else if (ip_index > se.ip_index)
+                    return false;
+                else if (depth < se.depth)
+                    return true;
+                else if (depth > se.depth)
+                    return false;
+                else if (index < se.index)
+                    return true;
+                else if (index > se.index)
+                    return false;
+                else
+                    return (name < se.name);
+            }
+            
+            void clear()
+            {
+                name   = "???";
+                size   = std::numeric_limits<std::size_t>::max();
+                index  = std::numeric_limits<std::size_t>::max();
+                depth  = std::numeric_limits<std::size_t>::max();
+                type   = e_none;
+                active = false;
+                ref_count = 0;
+                ip_index  = 0;
+                data      = 0;
+                var_node  = 0;
+                vec_node  = 0;
+#ifndef exprtk_disable_string_capabilities
+                str_node  = 0;
+#endif
             }
-
-            if (1 == error_list.size())
+            
+            std::string  name;
+            std::size_t  size;
+            std::size_t  index;
+            std::size_t  depth;
+            std::size_t  ref_count;
+            std::size_t  ip_index;
+            element_type type;
+            bool         active;
+            void*        data;
+            expression_node_ptr var_node;
+            vector_holder_ptr   vec_node;
+#ifndef exprtk_disable_string_capabilities
+            stringvar_node_ptr str_node;
+#endif
+        };
+        
+        class scope_element_manager
+        {
+        public:
+            
+            typedef expression_node_t* expression_node_ptr;
+            typedef variable_node_t*     variable_node_ptr;
+            typedef parser<T>                     parser_t;
+            
+            scope_element_manager(parser<T>& p)
+            : parser_(p),
+            input_param_cnt_(0)
+            {}
+            
+            inline std::size_t size() const
             {
-               parser_.
-                  set_error(
-                     make_error(parser_error::e_syntax,
-                                parser_.current_token(),
-                                "ERR100 - Failed parameter type check for function '" + function_name_ + "', "
-                                "Expected '" + param_seq_list_[0] + "'  call set: '" + param_seq +"'"));
+                return element_.size();
+            }
+            
+            inline bool empty() const
+            {
+                return element_.empty();
+            }
+            
+            inline scope_element& get_element(const std::size_t& index)
+            {
+                if (index < element_.size())
+                    return element_[index];
+                else
+                    return null_element_;
+            }
+            
+            inline scope_element& get_element(const std::string& var_name,
+                                              const std::size_t index = std::numeric_limits<std::size_t>::max())
+            {
+                const std::size_t current_depth = parser_.state_.scope_depth;
+                
+                for (std::size_t i = 0; i < element_.size(); ++i)
+                {
+                    scope_element& se = element_[i];
+                    
+                    if (se.depth > current_depth)
+                        continue;
+                    else if (
+                             (se.name  == var_name) &&
+                             (se.index == index)
+                             )
+                        return se;
+                }
+                
+                return null_element_;
+            }
+            
+            inline scope_element& get_active_element(const std::string& var_name,
+                                                     const std::size_t index = std::numeric_limits<std::size_t>::max())
+            {
+                const std::size_t current_depth = parser_.state_.scope_depth;
+                
+                for (std::size_t i = 0; i < element_.size(); ++i)
+                {
+                    scope_element& se = element_[i];
+                    
+                    if (se.depth > current_depth)
+                        continue;
+                    else if (
+                             (se.name  == var_name) &&
+                             (se.index == index)    &&
+                             (se.active)
+                             )
+                        return se;
+                }
+                
+                return null_element_;
+            }
+            
+            inline bool add_element(const scope_element& se)
+            {
+                for (std::size_t i = 0; i < element_.size(); ++i)
+                {
+                    scope_element& cse = element_[i];
+                    
+                    if (
+                        (cse.name  == se.name ) &&
+                        (cse.depth <= se.depth) &&
+                        (cse.index == se.index) &&
+                        (cse.size  == se.size ) &&
+                        (cse.type  == se.type ) &&
+                        (cse.active)
+                        )
+                        return false;
+                }
+                
+                element_.push_back(se);
+                std::sort(element_.begin(),element_.end());
+                
+                return true;
+            }
+            
+            inline void deactivate(const std::size_t& scope_depth)
+            {
+                exprtk_debug(("deactivate() - Scope depth: %d\n",
+                              static_cast<int>(parser_.state_.scope_depth)));
+                
+                for (std::size_t i = 0; i < element_.size(); ++i)
+                {
+                    scope_element& se = element_[i];
+                    
+                    if (se.active && (se.depth >= scope_depth))
+                    {
+                        exprtk_debug(("deactivate() - element[%02d] '%s'\n",
+                                      static_cast<int>(i),
+                                      se.name.c_str()));
+                        
+                        se.active = false;
+                    }
+                }
+            }
+            
+            inline void free_element(scope_element& se)
+            {
+                switch (se.type)
+                {
+                    case scope_element::e_variable   : if (se.data    ) delete (T*) se.data;
+                        if (se.var_node) delete se.var_node;
+                        break;
+                        
+                    case scope_element::e_vector     : if (se.data    ) delete[] (T*) se.data;
+                        if (se.vec_node) delete se.vec_node;
+                        break;
+                        
+                    case scope_element::e_vecelem    : if (se.var_node) delete se.var_node;
+                        break;
+                        
+#ifndef exprtk_disable_string_capabilities
+                    case scope_element::e_string     : if (se.data    ) delete (std::string*) se.data;
+                        if (se.str_node) delete se.str_node;
+                        break;
+#endif
+                        
+                    default                          : return;
+                }
+                
+                se.clear();
+            }
+            
+            inline void cleanup()
+            {
+                for (std::size_t i = 0; i < element_.size(); ++i)
+                {
+                    free_element(element_[i]);
+                }
+                
+                element_.clear();
+                
+                input_param_cnt_ = 0;
+            }
+            
+            inline std::size_t next_ip_index()
+            {
+                return ++input_param_cnt_;
+            }
+            
+            inline expression_node_ptr get_variable(const T& v)
+            {
+                for (std::size_t i = 0; i < element_.size(); ++i)
+                {
+                    scope_element& se = element_[i];
+                    
+                    if (
+                        se.active   &&
+                        se.var_node &&
+                        details::is_variable_node(se.var_node)
+                        )
+                    {
+                        variable_node_ptr vn = reinterpret_cast<variable_node_ptr>(se.var_node);
+                        
+                        if (&(vn->ref()) == (&v))
+                        {
+                            return se.var_node;
+                        }
+                    }
+                }
+                
+                return expression_node_ptr(0);
+            }
+            
+        private:
+            
+            scope_element_manager& operator=(const scope_element_manager&);
+            
+            parser_t& parser_;
+            std::vector<scope_element> element_;
+            scope_element null_element_;
+            std::size_t input_param_cnt_;
+        };
+        
+        class scope_handler
+        {
+        public:
+            
+            typedef parser<T> parser_t;
+            
+            scope_handler(parser<T>& p)
+            : parser_(p)
+            {
+                parser_.state_.scope_depth++;
+#ifdef exprtk_enable_debugging
+                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)));
+#endif
             }
-            else
+            
+            ~scope_handler()
             {
-               // find first with largest diff_index;
-               std::size_t max_diff_index = 0;
-
-               for (std::size_t i = 1; i < error_list.size(); ++i)
-               {
-                  if (error_list[i].first > error_list[max_diff_index].first)
-                  {
-                     max_diff_index = i;
-                  }
-               }
-
-               parser_.
-                  set_error(
-                     make_error(parser_error::e_syntax,
-                                parser_.current_token(),
-                                "ERR101 - Failed parameter type check for function '" + function_name_ + "', "
-                                "Best match: '" + param_seq_list_[max_diff_index] + "'  call set: '" + param_seq +"'"));
+                parser_.sem_.deactivate(parser_.state_.scope_depth);
+                parser_.state_.scope_depth--;
+#ifdef exprtk_enable_debugging
+                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)));
+#endif
             }
-
-            return false;
-         }
-
-         std::size_t paramseq_count() const
-         {
-            return param_seq_list_.size();
-         }
-
-         std::string paramseq(const std::size_t& index) const
-         {
-            return param_seq_list_[index];
-         }
-
-         bool invalid() const
-         {
-            return !invalid_state_;
-         }
-
-      private:
-
-         void split(const std::string& s)
-         {
-            if (s.empty())
-               return;
-
-            std::size_t start = 0;
-            std::size_t end   = 0;
-
-            param_seq_list_t param_seq_list;
-
-            struct token_validator
-            {
-               static inline bool process(const std::string& str,
-                                          std::size_t s, std::size_t e,
-                                          param_seq_list_t& psl)
-               {
-                  if (
-                       (e - s) &&
-                       (std::string::npos == str.find("?*")) &&
-                       (std::string::npos == str.find("**"))
-                     )
-                  {
-                     const std::string curr_str = str.substr(s,e - s);
-
-                     if (std::string::npos == curr_str.find_first_not_of("STV*?|"))
-                     {
-                        psl.push_back(curr_str);
+            
+        private:
+            
+            scope_handler& operator=(const scope_handler&);
+            
+            parser_t& parser_;
+        };
+        
+        struct symtab_store
+        {
+            symbol_table_list_t symtab_list_;
+            
+            typedef typename symbol_table_t::local_data_t   local_data_t;
+            typedef typename symbol_table_t::variable_ptr   variable_ptr;
+            typedef typename symbol_table_t::function_ptr   function_ptr;
+#ifndef exprtk_disable_string_capabilities
+            typedef typename symbol_table_t::stringvar_ptr stringvar_ptr;
+#endif
+            typedef typename symbol_table_t::vector_holder_ptr       vector_holder_ptr;
+            typedef typename symbol_table_t::vararg_function_ptr   vararg_function_ptr;
+            typedef typename symbol_table_t::generic_function_ptr generic_function_ptr;
+            
+            inline bool empty() const
+            {
+                return symtab_list_.empty();
+            }
+            
+            inline void clear()
+            {
+                symtab_list_.clear();
+            }
+            
+            inline bool valid() const
+            {
+                if (!empty())
+                {
+                    for (std::size_t i = 0; i < symtab_list_.size(); ++i)
+                    {
+                        if (symtab_list_[i].valid())
+                            return true;
+                    }
+                }
+                
+                return false;
+            }
+            
+            inline bool valid_symbol(const std::string& symbol) const
+            {
+                if (!symtab_list_.empty())
+                    return symtab_list_[0].valid_symbol(symbol);
+                else
+                    return false;
+            }
+            
+            inline bool valid_function_name(const std::string& symbol) const
+            {
+                if (!symtab_list_.empty())
+                    return symtab_list_[0].valid_function(symbol);
+                else
+                    return false;
+            }
+            
+            inline variable_ptr get_variable(const std::string& variable_name) const
+            {
+                if (!valid_symbol(variable_name))
+                    return reinterpret_cast<variable_ptr>(0);
+                
+                variable_ptr result = reinterpret_cast<variable_ptr>(0);
+                
+                for (std::size_t i = 0; i < symtab_list_.size(); ++i)
+                {
+                    if (!symtab_list_[i].valid())
+                        continue;
+                    else
+                        result = local_data(i)
+                        .variable_store.get(variable_name);
+                    
+                    if (result) break;
+                }
+                
+                return result;
+            }
+            
+            inline variable_ptr get_variable(const T& var_ref) const
+            {
+                variable_ptr result = reinterpret_cast<variable_ptr>(0);
+                
+                for (std::size_t i = 0; i < symtab_list_.size(); ++i)
+                {
+                    if (!symtab_list_[i].valid())
+                        continue;
+                    else
+                        result = local_data(i).variable_store
+                        .get_from_varptr(reinterpret_cast<const void*>(&var_ref));
+                    
+                    if (result) break;
+                }
+                
+                return result;
+            }
+            
+#ifndef exprtk_disable_string_capabilities
+            inline stringvar_ptr get_stringvar(const std::string& string_name) const
+            {
+                if (!valid_symbol(string_name))
+                    return reinterpret_cast<stringvar_ptr>(0);
+                
+                stringvar_ptr result = reinterpret_cast<stringvar_ptr>(0);
+                
+                for (std::size_t i = 0; i < symtab_list_.size(); ++i)
+                {
+                    if (!symtab_list_[i].valid())
+                        continue;
+                    else
+                        result = local_data(i)
+                        .stringvar_store.get(string_name);
+                    
+                    if (result) break;
+                }
+                
+                return result;
+            }
+#endif
+            
+            inline function_ptr get_function(const std::string& function_name) const
+            {
+                if (!valid_function_name(function_name))
+                    return reinterpret_cast<function_ptr>(0);
+                
+                function_ptr result = reinterpret_cast<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)
+                        .function_store.get(function_name);
+                    
+                    if (result) break;
+                }
+                
+                return result;
+            }
+            
+            inline vararg_function_ptr get_vararg_function(const std::string& vararg_function_name) const
+            {
+                if (!valid_function_name(vararg_function_name))
+                    return reinterpret_cast<vararg_function_ptr>(0);
+                
+                vararg_function_ptr result = reinterpret_cast<vararg_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)
+                        .vararg_function_store.get(vararg_function_name);
+                    
+                    if (result) break;
+                }
+                
+                return result;
+            }
+            
+            inline generic_function_ptr get_generic_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)
+                        .generic_function_store.get(function_name);
+                    
+                    if (result) break;
+                }
+                
+                return result;
+            }
+            
+            inline generic_function_ptr get_string_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).string_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))
+                    return reinterpret_cast<vector_holder_ptr>(0);
+                
+                vector_holder_ptr result = reinterpret_cast<vector_holder_ptr>(0);
+                
+                for (std::size_t i = 0; i < symtab_list_.size(); ++i)
+                {
+                    if (!symtab_list_[i].valid())
+                        continue;
+                    else
+                        result =
+                        local_data(i).vector_store.get(vector_name);
+                    
+                    if (result) break;
+                }
+                
+                return result;
+            }
+            
+            inline bool is_constant_node(const std::string& symbol_name) const
+            {
+                if (!valid_symbol(symbol_name))
+                    return false;
+                
+                for (std::size_t i = 0; i < symtab_list_.size(); ++i)
+                {
+                    if (!symtab_list_[i].valid())
+                        continue;
+                    else if (local_data(i).variable_store.is_constant(symbol_name))
                         return true;
-                     }
-                  }
-
-                  return false;
-               }
-            };
-
-            while (std::string::npos != (end = s.find('|',start)))
+                }
+                
+                return false;
+            }
+            
+#ifndef exprtk_disable_string_capabilities
+            inline bool is_constant_string(const std::string& symbol_name) const
+            {
+                if (!valid_symbol(symbol_name))
+                    return false;
+                
+                for (std::size_t i = 0; i < symtab_list_.size(); ++i)
+                {
+                    if (!symtab_list_[i].valid())
+                        continue;
+                    else if (!local_data(i).stringvar_store.symbol_exists(symbol_name))
+                        continue;
+                    else if ( local_data(i).stringvar_store.is_constant(symbol_name))
+                        return true;
+                }
+                
+                return false;
+            }
+#endif
+            
+            inline bool symbol_exists(const std::string& symbol) const
+            {
+                for (std::size_t i = 0; i < symtab_list_.size(); ++i)
+                {
+                    if (!symtab_list_[i].valid())
+                        continue;
+                    else if (symtab_list_[i].symbol_exists(symbol))
+                        return true;
+                }
+                
+                return false;
+            }
+            
+            inline bool is_variable(const std::string& variable_name) const
+            {
+                for (std::size_t i = 0; i < symtab_list_.size(); ++i)
+                {
+                    if (!symtab_list_[i].valid())
+                        continue;
+                    else if (
+                             symtab_list_[i].local_data().variable_store
+                             .symbol_exists(variable_name)
+                             )
+                        return true;
+                }
+                
+                return false;
+            }
+            
+#ifndef exprtk_disable_string_capabilities
+            inline bool is_stringvar(const std::string& stringvar_name) const
+            {
+                for (std::size_t i = 0; i < symtab_list_.size(); ++i)
+                {
+                    if (!symtab_list_[i].valid())
+                        continue;
+                    else if (
+                             symtab_list_[i].local_data().stringvar_store
+                             .symbol_exists(stringvar_name)
+                             )
+                        return true;
+                }
+                
+                return false;
+            }
+            
+            inline bool is_conststr_stringvar(const std::string& symbol_name) const
+            {
+                for (std::size_t i = 0; i < symtab_list_.size(); ++i)
+                {
+                    if (!symtab_list_[i].valid())
+                        continue;
+                    else if (
+                             symtab_list_[i].local_data().stringvar_store
+                             .symbol_exists(symbol_name)
+                             )
+                    {
+                        return (
+                                local_data(i).stringvar_store.symbol_exists(symbol_name) ||
+                                local_data(i).stringvar_store.is_constant  (symbol_name)
+                                );
+                        
+                    }
+                }
+                
+                return false;
+            }
+#endif
+            
+            inline bool is_function(const std::string& function_name) const
+            {
+                for (std::size_t i = 0; i < symtab_list_.size(); ++i)
+                {
+                    if (!symtab_list_[i].valid())
+                        continue;
+                    else if (
+                             local_data(i).vararg_function_store
+                             .symbol_exists(function_name)
+                             )
+                        return true;
+                }
+                
+                return false;
+            }
+            
+            inline bool is_vararg_function(const std::string& vararg_function_name) const
+            {
+                for (std::size_t i = 0; i < symtab_list_.size(); ++i)
+                {
+                    if (!symtab_list_[i].valid())
+                        continue;
+                    else if (
+                             local_data(i).vararg_function_store
+                             .symbol_exists(vararg_function_name)
+                             )
+                        return true;
+                }
+                
+                return false;
+            }
+            
+            inline bool is_vector(const std::string& vector_name) const
+            {
+                for (std::size_t i = 0; i < symtab_list_.size(); ++i)
+                {
+                    if (!symtab_list_[i].valid())
+                        continue;
+                    else if (
+                             local_data(i).vector_store
+                             .symbol_exists(vector_name)
+                             )
+                        return true;
+                }
+                
+                return false;
+            }
+            
+            inline std::string get_variable_name(const expression_node_ptr& ptr) const
             {
-               if (!token_validator::process(s,start,end,param_seq_list))
-               {
-                  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(),
-                                   "ERR102 - Invalid parameter sequence of '" + err_param_seq +
-                                   "'  for function: " + function_name_));
-
-                  return;
-               }
-               else
-                  start = end + 1;
+                return local_data().variable_store.entity_name(ptr);
             }
-
-            if (start < s.size())
+            
+            inline std::string get_vector_name(const vector_holder_ptr& ptr) const
             {
-               if (token_validator::process(s,start,s.size(),param_seq_list))
-                  param_seq_list_ = param_seq_list;
-               else
-               {
-                  const std::string err_param_seq =  s.substr(start,s.size() - start);
-
-                  parser_.
-                     set_error(
-                        make_error(parser_error::e_syntax,
-                                   parser_.current_token(),
-                                   "ERR103 - Invalid parameter sequence of '" + err_param_seq +
-                                   "'  for function: " + function_name_));
-                  return;
-               }
-            }
-         }
-
-         type_checker(const type_checker&);
-         type_checker& operator=(const type_checker&);
-
-         bool invalid_state_;
-         parser_t& parser_;
-         std::string function_name_;
-         param_seq_list_t param_seq_list_;
-      };
-
-      inline expression_node_ptr parse_generic_function_call(igeneric_function<T>* function, const std::string& function_name)
-      {
-         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 (tc.invalid())
-         {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token_,
-                          "ERR104 - Type checker instantiation failure for generic function: " + function_name));
-
-            return error_node();
-         }
-
-         if (token_is(token_t::e_lbracket))
-         {
-            if (!token_is(token_t::e_rbracket))
+                return local_data().vector_store.entity_name(ptr);
+            }
+            
+#ifndef exprtk_disable_string_capabilities
+            inline std::string get_stringvar_name(const expression_node_ptr& ptr) const
             {
-               for ( ; ; )
-               {
-                  expression_node_ptr arg = parse_expression();
-
-                  if (0 == arg)
-                     return error_node();
-
-                  if (is_ivector_node(arg))
-                     param_type_list += 'V';
-                  else if (is_generally_string_node(arg))
-                     param_type_list += 'S';
-                  else // Everything else is assumed to be scalar returning expression
-                     param_type_list += 'T';
-
-                  arg_list.push_back(arg);
-
-                  if (token_is(token_t::e_rbracket))
-                     break;
-                  else if (!token_is(token_t::e_comma))
-                  {
-                     set_error(
-                        make_error(parser_error::e_syntax,
-                                   current_token_,
-                                   "ERR105 - Expected ',' for call to generic function: " + function_name));
-
-                     return error_node();
-                  }
-               }
+                return local_data().stringvar_store.entity_name(ptr);
             }
-         }
-
-         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_,
-                          "ERR106 - Expected ',' for call to generic function: " + function_name));
-
-            return error_node();
-         }
-
-         expression_node_ptr result = error_node();
-
-         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);
-
-         sdd.delete_ptr = (0 == result);
-
-         return result;
-      }
-
-      inline expression_node_ptr parse_string_function_call(igeneric_function<T>* function, const std::string& function_name)
-      {
-         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))
+            
+            inline std::string get_conststr_stringvar_name(const expression_node_ptr& ptr) const
             {
-               for ( ; ; )
-               {
-                  expression_node_ptr arg = parse_expression();
-
-                  if (0 == arg)
-                     return error_node();
-
-                  if (is_ivector_node(arg))
-                     param_type_list += 'V';
-                  else if (is_generally_string_node(arg))
-                     param_type_list += 'S';
-                  else // Everything else is a scalar returning expression
-                     param_type_list += 'T';
-
-                  arg_list.push_back(arg);
-
-                  if (token_is(token_t::e_rbracket))
-                     break;
-                  else if (!token_is(token_t::e_comma))
-                  {
-                     set_error(
-                        make_error(parser_error::e_syntax,
-                                   current_token_,
-                                   "ERR107 - Expected ',' for call to string function: " + function_name));
-
-                     return error_node();
-                  }
-               }
+                return local_data().stringvar_store.entity_name(ptr);
             }
-         }
-
-         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_,
-                          "ERR108 - Expected ',' for call to string function: " + function_name));
-
-            return error_node();
-         }
-
-         expression_node_ptr result = error_node();
-
-         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);
-
-         sdd.delete_ptr = (0 == result);
-
-         return result;
-      }
-
-      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)
-         {
-            expression_node_ptr branch[NumberOfParameters];
-            expression_node_ptr result  = error_node();
-            std::fill_n(branch,NumberOfParameters,reinterpret_cast<expression_node_ptr>(0));
-            scoped_delete<expression_node_t,NumberOfParameters> sd(p,branch);
-
-            p.next_token();
-
-            if (!p.token_is(token_t::e_lbracket))
+#endif
+            
+            inline local_data_t& local_data(const std::size_t& index = 0)
             {
-               p.set_error(
-                    make_error(parser_error::e_syntax,
-                               p.current_token(),
-                               "ERR109 - Expected '(' for special function"));
-
-               return error_node();
+                return symtab_list_[index].local_data();
             }
-
-            for (std::size_t i = 0; i < NumberOfParameters; ++i)
+            
+            inline const local_data_t& local_data(const std::size_t& index = 0) const
             {
-               branch[i] = p.parse_expression();
-
-               if (0 == branch[i])
-               {
-                  return p.error_node();
-               }
-               else if (i < (NumberOfParameters - 1))
-               {
-                  if (!p.token_is(token_t::e_comma))
-                  {
-                     p.set_error(
-                          make_error(parser_error::e_syntax,
-                                     p.current_token(),
-                                     "ERR110 - Expected ',' before next parameter of special function"));
-
-                     return p.error_node();
-                  }
-               }
+                return symtab_list_[index].local_data();
             }
-
-            if (!p.token_is(token_t::e_rbracket))
-               return p.error_node();
-            else
-               result = p.expression_generator_.special_function(opt_type,branch);
-
-            sd.delete_ptr = (0 == result);
-
-            return result;
-         }
-      };
-
-      inline expression_node_ptr parse_special_function()
-      {
-         // 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])
-            )
-         {
-            set_error(
-               make_error(parser_error::e_token,
-                          current_token_,
-                          "ERR111 - Invalid special function[1]: " + current_token_.value));
-
-            return error_node();
-         }
-
-         const unsigned int id = (current_token_.value[2] - '0') * 10 + (current_token_.value[3] - '0');
-
-         if (id >= details::e_sffinal)
-         {
-            set_error(
-               make_error(parser_error::e_token,
-                          current_token_,
-                          "ERR112 - Invalid special function[2]: " + current_token_.value));
-
-            return error_node();
-         }
-
-         const std::size_t sf_3_to_4 = details::e_sf48;
-         const details::operator_type opt_type = details::operator_type(id + 1000);
-         const std::size_t NumberOfParameters = (id < (sf_3_to_4 - 1000)) ? 3 : 4;
-
-         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);
-            default : return error_node();
-         }
-      }
-
-      inline expression_node_ptr parse_null_statement()
-      {
-         next_token();
-         return node_allocator_.allocate<details::null_node<T> >();
-      }
-
-      #ifndef exprtk_disable_break_continue
-      inline expression_node_ptr parse_break_statement()
-      {
-         if (!brkcnt_list_.empty())
-         {
-            next_token();
-
-            brkcnt_list_.front() = true;
-
-            expression_node_ptr return_expr = error_node();
-
-            if (token_is(token_t::e_lsqrbracket))
-            {
-               if (0 == (return_expr = parse_expression()))
-               {
-                  set_error(
-                     make_error(parser_error::e_syntax,
-                                current_token_,
-                                "ERR113 - Failed to parse return expression for 'break' statement"));
-
-                  return error_node();
-               }
-               else if (!token_is(token_t::e_rsqrbracket))
-               {
-                  set_error(
-                     make_error(parser_error::e_syntax,
-                                current_token_,
-                                "ERR114 - Expected ']' at the completion of break's return expression"));
-
-                  free_node(node_allocator_,return_expr);
-
-                  return error_node();
-               }
-            }
-
-            return node_allocator_.allocate<details::break_node<T> >(return_expr);
-         }
-         else
-         {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token_,
-                          "ERR115 - Invalid use of 'break', allowed only in the scope of a loop"));
-         }
-
-         return error_node();
-      }
-
-      inline expression_node_ptr parse_continue_statement()
-      {
-         if (!brkcnt_list_.empty())
-         {
-            next_token();
-            brkcnt_list_.front() = true;
-            return node_allocator_.allocate<details::continue_node<T> >();
-         }
-         else
-         {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token_,
-                          "ERR116 - Invalid use of 'continue', allowed only in the scope of a loop"));
-
-            return error_node();
-         }
-      }
-      #endif
-
-      inline expression_node_ptr parse_define_vector_statement(const std::string& vec_name)
-      {
-         expression_node_ptr size_expr = error_node();
-
-         if (!token_is(token_t::e_lsqrbracket))
-         {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token_,
-                          "ERR117 - Expected '[' as part of vector size definition"));
-
-            return error_node();
-         }
-         else if (0 == (size_expr = parse_expression()))
-         {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token_,
-                          "ERR118 - Failed to determine size of vector '" + vec_name + "'"));
-
-            return error_node();
-         }
-         else if (!is_constant_node(size_expr))
-         {
-            free_node(node_allocator_,size_expr);
-
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token_,
-                          "ERR119 - Expected a literal number as size of vector '" + vec_name + "'"));
-
-            return error_node();
-         }
-
-         T vector_size = size_expr->value();
-
-         free_node(node_allocator_,size_expr);
-
-         if (
-              (vector_size <= T(0)) ||
-              std::not_equal_to<T>()
-              (T(0),vector_size - details::numeric::trunc(vector_size))
-            )
-         {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token_,
-                          "ERR120 - Invalid vector size. Must be an integer greater than zero, size: " +
-                          details::to_str(details::numeric::to_int32(vector_size))));
-
-            return error_node();
-         }
-
-         std::vector<expression_node_ptr> vec_initilizer_list;
-
-         scoped_vec_delete<expression_node_t> svd(*this,vec_initilizer_list);
-
-         bool single_value_initialiser = false;
-
-         if (!token_is(token_t::e_rsqrbracket))
-         {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token_,
-                          "ERR121 - Expected ']' as part of vector size definition"));
-
-            return error_node();
-         }
-         else if (!token_is(token_t::e_eof))
-         {
-            if (!token_is(token_t::e_assign))
-            {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token_,
-                             "ERR122 - Expected ':=' as part of vector definition"));
-
-               return error_node();
-            }
-            else if (token_is(token_t::e_lsqrbracket))
-            {
-               expression_node_ptr initialiser = parse_expression();
-
-               if (0 == initialiser)
-               {
-                  set_error(
-                     make_error(parser_error::e_syntax,
-                                current_token_,
-                                "ERR123 - Failed to parse single vector initialiser"));
-
-                  return error_node();
-               }
-
-               vec_initilizer_list.push_back(initialiser);
-
-               if (!token_is(token_t::e_rsqrbracket))
-               {
-                  set_error(
-                     make_error(parser_error::e_syntax,
-                                current_token_,
-                                "ERR124 - Expected ']' to close single value vector initialiser"));
-
-                  return error_node();
-               }
-
-               single_value_initialiser = true;
-            }
-            else if (!token_is(token_t::e_lcrlbracket))
+            
+            inline symbol_table_t& get_symbol_table(const std::size_t& index = 0)
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token_,
-                             "ERR125 - Expected '{' as part of vector initialiser list"));
-
-               return error_node();
+                return symtab_list_[index];
             }
-            else if (!token_is(token_t::e_rcrlbracket))
+        };
+        
+        struct parser_state
+        {
+            parser_state()
             {
-               for (;;)
-               {
-                  expression_node_ptr initialiser = parse_expression();
-
-                  if (0 == initialiser)
-                  {
-                     set_error(
-                        make_error(parser_error::e_syntax,
-                                   current_token_,
-                                   "ERR126 - Expected '{' as part of vector initialiser list"));
-
-                     return error_node();
-                  }
-                  else
-                     vec_initilizer_list.push_back(initialiser);
-
-                  if (token_is(token_t::e_rcrlbracket))
-                     break;
-
-                  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_,
-                                   "ERR127 - Expected ',' between vector initialisers"));
-
-                     return error_node();
-                  }
-
-                  if (token_is(token_t::e_rcrlbracket))
-                     break;
-               }
-            }
-
-            if (
-                 !token_is(token_t::e_rbracket   ,false) &&
-                 !token_is(token_t::e_rcrlbracket,false) &&
-                 !token_is(token_t::e_rsqrbracket,false)
-               )
-            {
-               if (!token_is(token_t::e_eof))
-               {
-                  set_error(
-                     make_error(parser_error::e_syntax,
-                                current_token_,
-                                "ERR128 - Expected ';' at end of vector definition"));
-
-                  return error_node();
-               }
+                reset();
             }
-
-            if (vec_initilizer_list.size() > vector_size)
+            
+            void reset()
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token_,
-                             "ERR129 - Initialiser list larger than the number of elements in the vector: '" + vec_name + "'"));
-
-               return error_node();
-            }
-         }
-
-         typename symbol_table_t::vector_holder_ptr vec_holder = typename symbol_table_t::vector_holder_ptr(0);
-
-         std::size_t vec_size = static_cast<std::size_t>(details::numeric::to_int32(vector_size));
-
-         scope_element& se = sem_.get_element(vec_name);
-
-         if (se.name == vec_name)
-         {
-            if (se.active)
-            {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token_,
-                             "ERR130 - Illegal redefinition of local vector: '" + vec_name + "'"));
-
-               return error_node();
+                parsing_return_stmt = false;
+                parsing_break_stmt  = false;
+                return_stmt_present = false;
+                side_effect_present = false;
+                scope_depth         = 0;
             }
-            else if (
-                      (se.size == vec_size) &&
-                      (scope_element::e_vector == se.type)
-                    )
+            
+#ifndef exprtk_enable_debugging
+            void activate_side_effect(const std::string&)
+#else
+            void activate_side_effect(const std::string& source)
+#endif
             {
-               vec_holder = se.vec_node;
-               se.active  = true;
-               se.ref_count++;
+                if (!side_effect_present)
+                {
+                    side_effect_present = true;
+                    
+                    exprtk_debug(("activate_side_effect() - caller: %s\n",source.c_str()));
+                }
+            }
+            
+            bool parsing_return_stmt;
+            bool parsing_break_stmt;
+            bool return_stmt_present;
+            bool side_effect_present;
+            std::size_t scope_depth;
+        };
+        
+    public:
+        
+        struct unknown_symbol_resolver
+        {
+            
+            enum usr_symbol_type
+            {
+                e_usr_variable_type = 0,
+                e_usr_constant_type = 1
+            };
+            
+            virtual ~unknown_symbol_resolver()
+            {}
+            
+            virtual bool process(const std::string& /*unknown_symbol*/,
+                                 usr_symbol_type& st,
+                                 T& default_value,
+                                 std::string& error_message)
+            {
+                st = e_usr_variable_type;
+                default_value = T(0);
+                error_message.clear();
+                
+                return true;
             }
-         }
-
-         if (0 == vec_holder)
-         {
-            scope_element nse;
-            nse.name     = vec_name;
-            nse.type     = scope_element::e_vector;
-            nse.depth    = scope_depth_;
-            nse.size     = vec_size;
-            nse.data     = new T[vec_size];
-            nse.vec_node = new typename scope_element::vector_holder_t((T*)(nse.data),nse.size);
-
-            if (!sem_.add_element(nse))
+        };
+        
+        enum collect_type
+        {
+            e_ct_none        = 0,
+            e_ct_variables   = 1,
+            e_ct_functions   = 2,
+            e_ct_assignments = 4
+        };
+        
+        enum symbol_type
+        {
+            e_st_unknown        = 0,
+            e_st_variable       = 1,
+            e_st_vector         = 2,
+            e_st_vecelem        = 3,
+            e_st_string         = 4,
+            e_st_function       = 5,
+            e_st_local_variable = 6,
+            e_st_local_vector   = 7,
+            e_st_local_string   = 8
+        };
+        
+        class dependent_entity_collector
+        {
+        public:
+            
+            typedef std::pair<std::string,symbol_type> symbol_t;
+            typedef std::vector<symbol_t> symbol_list_t;
+            
+            dependent_entity_collector(const std::size_t options = e_ct_none)
+            : options_(options),
+            collect_variables_  ((options_ & e_ct_variables  ) == e_ct_variables  ),
+            collect_functions_  ((options_ & e_ct_functions  ) == e_ct_functions  ),
+            collect_assignments_((options_ & e_ct_assignments) == e_ct_assignments),
+            return_present_   (false),
+            final_stmt_return_(false)
+            {}
+            
+            template <typename Allocator,
+            template <typename,typename> class Sequence>
+            inline std::size_t symbols(Sequence<symbol_t,Allocator>& symbols_list)
+            {
+                if (!collect_variables_ && !collect_functions_)
+                    return 0;
+                else if (symbol_name_list_.empty())
+                    return 0;
+                
+                for (std::size_t i = 0; i < symbol_name_list_.size(); ++i)
+                {
+                    std::string& s = symbol_name_list_[i].first;
+#ifndef MODIFICATION
+                    std::transform(s.begin(),s.end(),s.begin(),static_cast<int(*)(int)>(std::tolower));
+#endif
+                }
+                
+                std::sort(symbol_name_list_.begin(),symbol_name_list_.end());
+                
+                std::unique_copy(symbol_name_list_.begin(),
+                                 symbol_name_list_.end(),
+                                 std::back_inserter(symbols_list));
+                
+                return symbols_list.size();
+            }
+            
+            template <typename Allocator,
+            template <typename,typename> class Sequence>
+            inline std::size_t assignment_symbols(Sequence<symbol_t,Allocator>& assignment_list)
+            {
+                if (!collect_assignments_)
+                    return 0;
+                else if (assignment_name_list_.empty())
+                    return 0;
+                
+                for (std::size_t i = 0; i < assignment_name_list_.size(); ++i)
+                {
+                    std::string& s = assignment_name_list_[i].first;
+#ifndef MODIFICATION
+                    std::transform(s.begin(),s.end(),s.begin(),static_cast<int(*)(int)>(std::tolower));
+#endif
+                }
+                
+                std::sort(assignment_name_list_.begin(),assignment_name_list_.end());
+                
+                std::unique_copy(assignment_name_list_.begin(),
+                                 assignment_name_list_.end(),
+                                 std::back_inserter(assignment_list));
+                
+                return assignment_list.size();
+            }
+            
+            void clear()
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token_,
-                             "ERR131 - Failed to add new local vector '" + vec_name + "' to SEM"));
-
-               return error_node();
-            }
-
-            vec_holder = nse.vec_node;
-
-            exprtk_debug(("parse_define_vector_statement() - INFO - Added new local vector: %s[%d]\n",
-                          nse.name.c_str(),
-                          static_cast<int>(nse.size)));
-         }
-
-         lodge_symbol(vec_name,e_st_local_vector);
-
-         expression_node_ptr result =
-                node_allocator_
-                   .allocate<details::vector_assignment_node<T> >(
-                      (*vec_holder)[0],
-                      vec_size,
-                      vec_initilizer_list,
-                      single_value_initialiser);
-
-         svd.delete_ptr = (0 == result);
-
-         return result;
-      }
-
-      inline bool local_variable_is_shadowed(const std::string& symbol)
-      {
-         const scope_element& se = sem_.get_element(symbol);
-         return (se.name == symbol) && se.active;
-      }
-
-      inline expression_node_ptr parse_define_var_statement()
-      {
-         if (vardef_disabled_)
-         {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token_,
-                          "ERR132 - Illegal variable definition"));
-
-            return error_node();
-         }
-         else if (!details::imatch(current_token_.value,"var"))
-         {
-            return error_node();
-         }
-         else
-            next_token();
-
-         const std::string var_name = current_token_.value;
-
-         expression_node_ptr initialisation_expression = error_node();
-
-         if (!token_is(token_t::e_symbol))
-         {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token_,
-                          "ERR133 - Expected a symbol for variable definition"));
-
-            return error_node();
-         }
-         else if (details::is_reserved_symbol(var_name))
-         {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token_,
-                          "ERR134 - Illegal redefinition of reserved keyword: '" + var_name + "'"));
-
-            return error_node();
-         }
-         else if (symbol_table_.symbol_exists(var_name))
-         {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token_,
-                          "ERR135 - Illegal redefinition of variable '" + var_name + "'"));
-
-            return error_node();
-         }
-         else if (local_variable_is_shadowed(var_name))
-         {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token_,
-                          "ERR136 - Illegal redefinition of local variable: '" + var_name + "'"));
-
-            return error_node();
-         }
-         else if (token_is(token_t::e_lsqrbracket,false))
-         {
-            return parse_define_vector_statement(var_name);
-         }
-         else if (token_is(token_t::e_lcrlbracket,false))
-         {
-            return parse_uninitialised_var_statement(var_name);
-         }
-         else if (token_is(token_t::e_assign))
-         {
-            if (0 == (initialisation_expression = parse_expression()))
-            {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token_,
-                             "ERR137 - Failed to parse initialisation expression"));
-
-               return error_node();
-            }
-         }
-
-         if (
-              !token_is(token_t::e_rbracket   ,false) &&
-              !token_is(token_t::e_rcrlbracket,false) &&
-              !token_is(token_t::e_rsqrbracket,false)
-            )
-         {
-            if (!token_is(token_t::e_eof,false))
-            {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token_,
-                             "ERR138 - Expected ';' after variable definition"));
-
-               free_node(node_allocator_,initialisation_expression);
-
-               return error_node();
-            }
-         }
-
-         variable_node_t* var_node = reinterpret_cast<variable_node_t*>(0);
-
-         scope_element& se = sem_.get_element(var_name);
-
-         if (se.name == var_name)
-         {
-            if (se.active)
-            {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token_,
-                             "ERR139 - Illegal redefinition of local variable: '" + var_name + "'"));
-
-               free_node(node_allocator_,initialisation_expression);
-
-               return error_node();
-            }
-            else if (scope_element::e_variable == se.type)
+                symbol_name_list_    .clear();
+                assignment_name_list_.clear();
+                retparam_list_       .clear();
+                return_present_    = false;
+                final_stmt_return_ = false;
+            }
+            
+            bool& collect_variables()
+            {
+                return collect_variables_;
+            }
+            
+            bool& collect_functions()
+            {
+                return collect_functions_;
+            }
+            
+            bool& collect_assignments()
+            {
+                return collect_assignments_;
+            }
+            
+            bool return_present() const
+            {
+                return return_present_;
+            }
+            
+            bool final_stmt_return() const
+            {
+                return final_stmt_return_;
+            }
+            
+            typedef std::vector<std::string> retparam_list_t;
+            
+            retparam_list_t return_param_type_list() const
+            {
+                return retparam_list_;
+            }
+            
+        private:
+            
+            inline void add_symbol(const std::string& symbol, const symbol_type st)
+            {
+                switch (st)
+                {
+                    case e_st_variable       :
+                    case e_st_vector         :
+                    case e_st_string         :
+                    case e_st_local_variable :
+                    case e_st_local_vector   :
+                    case e_st_local_string   :
+                    case e_st_function       :
+                        if (collect_variables_ || collect_functions_)
+                            symbol_name_list_.push_back(std::make_pair(symbol,st));
+                        break;
+                        
+                    default                  : return;
+                }
+            }
+            
+            inline void add_assignment(const std::string& symbol, const symbol_type st)
+            {
+                switch (st)
+                {
+                    case e_st_variable       :
+                    case e_st_vector         :
+                    case e_st_string         :
+                        if (collect_assignments_)
+                            assignment_name_list_.push_back(std::make_pair(symbol,st));
+                        break;
+                        
+                    default                  : return;
+                }
+            }
+            
+            std::size_t options_;
+            bool collect_variables_;
+            bool collect_functions_;
+            bool collect_assignments_;
+            bool return_present_;
+            bool final_stmt_return_;
+            symbol_list_t symbol_name_list_;
+            symbol_list_t assignment_name_list_;
+            retparam_list_t retparam_list_;
+            
+            friend class parser<T>;
+        };
+        
+        class settings_store
+        {
+        private:
+            
+            typedef std::set<std::string,details::ilesscompare> disabled_entity_set_t;
+            typedef disabled_entity_set_t::iterator des_itr_t;
+            
+        public:
+            
+            enum settings_compilation_options
+            {
+                e_unknown              =    0,
+                e_replacer             =    1,
+                e_joiner               =    2,
+                e_numeric_check        =    4,
+                e_bracket_check        =    8,
+                e_sequence_check       =   16,
+                e_commutative_check    =   32,
+                e_strength_reduction   =   64,
+                e_disable_vardef       =  128,
+                e_collect_vars         =  256,
+                e_collect_funcs        =  512,
+                e_collect_assings      = 1024,
+                e_disable_usr_on_rsrvd = 2048,
+                e_disable_zero_return  = 4096
+            };
+            
+            enum settings_base_funcs
+            {
+                e_bf_unknown = 0,
+                e_bf_abs       , e_bf_acos     , e_bf_acosh    , e_bf_asin   ,
+                e_bf_asinh     , e_bf_atan     , e_bf_atan2    , e_bf_atanh  ,
+                e_bf_avg       , e_bf_ceil     , e_bf_clamp    , e_bf_cos    ,
+                e_bf_cosh      , e_bf_cot      , e_bf_csc      , e_bf_equal  ,
+                e_bf_erf       , e_bf_erfc     , e_bf_exp      , e_bf_expm1  ,
+                e_bf_floor     , e_bf_frac     , e_bf_hypot    , e_bf_iclamp ,
+                e_bf_like      , e_bf_log      , e_bf_log10    , e_bf_log1p  ,
+                e_bf_log2      , e_bf_logn     , e_bf_mand     , e_bf_max    ,
+                e_bf_min       , e_bf_mod      , e_bf_mor      , e_bf_mul    ,
+                e_bf_ncdf      , e_bf_pow      , e_bf_root     , e_bf_round  ,
+                e_bf_roundn    , e_bf_sec      , e_bf_sgn      , e_bf_sin    ,
+                e_bf_sinc      , e_bf_sinh     , e_bf_sqrt     , e_bf_sum    ,
+                e_bf_swap      , e_bf_tan      , e_bf_tanh     , e_bf_trunc  ,
+                e_bf_not_equal , e_bf_inrange  , e_bf_deg2grad , e_bf_deg2rad,
+                e_bf_rad2deg   , e_bf_grad2deg
+            };
+            
+            enum settings_control_structs
+            {
+                e_ctrl_unknown = 0,
+                e_ctrl_ifelse,
+                e_ctrl_switch,
+                e_ctrl_for_loop,
+                e_ctrl_while_loop,
+                e_ctrl_repeat_loop
+            };
+            
+            enum settings_logic_opr
             {
-               var_node  = se.var_node;
-               se.active = true;
-               se.ref_count++;
-            }
-         }
-
-         if (0 == var_node)
-         {
-            scope_element nse;
-            nse.name      = var_name;
-            nse.active    = true;
-            nse.ref_count = 1;
-            nse.type      = scope_element::e_variable;
-            nse.depth     = scope_depth_;
-            nse.data      = new T(T(0));
-            nse.var_node  = new variable_node_t(*(T*)(nse.data));
-
-            if (!sem_.add_element(nse))
+                e_logic_unknown = 0,
+                e_logic_and, e_logic_nand,  e_logic_nor,
+                e_logic_not, e_logic_or,    e_logic_xnor,
+                e_logic_xor, e_logic_scand, e_logic_scor
+            };
+            
+            enum settings_arithmetic_opr
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token_,
-                             "ERR140 - Failed to add new local variable '" + var_name + "' to SEM"));
-
-               free_node(node_allocator_,initialisation_expression);
-
-               return error_node();
-            }
-
-            var_node = nse.var_node;
-
-            exprtk_debug(("parse_define_var_statement() - INFO - Added new local variable: %s\n",nse.name.c_str()));
-         }
-
-         lodge_symbol(var_name,e_st_local_variable);
-
-         expression_node_ptr branch[2] = {0};
-
-         branch[0] = var_node;
-         branch[1] = initialisation_expression ? initialisation_expression : expression_generator_(T(0));
-
-         return expression_generator_(details::e_assign,branch);
-      }
-
-      inline expression_node_ptr parse_uninitialised_var_statement(const std::string& var_name)
-      {
-         if (
-              !token_is(token_t::e_lcrlbracket) ||
-              !token_is(token_t::e_rcrlbracket)
-            )
-         {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token_,
-                          "ERR141 - Expected a '{}' for uninitialised var definition"));
-
-            return error_node();
-         }
-         else if (!token_is(token_t::e_eof,false))
-         {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token_,
-                          "ERR142 - Expected ';' after uninitialised variable definition"));
-
-            return error_node();
-         }
-
-         variable_node_t* var_node = reinterpret_cast<variable_node_t*>(0);
-
-         scope_element& se = sem_.get_element(var_name);
-
-         if (se.name == var_name)
-         {
-            if (se.active)
-            {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token_,
-                             "ERR143 - Illegal redefinition of local variable: '" + var_name + "'"));
-
-               return error_node();
-            }
-            else if (scope_element::e_variable == se.type)
+                e_arith_unknown = 0,
+                e_arith_add, e_arith_sub, e_arith_mul,
+                e_arith_div, e_arith_mod, e_arith_pow
+            };
+            
+            enum settings_assignment_opr
             {
-               var_node  = se.var_node;
-               se.active = true;
-               se.ref_count++;
-            }
-         }
-
-         if (0 == var_node)
-         {
-            scope_element nse;
-            nse.name      = var_name;
-            nse.active    = true;
-            nse.ref_count = 1;
-            nse.type      = scope_element::e_variable;
-            nse.depth     = scope_depth_;
-            nse.ip_index  = sem_.next_ip_index();
-            nse.data      = new T(T(0));
-            nse.var_node  = new variable_node_t(*(T*)(nse.data));
-
-            if (!sem_.add_element(nse))
+                e_assign_unknown = 0,
+                e_assign_assign, e_assign_addass, e_assign_subass,
+                e_assign_mulass, e_assign_divass, e_assign_modass
+            };
+            
+            enum settings_inequality_opr
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token_,
-                             "ERR144 - Failed to add new local variable '" + var_name + "' to SEM"));
-
-               return error_node();
-            }
-
-            exprtk_debug(("parse_uninitialised_var_statement() - INFO - Added new local variable: %s\n",nse.name.c_str()));
-         }
-
-         lodge_symbol(var_name,e_st_local_variable);
-
-         return expression_generator_(T(0));
-      }
-
-      inline expression_node_ptr parse_swap_statement()
-      {
-         if (!details::imatch(current_token_.value,"swap"))
-         {
-            return error_node();
-         }
-         else
-            next_token();
-
-         if (!token_is(token_t::e_lbracket))
-         {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token_,
-                          "ERR145 - Expected '(' at start of swap statement"));
-
-            return error_node();
-         }
-
-         expression_node_ptr variable0 = error_node();
-         expression_node_ptr variable1 = error_node();
-
-         bool variable0_generated = false;
-         bool variable1_generated = false;
-
-         const std::string var0_name = current_token_.value;
-
-         if (!token_is(token_t::e_symbol,false))
-         {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token_,
-                          "ERR146 - Expected a symbol for variable or vector element definition"));
-
-            return error_node();
-         }
-         else if (peek_token_is(token_t::e_lsqrbracket))
-         {
-            if (0 == (variable0 = parse_vector()))
-            {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token_,
-                             "ERR147 - First parameter to swap is an invalid vector element: '" + var0_name + "'"));
-
-               return error_node();
-            }
-
-            variable0_generated = true;
-         }
-         else
-         {
-            if (symbol_table_.is_variable(var0_name))
+                e_ineq_unknown = 0,
+                e_ineq_lt,    e_ineq_lte, e_ineq_eq,
+                e_ineq_equal, e_ineq_ne,  e_ineq_nequal,
+                e_ineq_gte,   e_ineq_gt
+            };
+            
+            static const std::size_t compile_all_opts = e_replacer          +
+            e_joiner            +
+            e_numeric_check     +
+            e_bracket_check     +
+            e_sequence_check    +
+            e_commutative_check +
+            e_strength_reduction;
+            
+            settings_store(const std::size_t compile_options = compile_all_opts)
             {
-               variable0 = symbol_table_.get_variable(var0_name);
+                load_compile_options(compile_options);
             }
-
-            scope_element& se = sem_.get_element(var0_name);
-
-            if (
-                 (se.active)            &&
-                 (se.name == var0_name) &&
-                 (scope_element::e_variable == se.type)
-               )
+            
+            settings_store& enable_all_base_functions()
             {
-               variable0 = se.var_node;
+                disabled_func_set_.clear();
+                return *this;
             }
-
-            lodge_symbol(var0_name,e_st_variable);
-
-            if (0 == variable0)
+            
+            settings_store& enable_all_control_structures()
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token_,
-                             "ERR148 - First parameter to swap is an invalid variable: '" + var0_name + "'"));
-
-               return error_node();
+                disabled_ctrl_set_.clear();
+                return *this;
+            }
+            
+            settings_store& enable_all_logic_ops()
+            {
+                disabled_logic_set_.clear();
+                return *this;
+            }
+            
+            settings_store& enable_all_arithmetic_ops()
+            {
+                disabled_arithmetic_set_.clear();
+                return *this;
+            }
+            
+            settings_store& enable_all_assignment_ops()
+            {
+                disabled_assignment_set_.clear();
+                return *this;
+            }
+            
+            settings_store& enable_all_inequality_ops()
+            {
+                disabled_inequality_set_.clear();
+                return *this;
+            }
+            
+            settings_store& enable_local_vardef()
+            {
+                disable_vardef_ = false;
+                return *this;
+            }
+            
+            settings_store& disable_all_base_functions()
+            {
+                std::copy(details::base_function_list,
+                          details::base_function_list + details::base_function_list_size,
+                          std::insert_iterator<disabled_entity_set_t>
+                          (disabled_func_set_,disabled_func_set_.begin()));
+                return *this;
+            }
+            
+            settings_store& disable_all_control_structures()
+            {
+                std::copy(details::cntrl_struct_list,
+                          details::cntrl_struct_list + details::cntrl_struct_list_size,
+                          std::insert_iterator<disabled_entity_set_t>
+                          (disabled_ctrl_set_,disabled_ctrl_set_.begin()));
+                return *this;
+            }
+            
+            settings_store& disable_all_logic_ops()
+            {
+                std::copy(details::logic_ops_list,
+                          details::logic_ops_list + details::logic_ops_list_size,
+                          std::insert_iterator<disabled_entity_set_t>
+                          (disabled_logic_set_,disabled_logic_set_.begin()));
+                return *this;
+            }
+            
+            settings_store& disable_all_arithmetic_ops()
+            {
+                std::copy(details::arithmetic_ops_list,
+                          details::arithmetic_ops_list + details::arithmetic_ops_list_size,
+                          std::insert_iterator<disabled_entity_set_t>
+                          (disabled_arithmetic_set_,disabled_arithmetic_set_.begin()));
+                return *this;
+            }
+            
+            settings_store& disable_all_assignment_ops()
+            {
+                std::copy(details::assignment_ops_list,
+                          details::assignment_ops_list + details::assignment_ops_list_size,
+                          std::insert_iterator<disabled_entity_set_t>
+                          (disabled_assignment_set_,disabled_assignment_set_.begin()));
+                return *this;
+            }
+            
+            settings_store& disable_all_inequality_ops()
+            {
+                std::copy(details::inequality_ops_list,
+                          details::inequality_ops_list + details::inequality_ops_list_size,
+                          std::insert_iterator<disabled_entity_set_t>
+                          (disabled_inequality_set_,disabled_inequality_set_.begin()));
+                return *this;
             }
-            else
-               next_token();
-         }
-
-         if (!token_is(token_t::e_comma))
-         {
-            set_error(
-                make_error(parser_error::e_syntax,
-                           current_token(),
-                           "ERR149 - Expected ',' between parameters to swap"));
-
-            if (variable0_generated)
+            
+            settings_store& disable_local_vardef()
             {
-               free_node(node_allocator_,variable0);
+                disable_vardef_ = true;
+                return *this;
+            }
+            
+            bool replacer_enabled           () const { return enable_replacer_;           }
+            bool commutative_check_enabled  () const { return enable_commutative_check_;  }
+            bool joiner_enabled             () const { return enable_joiner_;             }
+            bool numeric_check_enabled      () const { return enable_numeric_check_;      }
+            bool bracket_check_enabled      () const { return enable_bracket_check_;      }
+            bool sequence_check_enabled     () const { return enable_sequence_check_;     }
+            bool strength_reduction_enabled () const { return enable_strength_reduction_; }
+            bool collect_variables_enabled  () const { return enable_collect_vars_;       }
+            bool collect_functions_enabled  () const { return enable_collect_funcs_;      }
+            bool collect_assignments_enabled() const { return enable_collect_assings_;    }
+            bool vardef_disabled            () const { return disable_vardef_;            }
+            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)
+            {
+                if (disabled_func_set_.empty())
+                    return true;
+                else
+                    return (disabled_func_set_.end() == disabled_func_set_.find(function_name));
+            }
+            
+            bool control_struct_enabled(const std::string& control_struct)
+            {
+                if (disabled_ctrl_set_.empty())
+                    return true;
+                else
+                    return (disabled_ctrl_set_.end() == disabled_ctrl_set_.find(control_struct));
+            }
+            
+            bool logic_enabled(const std::string& logic_operation)
+            {
+                if (disabled_logic_set_.empty())
+                    return true;
+                else
+                    return (disabled_logic_set_.end() == disabled_logic_set_.find(logic_operation));
+            }
+            
+            bool arithmetic_enabled(const details::operator_type& arithmetic_operation)
+            {
+                if (disabled_logic_set_.empty())
+                    return true;
+                else
+                    return (disabled_arithmetic_set_.end() == disabled_arithmetic_set_.find(arith_opr_to_string(arithmetic_operation)));
+            }
+            
+            bool assignment_enabled(const details::operator_type& assignment)
+            {
+                if (disabled_assignment_set_.empty())
+                    return true;
+                else
+                    return (disabled_assignment_set_.end() == disabled_assignment_set_.find(assign_opr_to_string(assignment)));
+            }
+            
+            bool inequality_enabled(const details::operator_type& inequality)
+            {
+                if (disabled_inequality_set_.empty())
+                    return true;
+                else
+                    return (disabled_inequality_set_.end() == disabled_inequality_set_.find(inequality_opr_to_string(inequality)));
+            }
+            
+            bool function_disabled(const std::string& function_name)
+            {
+                if (disabled_func_set_.empty())
+                    return false;
+                else
+                    return (disabled_func_set_.end() != disabled_func_set_.find(function_name));
+            }
+            
+            bool control_struct_disabled(const std::string& control_struct)
+            {
+                if (disabled_ctrl_set_.empty())
+                    return false;
+                else
+                    return (disabled_ctrl_set_.end() != disabled_ctrl_set_.find(control_struct));
+            }
+            
+            bool logic_disabled(const std::string& logic_operation)
+            {
+                if (disabled_logic_set_.empty())
+                    return false;
+                else
+                    return (disabled_logic_set_.end() != disabled_logic_set_.find(logic_operation));
+            }
+            
+            bool assignment_disabled(const details::operator_type assignment_operation)
+            {
+                if (disabled_assignment_set_.empty())
+                    return false;
+                else
+                    return (disabled_assignment_set_.end() != disabled_assignment_set_.find(assign_opr_to_string(assignment_operation)));
+            }
+            
+            bool arithmetic_disabled(const details::operator_type arithmetic_operation)
+            {
+                if (disabled_arithmetic_set_.empty())
+                    return false;
+                else
+                    return (disabled_arithmetic_set_.end() != disabled_arithmetic_set_.find(arith_opr_to_string(arithmetic_operation)));
+            }
+            
+            bool inequality_disabled(const details::operator_type& inequality)
+            {
+                if (disabled_inequality_set_.empty())
+                    return false;
+                else
+                    return (disabled_inequality_set_.end() != disabled_inequality_set_.find(inequality_opr_to_string(inequality)));
+            }
+            
+            settings_store& disable_base_function(settings_base_funcs bf)
+            {
+                if (
+                    (e_bf_unknown != bf) &&
+                    (static_cast<std::size_t>(bf) < (details::base_function_list_size + 1))
+                    )
+                {
+                    disabled_func_set_.insert(details::base_function_list[bf - 1]);
+                }
+                
+                return *this;
+            }
+            
+            settings_store& disable_control_structure(settings_control_structs ctrl_struct)
+            {
+                if (
+                    (e_ctrl_unknown != ctrl_struct) &&
+                    (static_cast<std::size_t>(ctrl_struct) < (details::cntrl_struct_list_size + 1))
+                    )
+                {
+                    disabled_ctrl_set_.insert(details::cntrl_struct_list[ctrl_struct - 1]);
+                }
+                
+                return *this;
+            }
+            
+            settings_store& disable_logic_operation(settings_logic_opr logic)
+            {
+                if (
+                    (e_logic_unknown != logic) &&
+                    (static_cast<std::size_t>(logic) < (details::logic_ops_list_size + 1))
+                    )
+                {
+                    disabled_logic_set_.insert(details::logic_ops_list[logic - 1]);
+                }
+                
+                return *this;
+            }
+            
+            settings_store& disable_arithmetic_operation(settings_arithmetic_opr arithmetic)
+            {
+                if (
+                    (e_arith_unknown != arithmetic) &&
+                    (static_cast<std::size_t>(arithmetic) < (details::arithmetic_ops_list_size + 1))
+                    )
+                {
+                    disabled_arithmetic_set_.insert(details::arithmetic_ops_list[arithmetic - 1]);
+                }
+                
+                return *this;
+            }
+            
+            settings_store& disable_assignment_operation(settings_assignment_opr assignment)
+            {
+                if (
+                    (e_assign_unknown != assignment) &&
+                    (static_cast<std::size_t>(assignment) < (details::assignment_ops_list_size + 1))
+                    )
+                {
+                    disabled_assignment_set_.insert(details::assignment_ops_list[assignment - 1]);
+                }
+                
+                return *this;
+            }
+            
+            settings_store& disable_inequality_operation(settings_inequality_opr inequality)
+            {
+                if (
+                    (e_ineq_unknown != inequality) &&
+                    (static_cast<std::size_t>(inequality) < (details::inequality_ops_list_size + 1))
+                    )
+                {
+                    disabled_inequality_set_.insert(details::inequality_ops_list[inequality - 1]);
+                }
+                
+                return *this;
+            }
+            
+            settings_store& enable_base_function(settings_base_funcs bf)
+            {
+                if (
+                    (e_bf_unknown != bf) &&
+                    (static_cast<std::size_t>(bf) < (details::base_function_list_size + 1))
+                    )
+                {
+                    des_itr_t itr = disabled_func_set_.find(details::base_function_list[bf - 1]);
+                    
+                    if (disabled_func_set_.end() != itr)
+                    {
+                        disabled_func_set_.erase(itr);
+                    }
+                }
+                
+                return *this;
+            }
+            
+            settings_store& enable_control_structure(settings_control_structs ctrl_struct)
+            {
+                if (
+                    (e_ctrl_unknown != ctrl_struct) &&
+                    (static_cast<std::size_t>(ctrl_struct) < (details::cntrl_struct_list_size + 1))
+                    )
+                {
+                    des_itr_t itr = disabled_ctrl_set_.find(details::cntrl_struct_list[ctrl_struct - 1]);
+                    
+                    if (disabled_ctrl_set_.end() != itr)
+                    {
+                        disabled_ctrl_set_.erase(itr);
+                    }
+                }
+                
+                return *this;
+            }
+            
+            settings_store& enable_logic_operation(settings_logic_opr logic)
+            {
+                if (
+                    (e_logic_unknown != logic) &&
+                    (static_cast<std::size_t>(logic) < (details::logic_ops_list_size + 1))
+                    )
+                {
+                    des_itr_t itr = disabled_logic_set_.find(details::logic_ops_list[logic - 1]);
+                    
+                    if (disabled_logic_set_.end() != itr)
+                    {
+                        disabled_logic_set_.erase(itr);
+                    }
+                }
+                
+                return *this;
+            }
+            
+            settings_store& enable_arithmetic_operation(settings_arithmetic_opr arithmetic)
+            {
+                if (
+                    (e_arith_unknown != arithmetic) &&
+                    (static_cast<std::size_t>(arithmetic) < (details::arithmetic_ops_list_size + 1))
+                    )
+                {
+                    des_itr_t itr = disabled_arithmetic_set_.find(details::arithmetic_ops_list[arithmetic - 1]);
+                    
+                    if (disabled_arithmetic_set_.end() != itr)
+                    {
+                        disabled_arithmetic_set_.erase(itr);
+                    }
+                }
+                
+                return *this;
+            }
+            
+            settings_store& enable_assignment_operation(settings_assignment_opr assignment)
+            {
+                if (
+                    (e_assign_unknown != assignment) &&
+                    (static_cast<std::size_t>(assignment) < (details::assignment_ops_list_size + 1))
+                    )
+                {
+                    des_itr_t itr = disabled_assignment_set_.find(details::assignment_ops_list[assignment - 1]);
+                    
+                    if (disabled_assignment_set_.end() != itr)
+                    {
+                        disabled_assignment_set_.erase(itr);
+                    }
+                }
+                
+                return *this;
+            }
+            
+            settings_store& enable_inequality_operation(settings_inequality_opr inequality)
+            {
+                if (
+                    (e_ineq_unknown != inequality) &&
+                    (static_cast<std::size_t>(inequality) < (details::inequality_ops_list_size + 1))
+                    )
+                {
+                    des_itr_t itr = disabled_inequality_set_.find(details::inequality_ops_list[inequality - 1]);
+                    
+                    if (disabled_inequality_set_.end() != itr)
+                    {
+                        disabled_inequality_set_.erase(itr);
+                    }
+                }
+                
+                return *this;
+            }
+            
+        private:
+            
+            void load_compile_options(const std::size_t compile_options)
+            {
+                enable_replacer_           = (compile_options & e_replacer            ) == e_replacer;
+                enable_joiner_             = (compile_options & e_joiner              ) == e_joiner;
+                enable_numeric_check_      = (compile_options & e_numeric_check       ) == e_numeric_check;
+                enable_bracket_check_      = (compile_options & e_bracket_check       ) == e_bracket_check;
+                enable_sequence_check_     = (compile_options & e_sequence_check      ) == e_sequence_check;
+                enable_commutative_check_  = (compile_options & e_commutative_check   ) == e_commutative_check;
+                enable_strength_reduction_ = (compile_options & e_strength_reduction  ) == e_strength_reduction;
+                enable_collect_vars_       = (compile_options & e_collect_vars        ) == e_collect_vars;
+                enable_collect_funcs_      = (compile_options & e_collect_funcs       ) == e_collect_funcs;
+                enable_collect_assings_    = (compile_options & e_collect_assings     ) == e_collect_assings;
+                disable_vardef_            = (compile_options & e_disable_vardef      ) == e_disable_vardef;
+                disable_rsrvd_sym_usr_     = (compile_options & e_disable_usr_on_rsrvd) == e_disable_usr_on_rsrvd;
+                disable_zero_return_       = (compile_options & e_disable_zero_return ) == e_disable_zero_return;
+            }
+            
+            std::string assign_opr_to_string(details::operator_type opr)
+            {
+                switch (opr)
+                {
+                    case details::e_assign : return ":=";
+                    case details::e_addass : return "+=";
+                    case details::e_subass : return "-=";
+                    case details::e_mulass : return "*=";
+                    case details::e_divass : return "/=";
+                    case details::e_modass : return "%=";
+                    default                : return   "";
+                }
+            }
+            
+            std::string arith_opr_to_string(details::operator_type opr)
+            {
+                switch (opr)
+                {
+                    case details::e_add : return "+";
+                    case details::e_sub : return "-";
+                    case details::e_mul : return "*";
+                    case details::e_div : return "/";
+                    case details::e_mod : return "%";
+                    default             : return  "";
+                }
+            }
+            
+            std::string inequality_opr_to_string(details::operator_type opr)
+            {
+                switch (opr)
+                {
+                    case details::e_lt    : return  "<";
+                    case details::e_lte   : return "<=";
+                    case details::e_eq    : return "==";
+                    case details::e_equal : return  "=";
+                    case details::e_ne    : return "!=";
+                    case details::e_nequal: return "<>";
+                    case details::e_gte   : return ">=";
+                    case details::e_gt    : return  ">";
+                    default               : return   "";
+                }
+            }
+            
+            bool enable_replacer_;
+            bool enable_joiner_;
+            bool enable_numeric_check_;
+            bool enable_bracket_check_;
+            bool enable_sequence_check_;
+            bool enable_commutative_check_;
+            bool enable_strength_reduction_;
+            bool enable_collect_vars_;
+            bool enable_collect_funcs_;
+            bool enable_collect_assings_;
+            bool disable_vardef_;
+            bool disable_rsrvd_sym_usr_;
+            bool disable_zero_return_;
+            
+            disabled_entity_set_t disabled_func_set_ ;
+            disabled_entity_set_t disabled_ctrl_set_ ;
+            disabled_entity_set_t disabled_logic_set_;
+            disabled_entity_set_t disabled_arithmetic_set_;
+            disabled_entity_set_t disabled_assignment_set_;
+            disabled_entity_set_t disabled_inequality_set_;
+            
+            friend class parser<T>;
+        };
+        
+        typedef settings_store settings_t;
+        
+        parser(const settings_t& settings = settings_t())
+        : settings_(settings),
+        resolve_unknown_symbol_(false),
+        results_context_(0),
+        unknown_symbol_resolver_(reinterpret_cast<unknown_symbol_resolver*>(0)),
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning (disable:4355)
+#endif
+        sem_(*this),
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+        operator_joiner_2_(2),
+        operator_joiner_3_(3)
+        {
+            init_precompilation();
+            
+            load_operations_map           (base_ops_map_     );
+            load_unary_operations_map     (unary_op_map_     );
+            load_binary_operations_map    (binary_op_map_    );
+            load_inv_binary_operations_map(inv_binary_op_map_);
+            load_sf3_map                  (sf3_map_          );
+            load_sf4_map                  (sf4_map_          );
+            
+            expression_generator_.init_synthesize_map();
+            expression_generator_.set_parser(*this);
+            expression_generator_.set_uom(unary_op_map_);
+            expression_generator_.set_bom(binary_op_map_);
+            expression_generator_.set_ibom(inv_binary_op_map_);
+            expression_generator_.set_sf3m(sf3_map_);
+            expression_generator_.set_sf4m(sf4_map_);
+            expression_generator_.set_strength_reduction_state(settings_.strength_reduction_enabled());
+        }
+        
+        ~parser()
+        {}
+        
+        inline void init_precompilation()
+        {
+            if (settings_.collect_variables_enabled())
+                dec_.collect_variables() = true;
+            
+            if (settings_.collect_functions_enabled())
+                dec_.collect_functions() = true;
+            
+            if (settings_.collect_assignments_enabled())
+                dec_.collect_assignments() = true;
+            
+            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);
+                helper_assembly_.token_modifier_list.clear();
+                helper_assembly_.register_modifier(&symbol_replacer_);
+            }
+            
+            if (settings_.commutative_check_enabled())
+            {
+                for (std::size_t i = 0; i < details::reserved_words_size; ++i)
+                {
+                    commutative_inserter_.ignore_symbol(details::reserved_words[i]);
+                }
+                
+                helper_assembly_.token_inserter_list.clear();
+                helper_assembly_.register_inserter(&commutative_inserter_);
+            }
+            
+            if (settings_.joiner_enabled())
+            {
+                helper_assembly_.token_joiner_list.clear();
+                helper_assembly_.register_joiner(&operator_joiner_2_);
+                helper_assembly_.register_joiner(&operator_joiner_3_);
+            }
+            
+            if (
+                settings_.numeric_check_enabled () ||
+                settings_.bracket_check_enabled () ||
+                settings_.sequence_check_enabled()
+                )
+            {
+                helper_assembly_.token_scanner_list.clear();
+                
+                if (settings_.numeric_check_enabled())
+                {
+                    helper_assembly_.register_scanner(&numeric_checker_);
+                }
+                
+                if (settings_.bracket_check_enabled())
+                {
+                    helper_assembly_.register_scanner(&bracket_checker_);
+                }
+                
+                if (settings_.sequence_check_enabled())
+                {
+                    helper_assembly_.register_scanner(&sequence_validator_);
+                }
+            }
+        }
+        
+        inline bool compile(const std::string& expression_string, expression<T>& expr)
+        {
+            state_          .reset();
+            error_list_     .clear();
+            brkcnt_list_    .clear();
+            synthesis_error_.clear();
+            sem_            .cleanup();
+            
+            return_cleanup();
+            
+            expression_generator_.set_allocator(node_allocator_);
+            
+            if (expression_string.empty())
+            {
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     "ERR000 - Empty expression!"));
+                
+                return false;
             }
-
-            return error_node();
-         }
-
-         const std::string var1_name = current_token_.value;
-
-         if (!token_is(token_t::e_symbol,false))
-         {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token_,
-                          "ERR150 - Expected a symbol for variable or vector element definition"));
-
-            if (variable0_generated)
+            
+            if (!init(expression_string))
             {
-               free_node(node_allocator_,variable0);
+                process_lexer_errors();
+                return false;
             }
-
-            return error_node();
-         }
-         else if (peek_token_is(token_t::e_lsqrbracket))
-         {
-            if (0 == (variable1 = parse_vector()))
-            {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token_,
-                             "ERR151 - Second parameter to swap is an invalid vector element: '" + var1_name + "'"));
-
-               if (variable0_generated)
-               {
-                  free_node(node_allocator_,variable0);
-               }
-
-               return error_node();
-            }
-
-            variable1_generated = true;
-         }
-         else
-         {
-            if (symbol_table_.is_variable(var1_name))
+            
+            if (lexer().empty())
             {
-               variable1 = symbol_table_.get_variable(var1_name);
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     "ERR001 - Empty expression!"));
+                
+                return false;
             }
-
-            scope_element& se = sem_.get_element(var1_name);
-
-            if (
-                 (se.active) &&
-                 (se.name == var1_name) &&
-                 (scope_element::e_variable == se.type)
-               )
+            
+            if (!run_assemblies())
             {
-               variable1 = se.var_node;
+                return false;
             }
-
-            lodge_symbol(var1_name,e_st_variable);
-
-            if (0 == variable1)
-            {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token_,
-                             "ERR152 - Second parameter to swap is an invalid variable: '" + var1_name + "'"));
-
-               if (variable0_generated)
-               {
-                  free_node(node_allocator_,variable0);
-               }
-
-               return error_node();
+            
+            symtab_store_.symtab_list_ = expr.get_symbol_table_list();
+            dec_.clear();
+            
+            lexer().begin();
+            
+            next_token();
+            
+            expression_node_ptr e = parse_corpus();
+            
+            if ((0 != e) && (token_t::e_eof == current_token().type))
+            {
+                bool* retinvk_ptr = 0;
+                
+                if (state_.return_stmt_present)
+                {
+                    dec_.return_present_ = true;
+                    
+                    e = expression_generator_
+                    .return_envelope(e,results_context_,retinvk_ptr);
+                }
+                
+                expr.set_expression(e);
+                expr.set_retinvk(retinvk_ptr);
+                
+                register_local_vars(expr);
+                register_return_results(expr);
+                
+                return !(!expr);
             }
             else
-               next_token();
-         }
-
-         if (!token_is(token_t::e_rbracket))
-         {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token_,
-                          "ERR153 - Expected ')' at end of swap statement"));
-
-            if (variable0_generated)
             {
-               free_node(node_allocator_,variable0);
+                if (error_list_.empty())
+                {
+                    set_error(
+                              make_error(parser_error::e_syntax,
+                                         current_token(),
+                                         "ERR002 - Invalid expression encountered"));
+                }
+                
+                dec_.clear    ();
+                sem_.cleanup  ();
+                return_cleanup();
+                
+                if ((0 != e) && branch_deletable(e))
+                {
+                    delete e;
+                }
+                
+                return false;
+            }
+        }
+        
+        void process_lexer_errors()
+        {
+            for (std::size_t i = 0; i < lexer().size(); ++i)
+            {
+                if (lexer()[i].is_error())
+                {
+                    std::string diagnostic = "ERR003 - ";
+                    
+                    switch (lexer()[i].type)
+                    {
+                        case lexer::token::e_error      : diagnostic += "General token error";
+                            break;
+                            
+                        case lexer::token::e_err_symbol : diagnostic += "Symbol error";
+                            break;
+                            
+                        case lexer::token::e_err_number : diagnostic += "Invalid numeric token";
+                            break;
+                            
+                        case lexer::token::e_err_string : diagnostic += "Invalid string token";
+                            break;
+                            
+                        case lexer::token::e_err_sfunc  : diagnostic += "Invalid special function token";
+                            break;
+                            
+                        default                         : diagnostic += "Unknown compiler error";
+                    }
+                    
+                    set_error(
+                              make_error(parser_error::e_lexer,
+                                         lexer()[i],
+                                         diagnostic + ": " + lexer()[i].value));
+                }
+            }
+        }
+        
+        inline bool run_assemblies()
+        {
+            if (settings_.commutative_check_enabled())
+            {
+                helper_assembly_.run_inserters(lexer());
+            }
+            
+            if (settings_.joiner_enabled())
+            {
+                helper_assembly_.run_joiners(lexer());
+            }
+            
+            if (settings_.replacer_enabled())
+            {
+                helper_assembly_.run_modifiers(lexer());
+            }
+            
+            if (
+                settings_.numeric_check_enabled () ||
+                settings_.bracket_check_enabled () ||
+                settings_.sequence_check_enabled()
+                )
+            {
+                if (!helper_assembly_.run_scanners(lexer()))
+                {
+                    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;
+                        
+                        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 + "'"));
+                        }
+                        else if (0 != (numeric_checker_ptr = dynamic_cast<lexer::helper::numeric_checker*>(helper_assembly_.error_token_scanner)))
+                        {
+                            for (std::size_t i = 0; i < numeric_checker_ptr->error_count(); ++i)
+                            {
+                                lexer::token error_token = lexer()[numeric_checker_ptr->error_index(i)];
+                                
+                                set_error(
+                                          make_error(parser_error::e_token,
+                                                     error_token,
+                                                     "ERR005 - Invalid numeric token: '" + error_token.value + "'"));
+                            }
+                            
+                            if (numeric_checker_ptr->error_count())
+                            {
+                                numeric_checker_ptr->clear_errors();
+                            }
+                        }
+                        else if (0 != (sequence_validator_ptr = dynamic_cast<lexer::helper::sequence_validator*>(helper_assembly_.error_token_scanner)))
+                        {
+                            for (std::size_t i = 0; i < sequence_validator_ptr->error_count(); ++i)
+                            {
+                                std::pair<lexer::token,lexer::token> error_token = sequence_validator_ptr->error(i);
+                                
+                                set_error(
+                                          make_error(parser_error::e_token,
+                                                     error_token.first,
+                                                     "ERR006 - Invalid token sequence: '" +
+                                                     error_token.first.value  + "' and '" +
+                                                     error_token.second.value + "'"));
+                            }
+                            
+                            if (sequence_validator_ptr->error_count())
+                            {
+                                sequence_validator_ptr->clear_errors();
+                            }
+                        }
+                    }
+                    
+                    return false;
+                }
             }
-
-            if (variable1_generated)
+            
+            return true;
+        }
+        
+        inline settings_store& settings()
+        {
+            return settings_;
+        }
+        
+        inline parser_error::type get_error(const std::size_t& index)
+        {
+            if (index < error_list_.size())
+                return error_list_[index];
+            else
+                throw std::invalid_argument("parser::get_error() - Invalid error index specificed");
+        }
+        
+        inline std::string error() const
+        {
+            if (!error_list_.empty())
             {
-               free_node(node_allocator_,variable1);
+                return error_list_[0].diagnostic;
             }
-
-            return error_node();
-         }
-
-         typedef details::variable_node<T>* variable_node_ptr;
-         variable_node_ptr v0 = variable_node_ptr(0);
-         variable_node_ptr v1 = variable_node_ptr(0);
-
-         if (
-              (0 != (v0 = dynamic_cast<variable_node_ptr>(variable0))) &&
-              (0 != (v1 = dynamic_cast<variable_node_ptr>(variable1)))
-            )
-         {
-            expression_node_ptr result = node_allocator_.allocate<details::swap_node<T> >(v0,v1);
-
-            if (variable0_generated)
+            else
+                return std::string("No Error");
+        }
+        
+        inline std::size_t error_count() const
+        {
+            return error_list_.size();
+        }
+        
+        inline dependent_entity_collector& dec()
+        {
+            return dec_;
+        }
+        
+        inline bool replace_symbol(const std::string& old_symbol, const std::string& new_symbol)
+        {
+            if (!settings_.replacer_enabled())
+                return false;
+            else if (details::is_reserved_word(old_symbol))
+                return false;
+            else
+                return symbol_replacer_.add_replace(old_symbol,new_symbol,lexer::token::e_symbol);
+        }
+        
+        inline bool remove_replace_symbol(const std::string& symbol)
+        {
+            if (!settings_.replacer_enabled())
+                return false;
+            else if (details::is_reserved_word(symbol))
+                return false;
+            else
+                return symbol_replacer_.remove(symbol);
+        }
+        
+        inline void enable_unknown_symbol_resolver(unknown_symbol_resolver* usr = reinterpret_cast<unknown_symbol_resolver*>(0))
+        {
+            resolve_unknown_symbol_ = true;
+            
+            if (usr)
+                unknown_symbol_resolver_ = usr;
+            else
+                unknown_symbol_resolver_ = &default_usr_;
+        }
+        
+        inline void disable_unknown_symbol_resolver()
+        {
+            resolve_unknown_symbol_  = false;
+            unknown_symbol_resolver_ = &default_usr_;
+        }
+        
+    private:
+        
+        inline bool valid_base_operation(const std::string& symbol)
+        {
+            const std::size_t length = symbol.size();
+            
+            if (
+                (length < 3) || // Shortest base op symbol length
+                (length > 9)    // Longest base op symbol length
+                )
+                return false;
+            else
+                return settings_.function_enabled(symbol) &&
+                (base_ops_map_.end() != base_ops_map_.find(symbol));
+        }
+        
+        inline bool valid_vararg_operation(const std::string& symbol)
+        {
+            static const std::string s_sum     = "sum" ;
+            static const std::string s_mul     = "mul" ;
+            static const std::string s_avg     = "avg" ;
+            static const std::string s_min     = "min" ;
+            static const std::string s_max     = "max" ;
+            static const std::string s_mand    = "mand";
+            static const std::string s_mor     = "mor" ;
+            static const std::string s_multi   = "~"   ;
+            static const std::string s_mswitch = "[*]" ;
+            
+            return
+            (
+             details::imatch(symbol,s_sum    ) ||
+             details::imatch(symbol,s_mul    ) ||
+             details::imatch(symbol,s_avg    ) ||
+             details::imatch(symbol,s_min    ) ||
+             details::imatch(symbol,s_max    ) ||
+             details::imatch(symbol,s_mand   ) ||
+             details::imatch(symbol,s_mor    ) ||
+             details::imatch(symbol,s_multi  ) ||
+             details::imatch(symbol,s_mswitch)
+             ) &&
+            settings_.function_enabled(symbol);
+        }
+        
+        bool is_invalid_arithmetic_operation(const details::operator_type operation)
+        {
+            return settings_.arithmetic_disabled(operation);
+        }
+        
+        bool is_invalid_assignment_operation(const details::operator_type operation)
+        {
+            return settings_.assignment_disabled(operation);
+        }
+        
+        bool is_invalid_inequality_operation(const details::operator_type operation)
+        {
+            return settings_.inequality_disabled(operation);
+        }
+        
+#ifdef exprtk_enable_debugging
+        inline void next_token()
+        {
+            std::string ct_str = current_token().value;
+            parser_helper::next_token();
+            std::string depth(2 * state_.scope_depth,' ');
+            exprtk_debug(("%s"
+                          "prev[%s] --> curr[%s]\n",
+                          depth.c_str(),
+                          ct_str.c_str(),
+                          current_token().value.c_str()));
+        }
+#endif
+        
+        inline expression_node_ptr parse_corpus()
+        {
+            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;
+            lexer::token   end_token;
+            
+            for ( ; ; )
+            {
+                state_.side_effect_present = false;
+                
+                begin_token = current_token();
+                
+                expression_node_ptr arg = parse_expression();
+                
+                if (0 == arg)
+                {
+                    if (error_list_.empty())
+                    {
+                        set_error(
+                                  make_error(parser_error::e_syntax,
+                                             current_token(),
+                                             "ERR007 - Invalid expression encountered"));
+                    }
+                    
+                    return error_node();
+                }
+                else
+                {
+                    arg_list.push_back(arg);
+                    
+                    side_effect_list.push_back(state_.side_effect_present);
+                    
+                    end_token = current_token();
+                    
+                    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),
+                                  sub_expr.c_str()));
+                    
+                    exprtk_debug(("parse_corpus(%02d) - Side effect present: %s\n",
+                                  static_cast<int>(arg_list.size() - 1),
+                                  state_.side_effect_present ? "true" : "false"));
+                    
+                    exprtk_debug(("-------------------------------------------------\n"));
+                }
+                
+                if (lexer().finished())
+                    break;
+                else if (token_is(token_t::e_eof,prsrhlpr_t::e_hold))
+                {
+                    if (lexer().finished())
+                        break;
+                    else
+                        next_token();
+                }
+            }
+            
+            if (
+                !arg_list.empty() &&
+                is_return_node(arg_list.back())
+                )
             {
-               free_node(node_allocator_,variable0);
+                dec_.final_stmt_return_ = true;
             }
-
-            if (variable1_generated)
+            
+            result = simplify(arg_list,side_effect_list);
+            
+            sdd.delete_ptr = (0 == result);
+            
+            return result;
+        }
+        
+        std::string construct_subexpr(lexer::token& begin_token, lexer::token& end_token)
+        {
+            std::string result = lexer().substr(begin_token.position,end_token.position);
+            
+            for (std::size_t i = 0; i < result.size(); ++i)
             {
-               free_node(node_allocator_,variable1);
+                if (details::is_whitespace(result[i])) result[i] = ' ';
             }
-
+            
             return result;
-         }
-         else
-            return node_allocator_.allocate<details::swap_generic_node<T> >(variable0,variable1);
-      }
-
-      inline bool post_variable_process(const std::string& symbol)
-      {
-         if (
-              peek_token_is(token_t::e_lbracket   ) ||
-              peek_token_is(token_t::e_lcrlbracket) ||
-              peek_token_is(token_t::e_lsqrbracket)
-            )
-         {
-            if (!commutative_check_enabled())
-            {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token_,
-                             "ERR154 - Invalid sequence of variable '"+ symbol + "' and bracket"));
-
-               return false;
-            }
-
-            lexer_.insert_front(token_t::e_mul);
-         }
-
-         return true;
-      }
-
-      inline bool post_bracket_process(const typename token_t::token_type& token, expression_node_ptr& branch)
-      {
-         bool implied_mul = false;
-
-         if (is_generally_string_node(branch))
-            return true;
-
-         switch (token)
-         {
-            case token_t::e_lcrlbracket : implied_mul = token_is(token_t::e_lbracket   ,false) ||
-                                                        token_is(token_t::e_lcrlbracket,false) ||
-                                                        token_is(token_t::e_lsqrbracket,false) ;
-                                          break;
-
-            case token_t::e_lbracket    : implied_mul = token_is(token_t::e_lbracket   ,false) ||
-                                                        token_is(token_t::e_lcrlbracket,false) ||
-                                                        token_is(token_t::e_lsqrbracket,false) ;
-                                          break;
-
-            case token_t::e_lsqrbracket : implied_mul = token_is(token_t::e_lbracket   ,false) ||
-                                                        token_is(token_t::e_lcrlbracket,false) ||
-                                                        token_is(token_t::e_lsqrbracket,false) ;
-                                          break;
-
-            default                     : return true;
-         }
-
-         if (implied_mul)
-         {
-            if (!commutative_check_enabled())
-            {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token_,
-                             "ERR155 - Invalid sequence of brackets"));
-
-               return false;
+        }
+        
+        static const precedence_level default_precedence = e_level00;
+        
+        struct state_t
+        {
+            inline void set(const precedence_level& l,
+                            const precedence_level& r,
+                            const details::operator_type& o)
+            {
+                left  = l;
+                right = r;
+                operation = o;
+            }
+            
+            inline void reset()
+            {
+                left      = e_level00;
+                right     = e_level00;
+                operation = details::e_default;
+            }
+            
+            precedence_level left;
+            precedence_level right;
+            details::operator_type operation;
+        };
+        
+        inline expression_node_ptr parse_expression(precedence_level precedence = e_level00)
+        {
+            expression_node_ptr expression = parse_branch(precedence);
+            
+            if (0 == expression)
+            {
+                return error_node();
+            }
+            
+            bool break_loop = false;
+            
+            state_t current_state;
+            
+            for ( ; ; )
+            {
+                current_state.reset();
+                
+                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;
+                    default                : if (token_t::e_symbol == current_token().type)
+                    {
+                        static const std::string s_and   =   "and";
+                        static const std::string s_nand  =  "nand";
+                        static const std::string s_or    =    "or";
+                        static const std::string s_nor   =   "nor";
+                        static const std::string s_xor   =   "xor";
+                        static const std::string s_xnor  =  "xnor";
+                        static const std::string s_in    =    "in";
+                        static const std::string s_like  =  "like";
+                        static const std::string s_ilike = "ilike";
+                        static const std::string s_and1  =     "&";
+                        static const std::string s_or1   =     "|";
+                        
+                        if (details::imatch(current_token().value,s_and))
+                        {
+                            current_state.set(e_level03,e_level04,details::e_and);
+                            break;
+                        }
+                        else if (details::imatch(current_token().value,s_and1))
+                        {
+#ifndef exprtk_disable_sc_andor
+                            current_state.set(e_level03,e_level04,details::e_scand);
+#else
+                            current_state.set(e_level03,e_level04,details::e_and);
+#endif
+                            break;
+                        }
+                        else if (details::imatch(current_token().value,s_nand))
+                        {
+                            current_state.set(e_level03,e_level04,details::e_nand);
+                            break;
+                        }
+                        else if (details::imatch(current_token().value,s_or))
+                        {
+                            current_state.set(e_level01,e_level02,details::e_or);
+                            break;
+                        }
+                        else if (details::imatch(current_token().value,s_or1))
+                        {
+#ifndef exprtk_disable_sc_andor
+                            current_state.set(e_level01,e_level02,details::e_scor);
+#else
+                            current_state.set(e_level01,e_level02,details::e_or);
+#endif
+                            break;
+                        }
+                        else if (details::imatch(current_token().value,s_nor))
+                        {
+                            current_state.set(e_level01,e_level02,details::e_nor);
+                            break;
+                        }
+                        else if (details::imatch(current_token().value,s_xor))
+                        {
+                            current_state.set(e_level01,e_level02,details::e_xor);
+                            break;
+                        }
+                        else if (details::imatch(current_token().value,s_xnor))
+                        {
+                            current_state.set(e_level01,e_level02,details::e_xnor);
+                            break;
+                        }
+                        else if (details::imatch(current_token().value,s_in))
+                        {
+                            current_state.set(e_level04,e_level04,details::e_in);
+                            break;
+                        }
+                        else if (details::imatch(current_token().value,s_like))
+                        {
+                            current_state.set(e_level04,e_level04,details::e_like);
+                            break;
+                        }
+                        else if (details::imatch(current_token().value,s_ilike))
+                        {
+                            current_state.set(e_level04,e_level04,details::e_ilike);
+                            break;
+                        }
+                    }
+                        
+                        break_loop = true;
+                }
+                
+                if (break_loop)
+                {
+                    parse_pending_string_rangesize(expression);
+                    break;
+                }
+                else if (current_state.left < precedence)
+                    break;
+                
+                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))
+                {
+                    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) + "'"));
+                    
+                    return error_node();
+                }
+                else if (is_invalid_inequality_operation(current_state.operation))
+                {
+                    free_node(node_allocator_,expression);
+                    
+                    set_error(
+                              make_error(parser_error::e_syntax,
+                                         prev_token,
+                                         "ERR009 - Invalid inequality operation '" + details::to_str(current_state.operation) + "'"));
+                    
+                    return error_node();
+                }
+                else if (is_invalid_assignment_operation(current_state.operation))
+                {
+                    free_node(node_allocator_,expression);
+                    
+                    set_error(
+                              make_error(parser_error::e_syntax,
+                                         prev_token,
+                                         "ERR010 - Invalid assignment operation '" + details::to_str(current_state.operation) + "'"));
+                    
+                    return error_node();
+                }
+                
+                if (0 != (right_branch = parse_expression(current_state.right)))
+                {
+                    if (
+                        details::is_return_node(  expression) ||
+                        details::is_return_node(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"));
+                        
+                        return error_node();
+                    }
+                    
+                    new_expression = expression_generator_
+                    (
+                     current_state.operation,
+                     expression,
+                     right_branch
+                     );
+                }
+                
+                if (0 == new_expression)
+                {
+                    if (error_list_.empty())
+                    {
+                        set_error(
+                                  make_error(parser_error::e_syntax,
+                                             prev_token,
+                                             !synthesis_error_.empty() ?
+                                             synthesis_error_ :
+                                             "ERR012 - General parsing error at token: '" + prev_token.value + "'"));
+                    }
+                    
+                    free_node(node_allocator_,expression);
+                    
+                    return error_node();
+                }
+                else
+                {
+                    if (
+                        token_is(token_t::e_ternary,prsrhlpr_t::e_hold) &&
+                        (precedence == e_level00)
+                        )
+                    {
+                        expression = parse_ternary_conditional_statement(new_expression);
+                    }
+                    else
+                        expression = new_expression;
+                    
+                    parse_pending_string_rangesize(expression);
+                }
+            }
+            
+            return expression;
+        }
+        
+        bool simplify_unary_negation_branch(expression_node_ptr& node)
+        {
+            {
+                typedef details::unary_branch_node<T,details::neg_op<T> > ubn_t;
+                ubn_t* n = dynamic_cast<ubn_t*>(node);
+                
+                if (n)
+                {
+                    expression_node_ptr un_r = n->branch(0);
+                    n->release();
+                    free_node(node_allocator_,node);
+                    node = un_r;
+                    
+                    return true;
+                }
+            }
+            
+            {
+                typedef details::unary_variable_node<T,details::neg_op<T> > uvn_t;
+                
+                uvn_t* n = dynamic_cast<uvn_t*>(node);
+                
+                if (n)
+                {
+                    const T& v = n->v();
+                    expression_node_ptr return_node = error_node();
+                    
+                    if (
+                        (0 != (return_node = symtab_store_.get_variable(v))) ||
+                        (0 != (return_node = sem_         .get_variable(v)))
+                        )
+                    {
+                        free_node(node_allocator_,node);
+                        node = return_node;
+                        
+                        return true;
+                    }
+                    else
+                    {
+                        set_error(
+                                  make_error(parser_error::e_syntax,
+                                             current_token(),
+                                             "ERR013 - Failed to find variable node in symbol table"));
+                        
+                        free_node(node_allocator_,node);
+                        
+                        return false;
+                    }
+                }
             }
-            else if (token_t::e_eof != current_token_.type)
+            
+            return false;
+        }
+        
+        static inline expression_node_ptr error_node()
+        {
+            return reinterpret_cast<expression_node_ptr>(0);
+        }
+        
+        template <typename Type, std::size_t N>
+        struct scoped_delete
+        {
+            typedef Type* ptr_t;
+            
+            scoped_delete(parser<T>& pr, ptr_t& p)
+            : delete_ptr(true),
+            parser_(pr),
+            p_(&p)
+            {}
+            
+            scoped_delete(parser<T>& pr, ptr_t (&p)[N])
+            : delete_ptr(true),
+            parser_(pr),
+            p_(&p[0])
+            {}
+            
+            ~scoped_delete()
+            {
+                if (delete_ptr)
+                {
+                    for (std::size_t i = 0; i < N; ++i)
+                    {
+                        free_node(parser_.node_allocator_,p_[i]);
+                    }
+                }
+            }
+            
+            bool delete_ptr;
+            parser<T>& parser_;
+            ptr_t* p_;
+            
+        private:
+            
+            scoped_delete<Type,N>& operator=(const scoped_delete<Type,N>&);
+        };
+        
+        template <typename Type>
+        struct scoped_deq_delete
+        {
+            typedef Type* ptr_t;
+            
+            scoped_deq_delete(parser<T>& pr, std::deque<ptr_t>& deq)
+            : delete_ptr(true),
+            parser_(pr),
+            deq_(deq)
+            {}
+            
+            ~scoped_deq_delete()
+            {
+                if (delete_ptr && !deq_.empty())
+                {
+                    for (std::size_t i = 0; i < deq_.size(); ++i)
+                    {
+                        free_node(parser_.node_allocator_,deq_[i]);
+                    }
+                    
+                    deq_.clear();
+                }
+            }
+            
+            bool delete_ptr;
+            parser<T>& parser_;
+            std::deque<ptr_t>& deq_;
+            
+        private:
+            
+            scoped_deq_delete<Type>& operator=(const scoped_deq_delete<Type>&);
+        };
+        
+        template <typename Type>
+        struct scoped_vec_delete
+        {
+            typedef Type* ptr_t;
+            
+            scoped_vec_delete(parser<T>& pr, std::vector<ptr_t>& vec)
+            : delete_ptr(true),
+            parser_(pr),
+            vec_(vec)
+            {}
+            
+            ~scoped_vec_delete()
+            {
+                if (delete_ptr && !vec_.empty())
+                {
+                    for (std::size_t i = 0; i < vec_.size(); ++i)
+                    {
+                        free_node(parser_.node_allocator_,vec_[i]);
+                    }
+                    
+                    vec_.clear();
+                }
+            }
+            
+            bool delete_ptr;
+            parser<T>& parser_;
+            std::vector<ptr_t>& vec_;
+            
+        private:
+            
+            scoped_vec_delete<Type>& operator=(const scoped_vec_delete<Type>&);
+        };
+        
+        struct scoped_bool_negator
+        {
+            scoped_bool_negator(bool& bb)
+            : b(bb)
+            { b = !b; }
+            
+            ~scoped_bool_negator()
+            { b = !b; }
+            
+            bool& b;
+        };
+        
+        struct scoped_bool_or_restorer
+        {
+            scoped_bool_or_restorer(bool& bb)
+            : b(bb),
+            original_value_(bb)
+            {}
+            
+            ~scoped_bool_or_restorer()
             {
-               lexer_.insert_front(current_token_.type);
-               lexer_.insert_front(token_t::e_mul);
-               next_token();
+                b = b || original_value_;
             }
-         }
-
-         return true;
-      }
-
-      inline expression_node_ptr parse_symtab_symbol()
-      {
-         const std::string symbol = current_token_.value;
-
-         // Are we dealing with a variable or a special constant?
-         expression_node_ptr variable = symbol_table_.get_variable(symbol);
-
-         if (variable)
-         {
-            if (symbol_table_.is_constant_node(symbol))
+            
+            bool& b;
+            bool original_value_;
+        };
+        
+        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);
+            
+            switch (function->param_count)
+            {
+                case  0 : func_node = parse_function_call_0  (function,function_name); break;
+                case  1 : func_node = parse_function_call< 1>(function,function_name); break;
+                case  2 : func_node = parse_function_call< 2>(function,function_name); break;
+                case  3 : func_node = parse_function_call< 3>(function,function_name); break;
+                case  4 : func_node = parse_function_call< 4>(function,function_name); break;
+                case  5 : func_node = parse_function_call< 5>(function,function_name); break;
+                case  6 : func_node = parse_function_call< 6>(function,function_name); break;
+                case  7 : func_node = parse_function_call< 7>(function,function_name); break;
+                case  8 : func_node = parse_function_call< 8>(function,function_name); break;
+                case  9 : func_node = parse_function_call< 9>(function,function_name); break;
+                case 10 : func_node = parse_function_call<10>(function,function_name); break;
+                case 11 : func_node = parse_function_call<11>(function,function_name); break;
+                case 12 : func_node = parse_function_call<12>(function,function_name); break;
+                case 13 : func_node = parse_function_call<13>(function,function_name); break;
+                case 14 : func_node = parse_function_call<14>(function,function_name); break;
+                case 15 : func_node = parse_function_call<15>(function,function_name); break;
+                case 16 : func_node = parse_function_call<16>(function,function_name); break;
+                case 17 : func_node = parse_function_call<17>(function,function_name); break;
+                case 18 : func_node = parse_function_call<18>(function,function_name); break;
+                case 19 : func_node = parse_function_call<19>(function,function_name); break;
+                case 20 : func_node = parse_function_call<20>(function,function_name); break;
+                default : {
+                    set_error(
+                              make_error(parser_error::e_syntax,
+                                         current_token(),
+                                         "ERR014 - Invalid number of parameters for function: '" + function_name + "'"));
+                    
+                    return error_node();
+                }
+            }
+            
+            if (func_node)
+                return func_node;
+            else
+            {
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR015 - Failed to generate call to function: '" + function_name + "'"));
+                
+                return error_node();
+            }
+        }
+        
+        template <std::size_t NumberofParameters>
+        inline expression_node_ptr parse_function_call(ifunction<T>* function, const std::string& function_name)
+        {
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable: 4127)
+#endif
+            if (0 == NumberofParameters)
             {
-               variable = expression_generator_(variable->value());
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR016 - Expecting ifunction '" + function_name + "' to have non-zero parameter count"));
+                
+                return error_node();
             }
-
-            if (!post_variable_process(symbol))
-               return error_node();
-
-            lodge_symbol(symbol,e_st_variable);
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+            
+            expression_node_ptr branch[NumberofParameters];
+            expression_node_ptr result  = error_node();
+            
+            std::fill_n(branch,NumberofParameters,reinterpret_cast<expression_node_ptr>(0));
+            scoped_delete<expression_node_t,NumberofParameters> sd(*this,branch);
+            
             next_token();
-
-            return variable;
-         }
-
-         // Are we dealing with a locally defined variable or vector?
-         if (!sem_.empty())
-         {
-            scope_element& se = sem_.get_element(symbol);
-
-            if (se.name == symbol)
-            {
-               if (scope_element::e_variable == se.type)
-               {
-                  se.active = true;
-                  lodge_symbol(symbol,e_st_local_variable);
-
-                  if (!post_variable_process(symbol))
-                     return error_node();
-
-                  next_token();
-
-                  return se.var_node;
-               }
-               else if (scope_element::e_vector == se.type)
-               {
-                  return parse_vector();
-               }
-            }
-         }
-
-         #ifndef exprtk_disable_string_capabilities
-         // Are we dealing with a string variable?
-         if (symbol_table_.is_stringvar(symbol))
-         {
-            return parse_string();
-         }
-         #endif
-
-         {
-            // Are we dealing with a function?
-            ifunction<T>* function = symbol_table_.get_function(symbol);
-
-            if (function)
+            
+            if (!token_is(token_t::e_lbracket))
             {
-               lodge_symbol(symbol,e_st_function);
-
-               expression_node_ptr func_node =
-                                      parse_function_invocation(function,symbol);
-
-               if (func_node)
-                  return func_node;
-               else
-               {
-                  set_error(
-                     make_error(parser_error::e_syntax,
-                                current_token_,
-                                "ERR156 - Failed to generate node for function: '" + symbol + "'"));
-
-                  return error_node();
-               }
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR017 - Expecting argument list for function: '" + function_name + "'"));
+                
+                return error_node();
+            }
+            
+            for (int i = 0; i < static_cast<int>(NumberofParameters); ++i)
+            {
+                branch[i] = parse_expression();
+                
+                if (0 == branch[i])
+                {
+                    set_error(
+                              make_error(parser_error::e_syntax,
+                                         current_token(),
+                                         "ERR018 - Failed to parse argument " + details::to_str(i) + " for function: '" + function_name + "'"));
+                    
+                    return error_node();
+                }
+                else if (i < static_cast<int>(NumberofParameters - 1))
+                {
+                    if (!token_is(token_t::e_comma))
+                    {
+                        set_error(
+                                  make_error(parser_error::e_syntax,
+                                             current_token(),
+                                             "ERR019 - Invalid number of arguments for function: '" + function_name + "'"));
+                        
+                        return error_node();
+                    }
+                }
             }
-         }
-
-         {
-            // Are we dealing with a vararg function?
-            ivararg_function<T>* vararg_function = symbol_table_.get_vararg_function(symbol);
-
-            if (vararg_function)
+            
+            if (!token_is(token_t::e_rbracket))
             {
-               lodge_symbol(symbol,e_st_function);
-
-               expression_node_ptr vararg_func_node =
-                                      parse_vararg_function_call(vararg_function,symbol);
-
-               if (vararg_func_node)
-                  return vararg_func_node;
-               else
-               {
-                  set_error(
-                     make_error(parser_error::e_syntax,
-                                current_token_,
-                                "ERR157 - Failed to generate node for vararg function: '" + symbol + "'"));
-
-                  return error_node();
-               }
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR020 - Invalid number of arguments for function: '" + function_name + "'"));
+                
+                return error_node();
             }
-         }
-
-         {
-            // Are we dealing with a vararg generic function?
-            igeneric_function<T>* generic_function = symbol_table_.get_generic_function(symbol);
-
-            if (generic_function)
+            else
+                result = expression_generator_.function(function,branch);
+            
+            sd.delete_ptr = false;
+            
+            return result;
+        }
+        
+        inline expression_node_ptr parse_function_call_0(ifunction<T>* function, const std::string& function_name)
+        {
+            expression_node_ptr result = expression_generator_.function(function);
+            
+            state_.side_effect_present = function->has_side_effects();
+            
+            next_token();
+            
+            if (
+                token_is(token_t::e_lbracket) &&
+                !token_is(token_t::e_rbracket)
+                )
             {
-               lodge_symbol(symbol,e_st_function);
-
-               expression_node_ptr genericfunc_node =
-                                      parse_generic_function_call(generic_function,symbol);
-
-               if (genericfunc_node)
-                  return genericfunc_node;
-               else
-               {
-                  set_error(
-                     make_error(parser_error::e_syntax,
-                                current_token_,
-                                "ERR158 - Failed to generate node for generic function: '" + symbol + "'"));
-
-                  return error_node();
-               }
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR021 - Expecting '()' to proceed call to function: '" + function_name + "'"));
+                
+                free_node(node_allocator_,result);
+                
+                return error_node();
             }
-         }
-
-         {
-            // Are we dealing with a vararg string returing function?
-            igeneric_function<T>* string_function = symbol_table_.get_string_function(symbol);
-
-            if (string_function)
+            else
+                return result;
+        }
+        
+        template <std::size_t MaxNumberofParameters>
+        inline int parse_base_function_call(expression_node_ptr (&param_list)[MaxNumberofParameters])
+        {
+            std::fill_n(param_list,MaxNumberofParameters,reinterpret_cast<expression_node_ptr>(0));
+            
+            scoped_delete<expression_node_t,MaxNumberofParameters> sd(*this,param_list);
+            
+            next_token();
+            
+            if (!token_is(token_t::e_lbracket))
             {
-               lodge_symbol(symbol,e_st_function);
-
-               expression_node_ptr stringfunc_node =
-                                      parse_string_function_call(string_function,symbol);
-
-               if (stringfunc_node)
-                  return stringfunc_node;
-               else
-               {
-                  set_error(
-                     make_error(parser_error::e_syntax,
-                                current_token_,
-                                "ERR159 - Failed to generate node for string function: '" + symbol + "'"));
-
-                  return error_node();
-               }
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR022 - Expected a '(' at start of function call, instead got: '" + current_token().value + "'"));
+                
+                return 0;
+            }
+            
+            int param_index = 0;
+            
+            for (; param_index < static_cast<int>(MaxNumberofParameters); ++param_index)
+            {
+                param_list[param_index] = parse_expression();
+                
+                if (0 == param_list[param_index])
+                    return 0;
+                else if (token_is(token_t::e_rbracket))
+                    break;
+                else if (token_is(token_t::e_comma))
+                    continue;
+                else
+                {
+                    set_error(
+                              make_error(parser_error::e_syntax,
+                                         current_token(),
+                                         "ERR023 - Expected a ',' between function input parameters, instead got: '" + current_token().value + "'"));
+                    
+                    return 0;
+                }
+            }
+            
+            sd.delete_ptr = false;
+            
+            return (param_index + 1);
+        }
+        
+        inline expression_node_ptr parse_base_operation()
+        {
+            typedef std::pair<base_ops_map_t::iterator,base_ops_map_t::iterator> map_range_t;
+            
+            const std::string operation_name = current_token().value;
+            map_range_t itr_range = base_ops_map_.equal_range(operation_name);
+            
+            if (0 == std::distance(itr_range.first,itr_range.second))
+            {
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR024 - No entry found for base operation: " + operation_name));
+                
+                return error_node();
+            }
+            
+            static const std::size_t MaxNumberofParameters = 4;
+            expression_node_ptr param_list[MaxNumberofParameters] = {0};
+            
+            std::size_t parameter_count = parse_base_function_call(param_list);
+            
+            if (0 == parameter_count)
+            {
+                return error_node();
+            }
+            else if (parameter_count <= MaxNumberofParameters)
+            {
+                for (base_ops_map_t::iterator itr = itr_range.first; itr != itr_range.second; ++itr)
+                {
+                    details::base_operation_t& operation = itr->second;
+                    
+                    if (operation.num_params == parameter_count)
+                    {
+                        switch (parameter_count)
+                        {
+#define base_opr_case(N)                                        \
+case N : {                                                      \
+expression_node_ptr pl##N[N] = {0};                 \
+std::copy(param_list,param_list + N,pl##N);         \
+lodge_symbol(operation_name,e_st_function);         \
+return expression_generator_(operation.type,pl##N); \
+}                                                      \
+
+                                base_opr_case(1)
+                                base_opr_case(2)
+                                base_opr_case(3)
+                                base_opr_case(4)
+#undef base_opr_case
+                        }
+                    }
+                }
             }
-         }
-
-         // Are we dealing with a vector element?
-         if (symbol_table_.is_vector(symbol))
-         {
-            lodge_symbol(symbol,e_st_vector);
-            return parse_vector();
-         }
-
-         if (details::is_reserved_symbol(symbol))
-         {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token_,
-                             "ERR160 - Invalid use of reserved symbol '" + symbol + "'"));
-
-               return error_node();
-         }
-
-         // Should we handle unknown symbols?
-         if (resolve_unknown_symbol_ && unknown_symbol_resolver_)
-         {
-            T default_value = T(0);
-            std::string error_message;
-            typename unknown_symbol_resolver::usr_symbol_type usr_symbol_type;
-
-            if (unknown_symbol_resolver_->process(symbol,usr_symbol_type,default_value,error_message))
+            
+            for (std::size_t i = 0; i < MaxNumberofParameters; ++i)
             {
-               bool create_result = false;
-
-               switch (usr_symbol_type)
-               {
-                  case unknown_symbol_resolver::e_usr_variable_type : create_result = symbol_table_.create_variable(symbol,default_value);
-                                                                      break;
-
-                  case unknown_symbol_resolver::e_usr_constant_type : create_result = symbol_table_.add_constant(symbol,default_value);
-                                                                      break;
-
-                  default                                           : create_result = false;
-               }
-
-               if (create_result)
-               {
-                  expression_node_ptr var = symbol_table_.get_variable(symbol);
-
-                  if (var)
-                  {
-                     if (symbol_table_.is_constant_node(symbol))
-                     {
-                        var = expression_generator_(var->value());
-                     }
-
-                     lodge_symbol(symbol,e_st_variable);
-
-                     if (!post_variable_process(symbol))
-                        return error_node();
-
-                     next_token();
-
-                     return var;
-                  }
-               }
-
-               set_error(
-                  make_error(parser_error::e_symtab,
-                             current_token_,
-                             "ERR161 - Failed to create variable: '" + symbol + "'"));
-
-               return error_node();
+                free_node(node_allocator_,param_list[i]);
             }
-         }
-
-         set_error(
-            make_error(parser_error::e_syntax,
-                       current_token_,
-                       "ERR162 - Undefined symbol: '" + symbol + "'"));
-
-         return error_node();
-      }
-
-      inline expression_node_ptr parse_symbol()
-      {
-         static const std::string symbol_if       = "if"      ;
-         static const std::string symbol_while    = "while"   ;
-         static const std::string symbol_repeat   = "repeat"  ;
-         static const std::string symbol_for      = "for"     ;
-         static const std::string symbol_switch   = "switch"  ;
-         static const std::string symbol_null     = "null"    ;
-         static const std::string symbol_break    = "break"   ;
-         static const std::string symbol_continue = "continue";
-         static const std::string symbol_var      = "var"     ;
-         static const std::string symbol_swap     = "swap"    ;
-
-         if (valid_vararg_operation(current_token_.value))
-         {
-            return parse_vararg_function();
-         }
-         else if (valid_base_operation(current_token_.value))
-         {
-            return parse_base_operation();
-         }
-         else if (details::imatch(current_token_.value,symbol_if))
-         {
-            return parse_conditional_statement();
-         }
-         else if (details::imatch(current_token_.value,symbol_while))
-         {
-            return parse_while_loop();
-         }
-         else if (details::imatch(current_token_.value,symbol_repeat))
-         {
-            return parse_repeat_until_loop();
-         }
-         else if (details::imatch(current_token_.value,symbol_for))
-         {
-            return parse_for_loop();
-         }
-         else if (details::imatch(current_token_.value,symbol_switch))
-         {
-            return parse_switch_statement();
-         }
-         else if (details::is_valid_sf_symbol(current_token_.value))
-         {
-            return parse_special_function();
-         }
-         else if (details::imatch(current_token_.value,symbol_null))
-         {
-            return parse_null_statement();
-         }
-         #ifndef exprtk_disable_break_continue
-         else if (details::imatch(current_token_.value,symbol_break))
-         {
-            return parse_break_statement();
-         }
-         else if (details::imatch(current_token_.value,symbol_continue))
-         {
-            return parse_continue_statement();
-         }
-         #endif
-         else if (details::imatch(current_token_.value,symbol_var))
-         {
-            return parse_define_var_statement();
-         }
-         else if (details::imatch(current_token_.value,symbol_swap))
-         {
-            return parse_swap_statement();
-         }
-         else if (symbol_table_.valid() || !sem_.empty())
-         {
-            return parse_symtab_symbol();
-         }
-         else
-         {
+            
             set_error(
-               make_error(parser_error::e_symtab,
-                          current_token_,
-                          "ERR163 - Variable or function detected, yet symbol-table is invalid, Symbol: " + current_token_.value));
-
+                      make_error(parser_error::e_syntax,
+                                 current_token(),
+                                 "ERR025 - Invalid number of parameters for call to function: '" + operation_name + "'"));
+            
             return error_node();
-         }
-      }
-
-      inline expression_node_ptr parse_branch(precedence_level precedence = e_level00)
-      {
-         expression_node_ptr branch = error_node();
-
-         if (token_t::e_number == current_token_.type)
-         {
-            T numeric_value = T(0);
-
-            if (details::string_to_real(current_token_.value,numeric_value))
+        }
+        
+        inline expression_node_ptr parse_conditional_statement_01(expression_node_ptr condition)
+        {
+            // Parse: [if][(][condition][,][consequent][,][alternative][)]
+            
+            expression_node_ptr consequent  = error_node();
+            expression_node_ptr alternative = error_node();
+            
+            bool result = true;
+            
+            if (!token_is(token_t::e_comma))
+            {
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR026 - Expected ',' between if-statement condition and consequent"));
+                result = false;
+            }
+            else if (0 == (consequent = parse_expression()))
             {
-               expression_node_ptr literal_exp = expression_generator_(numeric_value);
-               next_token();
-               branch = literal_exp;
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR027 - Failed to parse consequent for if-statement"));
+                result = false;
             }
-            else
+            else if (!token_is(token_t::e_comma))
             {
-               set_error(
-                  make_error(parser_error::e_numeric,
-                             current_token_,
-                             "ERR164 - Failed to convert '" + current_token_.value + "' to a number"));
-
-               return error_node();
-            }
-         }
-         else if (token_t::e_symbol == current_token_.type)
-         {
-            branch = parse_symbol();
-         }
-         #ifndef exprtk_disable_string_capabilities
-         else if (token_t::e_string == current_token_.type)
-         {
-            branch = parse_const_string();
-         }
-         #endif
-         else if (token_t::e_lbracket == current_token_.type)
-         {
-            next_token();
-
-            if (0 == (branch = parse_expression()))
-               return error_node();
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR028 - Expected ',' between if-statement consequent and alternative"));
+                result = false;
+            }
+            else if (0 == (alternative = parse_expression()))
+            {
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR029 - Failed to parse alternative for if-statement"));
+                result = false;
+            }
             else if (!token_is(token_t::e_rbracket))
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token_,
-                             "ERR165 - Expected ')' instead of: '" + current_token_.value + "'"));
-
-               free_node(node_allocator_,branch);
-
-               return error_node();
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR030 - Expected ')' at the end of if-statement"));
+                result = false;
             }
-            else if (!post_bracket_process(token_t::e_lbracket,branch))
+            
+#ifndef exprtk_disable_string_capabilities
+            if (result)
             {
-               free_node(node_allocator_,branch);
-
-               return error_node();
+                const bool consq_is_str = is_generally_string_node( consequent);
+                const bool alter_is_str = is_generally_string_node(alternative);
+                
+                if (consq_is_str || alter_is_str)
+                {
+                    if (consq_is_str && alter_is_str)
+                    {
+                        return expression_generator_
+                        .conditional_string(condition,consequent,alternative);
+                    }
+                    
+                    set_error(
+                              make_error(parser_error::e_syntax,
+                                         current_token(),
+                                         "ERR031 - Return types of ternary if-statement differ"));
+                    
+                    result = false;
+                }
             }
-         }
-         else if (token_t::e_lsqrbracket == current_token_.type)
-         {
-            next_token();
-
-            if (0 == (branch = parse_expression()))
-               return error_node();
-            else if (!token_is(token_t::e_rsqrbracket))
+#endif
+            
+            if (!result)
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token_,
-                             "ERR166 - Expected ']' instead of: '" + current_token_.value + "'"));
-
-               free_node(node_allocator_,branch);
-
-               return error_node();
+                free_node(node_allocator_,  condition);
+                free_node(node_allocator_, consequent);
+                free_node(node_allocator_,alternative);
+                
+                return error_node();
             }
-            else if (!post_bracket_process(token_t::e_lsqrbracket,branch))
+            else
+                return expression_generator_
+                .conditional(condition,consequent,alternative);
+        }
+        
+        inline expression_node_ptr parse_conditional_statement_02(expression_node_ptr condition)
+        {
+            expression_node_ptr consequent  = error_node();
+            expression_node_ptr alternative = error_node();
+            
+            bool result = true;
+            
+            if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold))
+            {
+                if (0 == (consequent = parse_multi_sequence("if-statement-01")))
+                {
+                    set_error(
+                              make_error(parser_error::e_syntax,
+                                         current_token(),
+                                         "ERR032 - Failed to parse body of consequent for if-statement"));
+                    result = false;
+                }
+            }
+            else
             {
-               free_node(node_allocator_,branch);
-
-               return error_node();
+                if (
+                    settings_.commutative_check_enabled() &&
+                    token_is(token_t::e_mul,prsrhlpr_t::e_hold)
+                    )
+                {
+                    next_token();
+                }
+                
+                if (0 != (consequent = parse_expression()))
+                {
+                    if (!token_is(token_t::e_eof))
+                    {
+                        set_error(
+                                  make_error(parser_error::e_syntax,
+                                             current_token(),
+                                             "ERR033 - Expected ';' at the end of the consequent for if-statement"));
+                        result = false;
+                    }
+                }
+                else
+                {
+                    set_error(
+                              make_error(parser_error::e_syntax,
+                                         current_token(),
+                                         "ERR034 - Failed to parse body of consequent for if-statement"));
+                    result = false;
+                }
+            }
+            
+            if (result)
+            {
+                if (details::imatch(current_token().value,"else"))
+                {
+                    next_token();
+                    
+                    if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold))
+                    {
+                        if (0 == (alternative = parse_multi_sequence("else-statement-01")))
+                        {
+                            set_error(
+                                      make_error(parser_error::e_syntax,
+                                                 current_token(),
+                                                 "ERR035 - Failed to parse body of the 'else' for if-statement"));
+                            result = false;
+                        }
+                    }
+                    else if (details::imatch(current_token().value,"if"))
+                    {
+                        if (0 == (alternative = parse_conditional_statement()))
+                        {
+                            set_error(
+                                      make_error(parser_error::e_syntax,
+                                                 current_token(),
+                                                 "ERR036 - Failed to parse body of if-else statement"));
+                            result = false;
+                        }
+                    }
+                    else if (0 != (alternative = parse_expression()))
+                    {
+                        if (!token_is(token_t::e_eof))
+                        {
+                            set_error(
+                                      make_error(parser_error::e_syntax,
+                                                 current_token(),
+                                                 "ERR037 - Expected ';' at the end of the 'else-if' for the if-statement"));
+                            result = false;
+                        }
+                    }
+                    else
+                    {
+                        set_error(
+                                  make_error(parser_error::e_syntax,
+                                             current_token(),
+                                             "ERR038 - Failed to parse body of the 'else' for if-statement"));
+                        result = false;
+                    }
+                }
             }
-         }
-         else if (token_t::e_lcrlbracket == current_token_.type)
-         {
-            next_token();
-
-            if (0 == (branch = parse_expression()))
-               return error_node();
-            else if (!token_is(token_t::e_rcrlbracket))
-            {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token_,
-                             "ERR167 - Expected '}' instead of: '" + current_token_.value + "'"));
-
-               free_node(node_allocator_,branch);
-
-               return error_node();
+            
+#ifndef exprtk_disable_string_capabilities
+            if (result)
+            {
+                const bool consq_is_str = is_generally_string_node( consequent);
+                const bool alter_is_str = is_generally_string_node(alternative);
+                
+                if (consq_is_str || alter_is_str)
+                {
+                    if (consq_is_str && alter_is_str)
+                    {
+                        return expression_generator_
+                        .conditional_string(condition,consequent,alternative);
+                    }
+                    
+                    set_error(
+                              make_error(parser_error::e_syntax,
+                                         current_token(),
+                                         "ERR039 - Return types of ternary if-statement differ"));
+                    
+                    result = false;
+                }
             }
-            else if (!post_bracket_process(token_t::e_lcrlbracket,branch))
+#endif
+            
+            if (!result)
             {
-               free_node(node_allocator_,branch);
-
-               return error_node();
+                free_node(node_allocator_,  condition);
+                free_node(node_allocator_, consequent);
+                free_node(node_allocator_,alternative);
+                
+                return error_node();
             }
-         }
-         else if (token_t::e_sub == current_token_.type)
-         {
-            next_token();
-            branch = parse_expression(e_level11);
-
-            if (
-                 branch &&
-                 !(
-                    details::is_neg_unary_node    (branch) &&
-                    simplify_unary_negation_branch(branch)
-                  )
-               )
-            {
-               branch = expression_generator_(details::e_neg,branch);
-            }
-         }
-         else if (token_t::e_add == current_token_.type)
-         {
+            else
+                return expression_generator_
+                .conditional(condition,consequent,alternative);
+        }
+        
+        inline expression_node_ptr parse_conditional_statement()
+        {
+            expression_node_ptr condition = error_node();
+            
             next_token();
-            branch = parse_expression(e_level13);
-         }
-         else if (token_t::e_eof == current_token_.type)
-         {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token_,
-                          "ERR168 - Premature end of expression[1]"));
-
-            return error_node();
-         }
-         else
-         {
+            
+            if (!token_is(token_t::e_lbracket))
+            {
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR040 - Expected '(' at start of if-statement, instead got: '" + current_token().value + "'"));
+                
+                return error_node();
+            }
+            else if (0 == (condition = parse_expression()))
+            {
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR041 - Failed to parse condition for if-statement"));
+                
+                return error_node();
+            }
+            else if (token_is(token_t::e_comma,prsrhlpr_t::e_hold))
+            {
+                // if (x,y,z)
+                return parse_conditional_statement_01(condition);
+            }
+            else if (token_is(token_t::e_rbracket))
+            {
+                // 00. if (x) y;
+                // 01. if (x) y; else z;
+                // 02. if (x) y; else {z0; ... zn;}
+                // 03. if (x) y; else if (z) w;
+                // 04. if (x) y; else if (z) w; else u;
+                // 05. if (x) y; else if (z) w; else {u0; ... un;}
+                // 06. if (x) y; else if (z) {w0; ... wn;}
+                // 07. if (x) {y0; ... yn;}
+                // 08. if (x) {y0; ... yn;} else z;
+                // 09. if (x) {y0; ... yn;} else {z0; ... zn;};
+                // 10. if (x) {y0; ... yn;} else if (z) w;
+                // 11. if (x) {y0; ... yn;} else if (z) w; else u;
+                // 12. if (x) {y0; ... nex;} else if (z) w; else {u0 ... un;}
+                // 13. if (x) {y0; ... yn;} else if (z) {w0; ... wn;}
+                return parse_conditional_statement_02(condition);
+            }
+            
             set_error(
-               make_error(parser_error::e_syntax,
-                          current_token_,
-                          "ERR169 - Premature end of expression[2]"));
-
+                      make_error(parser_error::e_syntax,
+                                 current_token(),
+                                 "ERR042 - Invalid if-statement"));
+            
+            free_node(node_allocator_,condition);
+            
             return error_node();
-         }
-
-         if (
-              branch                    &&
-              (e_level00 == precedence) &&
-              token_is(token_t::e_ternary,false)
-            )
-         {
-            branch = parse_ternary_conditional_statement(branch);
-         }
-
-         parse_pending_string_rangesize(branch);
-
-         return branch;
-      }
-
-      inline bool token_is(const typename token_t::token_type& ttype, const bool advance_token = true)
-      {
-         if (current_token_.type != ttype)
-         {
-            return false;
-         }
-
-         if (advance_token)
-         {
-            next_token();
-         }
-
-         return true;
-      }
-
-      inline bool peek_token_is(const typename token_t::token_type& ttype)
-      {
-         return (lexer_.peek_next_token().type == ttype);
-      }
-
-      inline bool peek_token_is(const std::string& s)
-      {
-         return (details::imatch(lexer_.peek_next_token().value,s));
-      }
-
-      template <typename Type>
-      class expression_generator
-      {
-      public:
-
-         typedef details::expression_node<Type>* expression_node_ptr;
-         typedef expression_node_ptr (*synthesize_functor_t)(expression_generator<T>&, const details::operator_type& operation, expression_node_ptr (&branch)[2]);
-         typedef std::map<std::string,synthesize_functor_t> synthesize_map_t;
-         typedef typename exprtk::parser<Type> parser_t;
-         typedef const Type& vtype;
-         typedef const Type  ctype;
-
-         inline void init_synthesize_map()
-         {
-            #ifndef exprtk_disable_enhanced_features
-            synthesize_map_["(v)o(v)"] = synthesize_vov_expression::process;
-            synthesize_map_["(c)o(v)"] = synthesize_cov_expression::process;
-            synthesize_map_["(v)o(c)"] = synthesize_voc_expression::process;
-
-            #define register_synthezier(S)                      \
-            synthesize_map_[S ::node_type::id()] = S ::process; \
-
-            register_synthezier(synthesize_vovov_expression0)
-            register_synthezier(synthesize_vovov_expression1)
-            register_synthezier(synthesize_vovoc_expression0)
-            register_synthezier(synthesize_vovoc_expression1)
-            register_synthezier(synthesize_vocov_expression0)
-            register_synthezier(synthesize_vocov_expression1)
-            register_synthezier(synthesize_covov_expression0)
-            register_synthezier(synthesize_covov_expression1)
-            register_synthezier(synthesize_covoc_expression0)
-            register_synthezier(synthesize_covoc_expression1)
-            register_synthezier(synthesize_cocov_expression1)
-            register_synthezier(synthesize_vococ_expression0)
-
-            register_synthezier(synthesize_vovovov_expression0)
-            register_synthezier(synthesize_vovovoc_expression0)
-            register_synthezier(synthesize_vovocov_expression0)
-            register_synthezier(synthesize_vocovov_expression0)
-            register_synthezier(synthesize_covovov_expression0)
-            register_synthezier(synthesize_covocov_expression0)
-            register_synthezier(synthesize_vocovoc_expression0)
-            register_synthezier(synthesize_covovoc_expression0)
-            register_synthezier(synthesize_vococov_expression0)
-
-            register_synthezier(synthesize_vovovov_expression1)
-            register_synthezier(synthesize_vovovoc_expression1)
-            register_synthezier(synthesize_vovocov_expression1)
-            register_synthezier(synthesize_vocovov_expression1)
-            register_synthezier(synthesize_covovov_expression1)
-            register_synthezier(synthesize_covocov_expression1)
-            register_synthezier(synthesize_vocovoc_expression1)
-            register_synthezier(synthesize_covovoc_expression1)
-            register_synthezier(synthesize_vococov_expression1)
-
-            register_synthezier(synthesize_vovovov_expression2)
-            register_synthezier(synthesize_vovovoc_expression2)
-            register_synthezier(synthesize_vovocov_expression2)
-            register_synthezier(synthesize_vocovov_expression2)
-            register_synthezier(synthesize_covovov_expression2)
-            register_synthezier(synthesize_covocov_expression2)
-            register_synthezier(synthesize_vocovoc_expression2)
-            register_synthezier(synthesize_covovoc_expression2)
-
-            register_synthezier(synthesize_vovovov_expression3)
-            register_synthezier(synthesize_vovovoc_expression3)
-            register_synthezier(synthesize_vovocov_expression3)
-            register_synthezier(synthesize_vocovov_expression3)
-            register_synthezier(synthesize_covovov_expression3)
-            register_synthezier(synthesize_covocov_expression3)
-            register_synthezier(synthesize_vocovoc_expression3)
-            register_synthezier(synthesize_covovoc_expression3)
-            register_synthezier(synthesize_vococov_expression3)
-
-            register_synthezier(synthesize_vovovov_expression4)
-            register_synthezier(synthesize_vovovoc_expression4)
-            register_synthezier(synthesize_vovocov_expression4)
-            register_synthezier(synthesize_vocovov_expression4)
-            register_synthezier(synthesize_covovov_expression4)
-            register_synthezier(synthesize_covocov_expression4)
-            register_synthezier(synthesize_vocovoc_expression4)
-            register_synthezier(synthesize_covovoc_expression4)
-            #endif
-         }
-
-         inline void set_parser(parser_t& p)
-         {
-            parser_ = &p;
-         }
-
-         inline void set_uom(unary_op_map_t& unary_op_map)
-         {
-            unary_op_map_ = &unary_op_map;
-         }
-
-         inline void set_bom(binary_op_map_t& binary_op_map)
-         {
-            binary_op_map_ = &binary_op_map;
-         }
-
-         inline void set_ibom(inv_binary_op_map_t& inv_binary_op_map)
-         {
-            inv_binary_op_map_ = &inv_binary_op_map;
-         }
-
-         inline void set_sf3m(sf3_map_t& sf3_map)
-         {
-            sf3_map_ = &sf3_map;
-         }
-
-         inline void set_sf4m(sf4_map_t& sf4_map)
-         {
-            sf4_map_ = &sf4_map;
-         }
-
-         inline void set_allocator(details::node_allocator& na)
-         {
-            node_allocator_ = &na;
-         }
-
-         inline void set_strength_reduction_state(const bool enabled)
-         {
-            strength_reduction_enabled_ = enabled;
-         }
-
-         inline bool strength_reduction_enabled() const
-         {
-            return strength_reduction_enabled_;
-         }
-
-         inline bool valid_operator(const details::operator_type& operation, binary_functor_t& bop)
-         {
-            typename binary_op_map_t::iterator bop_itr = binary_op_map_->find(operation);
-
-            if ((*binary_op_map_).end() == bop_itr)
-               return false;
-
-            bop = bop_itr->second;
-
-            return true;
-         }
-
-         inline bool valid_operator(const details::operator_type& operation, unary_functor_t& uop)
-         {
-            typename unary_op_map_t::iterator uop_itr = unary_op_map_->find(operation);
-
-            if ((*unary_op_map_).end() == uop_itr)
-               return false;
-
-            uop = uop_itr->second;
-
-            return true;
-         }
-
-         inline details::operator_type get_operator(const binary_functor_t& bop)
-         {
-            return (*inv_binary_op_map_).find(bop)->second;
-         }
-
-         inline expression_node_ptr operator()(const Type& v) const
-         {
-            return node_allocator_->allocate<literal_node_t>(v);
-         }
-
-         inline expression_node_ptr operator()(const std::string& s) const
-         {
-            return node_allocator_->allocate<string_literal_node_t>(s);
-         }
-
-         inline expression_node_ptr operator()(std::string& s, range_t& rp) const
-         {
-            return node_allocator_->allocate_rr<string_range_node_t>(s,rp);
-         }
-
-         inline expression_node_ptr operator()(const std::string& s, range_t& rp) const
-         {
-            return node_allocator_->allocate_tt<const_string_range_node_t>(s,rp);
-         }
-
-         inline expression_node_ptr operator()(expression_node_ptr branch, range_t& rp) const
-         {
-            if (is_generally_string_node(branch))
-               return node_allocator_->allocate_tt<generic_string_range_node_t>(branch,rp);
-            else
-               return error_node();
-         }
-
-         inline bool unary_optimizable(const details::operator_type& operation) const
-         {
-            return (details::e_abs   == operation) || (details::e_acos  == operation) ||
-                   (details::e_acosh == operation) || (details::e_asin  == operation) ||
-                   (details::e_asinh == operation) || (details::e_atan  == operation) ||
-                   (details::e_atanh == operation) || (details::e_ceil  == operation) ||
-                   (details::e_cos   == operation) || (details::e_cosh  == operation) ||
-                   (details::e_exp   == operation) || (details::e_expm1 == operation) ||
-                   (details::e_floor == operation) || (details::e_log   == operation) ||
-                   (details::e_log10 == operation) || (details::e_log2  == operation) ||
-                   (details::e_log1p == operation) || (details::e_neg   == operation) ||
-                   (details::e_pos   == operation) || (details::e_round == operation) ||
-                   (details::e_sin   == operation) || (details::e_sinc  == operation) ||
-                   (details::e_sinh  == operation) || (details::e_sqrt  == operation) ||
-                   (details::e_tan   == operation) || (details::e_tanh  == operation) ||
-                   (details::e_cot   == operation) || (details::e_sec   == operation) ||
-                   (details::e_csc   == operation) || (details::e_r2d   == operation) ||
-                   (details::e_d2r   == operation) || (details::e_d2g   == operation) ||
-                   (details::e_g2d   == operation) || (details::e_notl  == operation) ||
-                   (details::e_sgn   == operation) || (details::e_erf   == operation) ||
-                   (details::e_erfc  == operation) || (details::e_ncdf  == operation) ||
-                   (details::e_frac  == operation) || (details::e_trunc == operation);
-         }
-
-         inline bool sf3_optimizable(const std::string& sf3id, trinary_functor_t& tfunc)
-         {
-            typename sf3_map_t::iterator itr = sf3_map_->find(sf3id);
-
-            if (sf3_map_->end() == itr)
-               return false;
-            else
-               tfunc = itr->second.first;
-
-            return true;
-         }
-
-         inline bool sf4_optimizable(const std::string& sf4id, quaternary_functor_t& qfunc)
-         {
-            typename sf4_map_t::iterator itr = sf4_map_->find(sf4id);
-
-            if (sf4_map_->end() == itr)
-               return false;
-            else
-               qfunc = itr->second.first;
-
-            return true;
-         }
-
-         inline bool sf3_optimizable(const std::string& sf3id, details::operator_type& operation)
-         {
-            typename sf3_map_t::iterator itr = sf3_map_->find(sf3id);
-
-            if (sf3_map_->end() == itr)
-               return false;
-            else
-               operation = itr->second.second;
-
-            return true;
-         }
-
-         inline bool sf4_optimizable(const std::string& sf4id, details::operator_type& operation)
-         {
-            typename sf4_map_t::iterator itr = sf4_map_->find(sf4id);
-
-            if (sf4_map_->end() == itr)
-               return false;
-            else
-               operation = itr->second.second;
-
-            return true;
-         }
-
-         inline expression_node_ptr operator()(const details::operator_type& operation, expression_node_ptr (&branch)[1])
-         {
-            if (0 == branch[0])
-               return error_node();
-            else if (details::is_null_node(branch[0]))
-               return branch[0];
-            else if (details::is_break_node(branch[0]))
-               return error_node();
-            else if (details::is_continue_node(branch[0]))
-               return error_node();
-            else if (details::is_constant_node(branch[0]))
-               return synthesize_expression<unary_node_t,1>(operation,branch);
-            else if (unary_optimizable(operation) && details::is_variable_node(branch[0]))
-               return synthesize_uv_expression(operation,branch);
-            else if (unary_optimizable(operation) && details::is_ivector_node(branch[0]))
-               return synthesize_uvec_expression(operation,branch);
-            else
-               return synthesize_unary_expression(operation,branch);
-         }
-
-         inline bool is_assignment_operation(const details::operator_type& operation) const
-         {
-            return (details::e_addass == operation) ||
-                   (details::e_subass == operation) ||
-                   (details::e_mulass == operation) ||
-                   (details::e_divass == operation) ||
-                   (details::e_modass == operation) ;
-         }
-
-         #ifndef exprtk_disable_string_capabilities
-         inline bool valid_string_operation(const details::operator_type& operation) const
-         {
-            return (details::e_add    == 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_in     == operation) ||
-                   (details::e_like   == operation) ||
-                   (details::e_ilike  == operation) ||
-                   (details::e_assign == operation) ||
-                   (details::e_addass == operation) ||
-                   (details::e_swap   == operation) ;
-         }
-         #else
-         inline bool valid_string_operation(const details::operator_type&) const
-         {
-            return false;
-         }
-         #endif
-
-         inline std::string to_str(const details::operator_type& operation) const
-         {
-            switch (operation)
-            {
-               case details::e_add  : return "+";
-               case details::e_sub  : return "-";
-               case details::e_mul  : return "*";
-               case details::e_div  : return "/";
-               case details::e_mod  : return "%";
-               case details::e_pow  : return "^";
-               case details::e_lt   : return "<";
-               case details::e_lte  : return "<=";
-               case details::e_gt   : return ">";
-               case details::e_gte  : return ">=";
-               case details::e_eq   : return "==";
-               case details::e_ne   : return "!=";
-               case details::e_and  : return "and";
-               case details::e_nand : return "nand";
-               case details::e_or   : return "or";
-               case details::e_nor  : return "nor";
-               case details::e_xor  : return "xor";
-               case details::e_xnor : return "xnor";
-               default              : return "UNKNOWN";
-            }
-         }
-
-         inline bool operation_optimizable(const details::operator_type& operation) const
-         {
-            return (details::e_add  == operation) ||
-                   (details::e_sub  == operation) ||
-                   (details::e_mul  == operation) ||
-                   (details::e_div  == operation) ||
-                   (details::e_mod  == operation) ||
-                   (details::e_pow  == 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_and  == operation) ||
-                   (details::e_nand == operation) ||
-                   (details::e_or   == operation) ||
-                   (details::e_nor  == operation) ||
-                   (details::e_xor  == operation) ||
-                   (details::e_xnor == operation) ;
-         }
-
-         inline std::string branch_to_id(expression_node_ptr branch)
-         {
-            static const std::string null_str   ("(null)" );
-            static const std::string const_str  ("(c)"    );
-            static const std::string var_str    ("(v)"    );
-            static const std::string vov_str    ("(vov)"  );
-            static const std::string cov_str    ("(cov)"  );
-            static const std::string voc_str    ("(voc)"  );
-            static const std::string str_str    ("(s)"    );
-            static const std::string strrng_str ("(rngs)" );
-            static const std::string cs_str     ("(cs)"   );
-            static const std::string cstrrng_str("(crngs)");
-
-            if (details::is_null_node(branch))
-               return null_str;
-            else if (details::is_constant_node(branch))
-               return const_str;
-            else if (details::is_variable_node(branch))
-               return var_str;
-            else if (details::is_vov_node(branch))
-               return vov_str;
-            else if (details::is_cov_node(branch))
-               return cov_str;
-            else if (details::is_voc_node(branch))
-               return voc_str;
-            else if (details::is_string_node(branch))
-               return str_str;
-            else if (details::is_const_string_node(branch))
-               return cs_str;
-            else if (details::is_string_range_node(branch))
-               return strrng_str;
-            else if (details::is_const_string_range_node(branch))
-               return cstrrng_str;
-            else if (details::is_t0ot1ot2_node(branch))
-               return "(" + dynamic_cast<details::T0oT1oT2_base_node<T>*>(branch)->type_id() + ")";
-            else if (details::is_t0ot1ot2ot3_node(branch))
-               return "(" + dynamic_cast<details::T0oT1oT2oT3_base_node<T>*>(branch)->type_id() + ")";
-            else
-               return "ERROR";
-         }
-
-         inline std::string branch_to_id(expression_node_ptr (&branch)[2])
-         {
-            return branch_to_id(branch[0]) + std::string("o") + branch_to_id(branch[1]);
-         }
-
-         inline bool cov_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
-         {
-            if (!operation_optimizable(operation))
-               return false;
-            else
-               return (details::is_constant_node(branch[0]) && details::is_variable_node(branch[1]));
-         }
-
-         inline bool voc_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
-         {
-            if (!operation_optimizable(operation))
-               return false;
-            else
-               return (details::is_variable_node(branch[0]) && details::is_constant_node(branch[1]));
-         }
-
-         inline bool vov_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
-         {
-            if (!operation_optimizable(operation))
-               return false;
-            else
-               return (details::is_variable_node(branch[0]) && details::is_variable_node(branch[1]));
-         }
-
-         inline bool cob_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
-         {
-            if (!operation_optimizable(operation))
-               return false;
-            else
-               return (details::is_constant_node(branch[0]) && !details::is_constant_node(branch[1]));
-         }
-
-         inline bool boc_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
-         {
-            if (!operation_optimizable(operation))
-               return false;
-            else
-               return (!details::is_constant_node(branch[0]) && details::is_constant_node(branch[1]));
-         }
-
-         inline bool cocob_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
-         {
-            if (
-                 (details::e_add == operation) ||
-                 (details::e_sub == operation) ||
-                 (details::e_mul == operation) ||
-                 (details::e_div == operation)
-               )
+        }
+        
+        inline expression_node_ptr parse_ternary_conditional_statement(expression_node_ptr condition)
+        {
+            // Parse: [condition][?][consequent][:][alternative]
+            expression_node_ptr consequent  = error_node();
+            expression_node_ptr alternative = error_node();
+            
+            bool result = true;
+            
+            if (0 == condition)
             {
-               return (details::is_constant_node(branch[0]) && details::is_cob_node(branch[1])) ||
-                      (details::is_constant_node(branch[1]) && details::is_cob_node(branch[0]));
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR043 - Encountered invalid condition branch for ternary if-statement"));
+                
+                return error_node();
             }
-            else
-               return false;
-         }
-
-         inline bool coboc_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
-         {
-            if (
-                 (details::e_add == operation) ||
-                 (details::e_sub == operation) ||
-                 (details::e_mul == operation) ||
-                 (details::e_div == operation)
-               )
+            else if (!token_is(token_t::e_ternary))
             {
-               return (details::is_constant_node(branch[0]) && details::is_boc_node(branch[1])) ||
-                      (details::is_constant_node(branch[1]) && details::is_boc_node(branch[0]));
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR044 - Expected '?' after condition of ternary if-statement"));
+                
+                result = false;
             }
-            else
-               return false;
-         }
-
-         inline bool uvouv_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
-         {
-            if (!operation_optimizable(operation))
-               return false;
-            else
-               return (details::is_uv_node(branch[0]) && details::is_uv_node(branch[1]));
-         }
-
-         inline bool vob_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
-         {
-            if (!operation_optimizable(operation))
-               return false;
-            else
-               return (details::is_variable_node(branch[0]) && !details::is_variable_node(branch[1]));
-         }
-
-         inline bool bov_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
-         {
-            if (!operation_optimizable(operation))
-               return false;
-            else
-               return (!details::is_variable_node(branch[0]) && details::is_variable_node(branch[1]));
-         }
-
-         inline bool binext_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
-         {
-            if (!operation_optimizable(operation))
-               return false;
-            else
-               return (!details::is_constant_node(branch[0]) || !details::is_constant_node(branch[1]));
-         }
-
-         inline bool is_invalid_assignment_op(const details::operator_type& operation, expression_node_ptr (&branch)[2])
-         {
-            if (is_assignment_operation(operation))
+            else if (0 == (consequent = parse_expression()))
             {
-               const bool b1_is_genstring = details::is_generally_string_node(branch[1]);
-
-               if (details::is_string_node(branch[0]))
-                  return !b1_is_genstring;
-               else
-                  return (
-                           !details::is_variable_node   (branch[0]) &&
-                           !details::is_vector_elem_node(branch[0]) &&
-                           !details::is_vector_node     (branch[0])
-                         )
-                         || b1_is_genstring;
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR045 - Failed to parse consequent for ternary if-statement"));
+                
+                result = false;
             }
-            else
-               return false;
-         }
-
-         inline bool is_invalid_break_continue_op(expression_node_ptr (&branch)[2])
-         {
-            return (
-                     details::is_break_node   (branch[0]) ||
-                     details::is_break_node   (branch[1]) ||
-                     details::is_continue_node(branch[0]) ||
-                     details::is_continue_node(branch[1])
-                   );
-         }
-
-         inline bool is_invalid_string_op(const details::operator_type& operation, expression_node_ptr (&branch)[2])
-         {
-            const bool b0_string = is_generally_string_node(branch[0]);
-            const bool b1_string = is_generally_string_node(branch[1]);
-
-            bool result = false;
-
-            if (b0_string ^ b1_string)
-               result = true;
-            else if (!valid_string_operation(operation) && b0_string && b1_string)
-               result = true;
-
-            if (result)
+            else if (!token_is(token_t::e_colon))
             {
-               parser_->set_synthesis_error("Invalid string operation");
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR046 - Expected ':' between ternary if-statement consequent and alternative"));
+                
+                result = false;
             }
-
-            return result;
-         }
-
-         inline bool is_invalid_string_op(const details::operator_type& operation, expression_node_ptr (&branch)[3])
-         {
-            const bool b0_string = is_generally_string_node(branch[0]);
-            const bool b1_string = is_generally_string_node(branch[1]);
-            const bool b2_string = is_generally_string_node(branch[2]);
-
-            bool result = false;
-
-            if ((b0_string ^ b1_string) || (b1_string ^ b2_string))
-               result = true;
-            else if ((details::e_inrange != operation) && b0_string && b1_string && b2_string)
-               result = true;
-
-            if (result)
+            else if (0 == (alternative = parse_expression()))
             {
-               parser_->set_synthesis_error("Invalid string operation");
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR047 - Failed to parse alternative for ternary if-statement"));
+                
+                result = false;
             }
-
-            return result;
-         }
-
-         inline bool is_string_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2])
-         {
-            const bool b0_string = is_generally_string_node(branch[0]);
-            const bool b1_string = is_generally_string_node(branch[1]);
-
-            return (b0_string && b1_string && valid_string_operation(operation));
-         }
-
-         inline bool is_string_operation(const details::operator_type& operation, expression_node_ptr (&branch)[3])
-         {
-            const bool b0_string = is_generally_string_node(branch[0]);
-            const bool b1_string = is_generally_string_node(branch[1]);
-            const bool b2_string = is_generally_string_node(branch[2]);
-
-            return (b0_string && b1_string && b2_string && (details::e_inrange == operation));
-         }
-
-         #ifndef exprtk_disable_sc_andor
-         inline bool is_shortcircuit_expression(const details::operator_type& operation)
-         {
-            return (
-                     (details::e_scand == operation) ||
-                     (details::e_scor  == operation)
-                   );
-         }
-         #else
-         inline bool is_shortcircuit_expression(const details::operator_type&)
-         {
-            return false;
-         }
-         #endif
-
-         inline bool is_null_present(expression_node_ptr (&branch)[2])
-         {
-            return (
-                     details::is_null_node(branch[0]) ||
-                     details::is_null_node(branch[1])
-                   );
-         }
-
-         inline bool is_vector_eqineq_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2])
-         {
-            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)
-                      );
-         }
-
-         inline bool is_vector_arithmetic_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2])
-         {
-            if (!is_ivector_node(branch[0]) && !is_ivector_node(branch[1]))
-               return false;
-            else
-               return (
-                        (details::e_add == operation) ||
-                        (details::e_sub == operation) ||
-                        (details::e_mul == operation) ||
-                        (details::e_div == operation) ||
-                        (details::e_pow == operation)
-                      );
-         }
-
-         inline expression_node_ptr operator()(const details::operator_type& operation, expression_node_ptr (&branch)[2])
-         {
-            if ((0 == branch[0]) || (0 == branch[1]))
-               return error_node();
-            else if (is_invalid_string_op(operation,branch))
-               return error_node();
-            else if (is_invalid_assignment_op(operation,branch))
-               return error_node();
-            else if (is_invalid_break_continue_op(branch))
-               return error_node();
-            else if (details::e_assign == operation)
-               return synthesize_assignment_expression(operation,branch);
-            else if (details::e_swap == operation)
-               return synthesize_swap_expression(branch);
-            else if (is_assignment_operation(operation))
-               return synthesize_assignment_operation_expression(operation,branch);
-            else if (is_vector_eqineq_operation(operation,branch))
-               return synthesize_veceqineq_operation_expression(operation,branch);
-            else if (is_vector_arithmetic_operation(operation,branch))
-               return synthesize_vecarithmetic_operation_expression(operation,branch);
-            else if (is_shortcircuit_expression(operation))
-               return synthesize_shortcircuit_expression(operation,branch);
-            else if (is_string_operation(operation,branch))
-               return synthesize_string_expression(operation,branch);
-            else if (is_null_present(branch))
-               return synthesize_null_expression(operation,branch);
-
-            expression_node_ptr result = error_node();
-
-            #ifndef exprtk_disable_enhanced_features
-            if (synthesize_expression(operation,branch,result))
-               return result;
-            else
-            #endif
-
+            
+#ifndef exprtk_disable_string_capabilities
+            if (result)
             {
-               /*
-                  Possible reductions:
-                  1. c o cob -> cob
-                  2. cob o c -> cob
-                  3. c o boc -> boc
-                  4. boc o c -> boc
-               */
-               result = error_node();
-
-               if (cocob_optimizable(operation,branch))
-                  result = synthesize_cocob_expression::process(*this,operation,branch);
-               else if (coboc_optimizable(operation,branch) && (0 == result))
-                  result = synthesize_coboc_expression::process(*this,operation,branch);
-
-               if (result)
-                  return result;
+                const bool consq_is_str = is_generally_string_node( consequent);
+                const bool alter_is_str = is_generally_string_node(alternative);
+                
+                if (consq_is_str || alter_is_str)
+                {
+                    if (consq_is_str && alter_is_str)
+                    {
+                        return expression_generator_
+                        .conditional_string(condition,consequent,alternative);
+                    }
+                    
+                    set_error(
+                              make_error(parser_error::e_syntax,
+                                         current_token(),
+                                         "ERR048 - Return types of ternary if-statement differ"));
+                    
+                    result = false;
+                }
             }
-
-            if (uvouv_optimizable(operation,branch))
-               return synthesize_uvouv_expression(operation,branch);
-            else if (vob_optimizable(operation,branch))
-               return synthesize_vob_expression::process(*this,operation,branch);
-            else if (bov_optimizable(operation,branch))
-               return synthesize_bov_expression::process(*this,operation,branch);
-            else if (cob_optimizable(operation,branch))
-               return synthesize_cob_expression::process(*this,operation,branch);
-            else if (boc_optimizable(operation,branch))
-               return synthesize_boc_expression::process(*this,operation,branch);
-            #ifndef exprtk_disable_enhanced_features
-            else if (cov_optimizable(operation,branch))
-               return synthesize_cov_expression::process(*this,operation,branch);
-            #endif
-            else if (binext_optimizable(operation,branch))
-               return synthesize_binary_ext_expression::process(*this,operation,branch);
-            else
-               return synthesize_expression<binary_node_t,2>(operation,branch);
-         }
-
-         inline expression_node_ptr operator()(const details::operator_type& operation, expression_node_ptr (&branch)[3])
-         {
-            if (
-                 (0 == branch[0]) ||
-                 (0 == branch[1]) ||
-                 (0 == branch[2])
-               )
+#endif
+            
+            if (!result)
             {
-               details::free_all_nodes(*node_allocator_,branch);
-
-               return error_node();
+                free_node(node_allocator_,  condition);
+                free_node(node_allocator_, consequent);
+                free_node(node_allocator_,alternative);
+                
+                return error_node();
             }
-            else if (is_invalid_string_op(operation,branch))
-               return error_node();
-            else if (is_string_operation(operation,branch))
-               return synthesize_string_expression(operation,branch);
-            else
-               return synthesize_expression<trinary_node_t,3>(operation,branch);
-         }
-
-         inline expression_node_ptr operator()(const details::operator_type& operation, expression_node_ptr (&branch)[4])
-         {
-            return synthesize_expression<quaternary_node_t,4>(operation,branch);
-         }
-
-         inline expression_node_ptr operator()(const details::operator_type& operation, expression_node_ptr (&branch)[5])
-         {
-            return synthesize_expression<quinary_node_t,5>(operation,branch);
-         }
-
-         inline expression_node_ptr operator()(const details::operator_type& operation, expression_node_ptr (&branch)[6])
-         {
-            return synthesize_expression<senary_node_t,6>(operation,branch);
-         }
-
-         inline expression_node_ptr operator()(const details::operator_type& operation, expression_node_ptr b0)
-         {
-            expression_node_ptr branch[1] = { b0 };
-            return (*this)(operation,branch);
-         }
-
-         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
+                return expression_generator_
+                .conditional(condition,consequent,alternative);
+        }
+        
+        inline expression_node_ptr parse_while_loop()
+        {
+            // Parse: [while][(][test expr][)][{][expression][}]
+            expression_node_ptr condition   = error_node();
+            expression_node_ptr branch      = error_node();
+            expression_node_ptr result_node = error_node();
+            
+            bool result = true;
+            
+            next_token();
+            
+            if (!token_is(token_t::e_lbracket))
             {
-               expression_node_ptr branch[2] = { b0, b1 };
-               return expression_generator<Type>::operator()(operation,branch);
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR049 - Expected '(' at start of while-loop condition statement"));
+                
+                return error_node();
             }
-         }
-
-         inline expression_node_ptr conditional(expression_node_ptr condition,
-                                                expression_node_ptr consequent,
-                                                expression_node_ptr alternative) const
-         {
-            if ((0 == condition) || (0 == consequent))
-            {
-               free_node(*node_allocator_,condition  );
-               free_node(*node_allocator_,consequent );
-               free_node(*node_allocator_,alternative);
-
-               return error_node();
+            else if (0 == (condition = parse_expression()))
+            {
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR050 - Failed to parse condition for while-loop"));
+                
+                return error_node();
             }
-            // Can the condition be immediately evaluated? if so optimize.
-            else if (details::is_constant_node(condition))
+            else if (!token_is(token_t::e_rbracket))
             {
-               // True branch
-               if (details::is_true(condition))
-               {
-                  free_node(*node_allocator_,condition  );
-                  free_node(*node_allocator_,alternative);
-
-                  return consequent;
-               }
-               // False branch
-               else
-               {
-                  free_node(*node_allocator_,condition);
-                  free_node(*node_allocator_,consequent);
-
-                  if (alternative)
-                     return alternative;
-                  else
-                     return node_allocator_->allocate<details::null_node<T> >();
-               }
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR051 - Expected ')' at end of while-loop condition statement"));
+                result = false;
             }
-            else if ((0 != consequent) && (0 != alternative))
+            
+            brkcnt_list_.push_front(false);
+            
+            if (result)
             {
-               return node_allocator_->allocate<conditional_node_t>(condition,consequent,alternative);
+                if (0 == (branch = parse_multi_sequence("while-loop")))
+                {
+                    set_error(
+                              make_error(parser_error::e_syntax,
+                                         current_token(),
+                                         "ERR052 - Failed to parse body of while-loop"));
+                    result = false;
+                }
+                else if (0 == (result_node = expression_generator_.while_loop(condition,
+                                                                              branch,
+                                                                              brkcnt_list_.front())))
+                {
+                    set_error(
+                              make_error(parser_error::e_syntax,
+                                         current_token(),
+                                         "ERR053 - Failed to synthesize while-loop"));
+                    result = false;
+                }
+            }
+            
+            if (!result)
+            {
+                free_node(node_allocator_,     branch);
+                free_node(node_allocator_,  condition);
+                free_node(node_allocator_,result_node);
+                
+                brkcnt_list_.pop_front();
+                
+                return error_node();
             }
             else
-               return node_allocator_->allocate<cons_conditional_node_t>(condition,consequent);
-         }
-
-         inline expression_node_ptr while_loop(expression_node_ptr& condition,
-                                               expression_node_ptr& branch,
-                                               const bool brkcont = false) const
-         {
-            if (!brkcont && details::is_constant_node(condition))
-            {
-               expression_node_ptr result = error_node();
-               if (details::is_true(condition))
-                  // Infinite loops are not allowed.
-                  result = error_node();
-               else
-                  result = node_allocator_->allocate<details::null_node<Type> >();
-
-               free_node(*node_allocator_, condition);
-               free_node(*node_allocator_, branch   );
-
-               return result;
-            }
-            else if (details::is_null_node(condition))
+                return result_node;
+        }
+        
+        inline expression_node_ptr parse_repeat_until_loop()
+        {
+            // Parse: [repeat][{][expression][}][until][(][test expr][)]
+            expression_node_ptr condition = error_node();
+            expression_node_ptr branch    = error_node();
+            next_token();
+            
+            std::vector<expression_node_ptr> arg_list;
+            std::vector<bool> side_effect_list;
+            
+            scoped_vec_delete<expression_node_t> sdd(*this,arg_list);
+            
+            brkcnt_list_.push_front(false);
+            
+            if (details::imatch(current_token().value,"until"))
             {
-               free_node(*node_allocator_,condition);
-
-               return branch;
+                next_token();
+                branch = node_allocator_.allocate<details::null_node<T> >();
             }
-            else if (!brkcont)
-               return node_allocator_->allocate<while_loop_node_t>(condition,branch);
-            #ifndef exprtk_disable_break_continue
             else
-               return node_allocator_->allocate<while_loop_bc_node_t>(condition,branch);
-            #else
-               return error_node();
-            #endif
-         }
-
-         inline expression_node_ptr repeat_until_loop(expression_node_ptr& condition,
-                                                      expression_node_ptr& branch,
-                                                      const bool brkcont = false) const
-         {
-            if (!brkcont && details::is_constant_node(condition))
-            {
-               if (details::is_true(condition) && details::is_constant_node(branch))
-               {
-                  free_node(*node_allocator_,condition);
-
-                  return branch;
-               }
-
-               free_node(*node_allocator_, condition);
-               free_node(*node_allocator_, branch   );
-
-               return error_node();
+            {
+                token_t::token_type seperator = token_t::e_eof;
+                
+                scope_handler sh(*this);
+                
+                scoped_bool_or_restorer sbr(state_.side_effect_present);
+                
+                for ( ; ; )
+                {
+                    state_.side_effect_present = false;
+                    
+                    expression_node_ptr arg = parse_expression();
+                    
+                    if (0 == arg)
+                        return error_node();
+                    else
+                    {
+                        arg_list.push_back(arg);
+                        side_effect_list.push_back(state_.side_effect_present);
+                    }
+                    
+                    if (details::imatch(current_token().value,"until"))
+                    {
+                        next_token();
+                        break;
+                    }
+                    
+                    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(),
+                                             "ERR054 - Expected '" + token_t::to_str(seperator) + "' in body of repeat until loop"));
+                        
+                        return error_node();
+                    }
+                    
+                    if (details::imatch(current_token().value,"until"))
+                    {
+                        next_token();
+                        break;
+                    }
+                }
+                
+                branch = simplify(arg_list,side_effect_list);
+                
+                sdd.delete_ptr = (0 == branch);
+                
+                if (sdd.delete_ptr)
+                {
+                    brkcnt_list_.pop_front();
+                    
+                    set_error(
+                              make_error(parser_error::e_syntax,
+                                         current_token(),
+                                         "ERR055 - Failed to parse body of repeat until loop"));
+                    
+                    return error_node();
+                }
+            }
+            
+            if (!token_is(token_t::e_lbracket))
+            {
+                brkcnt_list_.pop_front();
+                
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR056 - Expected '(' before condition statement of repeat until loop"));
+                
+                free_node(node_allocator_,branch);
+                
+                return error_node();
+            }
+            else if (0 == (condition = parse_expression()))
+            {
+                brkcnt_list_.pop_front();
+                
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR057 - Failed to parse condition for repeat until loop"));
+                
+                free_node(node_allocator_,branch);
+                
+                return error_node();
             }
-            else if (details::is_null_node(condition))
+            else if (!token_is(token_t::e_rbracket))
             {
-               free_node(*node_allocator_,condition);
-
-               return branch;
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR058 - Expected ')' after condition of repeat until loop"));
+                
+                free_node(node_allocator_,    branch);
+                free_node(node_allocator_, condition);
+                
+                brkcnt_list_.pop_front();
+                
+                return error_node();
+            }
+            
+            expression_node_ptr result;
+            
+            result = expression_generator_
+            .repeat_until_loop(condition,branch,brkcnt_list_.front());
+            
+            if (0 == result)
+            {
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR059 - Failed to synthesize repeat until loop"));
+                
+                free_node(node_allocator_, condition);
+                brkcnt_list_.pop_front();
+                
+                return error_node();
             }
-            else if (!brkcont)
-               return node_allocator_->allocate<repeat_until_loop_node_t>(condition,branch);
-            #ifndef exprtk_disable_break_continue
             else
-               return node_allocator_->allocate<repeat_until_loop_bc_node_t>(condition,branch);
-            #else
-               return error_node();
-            #endif
-         }
-
-         inline expression_node_ptr for_loop(expression_node_ptr& initialiser,
-                                             expression_node_ptr& condition,
-                                             expression_node_ptr& incrementor,
-                                             expression_node_ptr& loop_body,
-                                             bool brkcont = false) const
-         {
-            if (!brkcont && details::is_constant_node(condition))
-            {
-               expression_node_ptr result = error_node();
-
-               if (details::is_true(condition))
-                  // Infinite loops are not allowed.
-                  result = error_node();
-               else
-                  result = node_allocator_->allocate<details::null_node<Type> >();
-
-               free_node(*node_allocator_,initialiser);
-               free_node(*node_allocator_,condition  );
-               free_node(*node_allocator_,incrementor);
-               free_node(*node_allocator_,loop_body  );
-
-               return result;
+            {
+                brkcnt_list_.pop_front();
+                return result;
+            }
+        }
+        
+        inline expression_node_ptr parse_for_loop()
+        {
+            expression_node_ptr initialiser = error_node();
+            expression_node_ptr condition   = error_node();
+            expression_node_ptr incrementor = error_node();
+            expression_node_ptr loop_body   = error_node();
+            
+            scope_element* se = 0;
+            bool result       = true;
+            std::string loop_counter_symbol;
+            
+            next_token();
+            
+            scope_handler sh(*this);
+            
+            if (!token_is(token_t::e_lbracket))
+            {
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR060 - Expected '(' at start of for-loop"));
+                
+                return error_node();
             }
-            else if (details::is_null_node(condition))
+            
+            if (!token_is(token_t::e_eof))
             {
-               free_node(*node_allocator_,initialiser);
-               free_node(*node_allocator_,condition  );
-               free_node(*node_allocator_,incrementor);
-
-               return loop_body;
-            }
-            else if (!brkcont)
-               return node_allocator_->allocate<for_loop_node_t>(initialiser,
-                                                                 condition,
-                                                                 incrementor,
-                                                                 loop_body);
-            #ifndef exprtk_disable_break_continue
+                if (
+                    !token_is(token_t::e_symbol,prsrhlpr_t::e_hold) &&
+                    details::imatch(current_token().value,"var")
+                    )
+                {
+                    next_token();
+                    
+                    if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold))
+                    {
+                        set_error(
+                                  make_error(parser_error::e_syntax,
+                                             current_token(),
+                                             "ERR061 - Expected a variable at the start of initialiser section of for-loop"));
+                        
+                        return error_node();
+                    }
+                    else if (!peek_token_is(token_t::e_assign))
+                    {
+                        set_error(
+                                  make_error(parser_error::e_syntax,
+                                             current_token(),
+                                             "ERR062 - Expected variable assignment of initialiser section of for-loop"));
+                        
+                        return error_node();
+                    }
+                    
+                    loop_counter_symbol = current_token().value;
+                    
+                    se = &sem_.get_element(loop_counter_symbol);
+                    
+                    if ((se->name == loop_counter_symbol) && se->active)
+                    {
+                        set_error(
+                                  make_error(parser_error::e_syntax,
+                                             current_token(),
+                                             "ERR063 - For-loop variable '" + loop_counter_symbol+ "' is being shadowed by a previous declaration"));
+                        
+                        return error_node();
+                    }
+                    else if (!symtab_store_.is_variable(loop_counter_symbol))
+                    {
+                        if (
+                            !se->active &&
+                            (se->name == loop_counter_symbol) &&
+                            (se->type ==  scope_element::e_variable)
+                            )
+                        {
+                            se->active = true;
+                            se->ref_count++;
+                        }
+                        else
+                        {
+                            scope_element nse;
+                            nse.name      = loop_counter_symbol;
+                            nse.active    = true;
+                            nse.ref_count = 1;
+                            nse.type      = scope_element::e_variable;
+                            nse.depth     = state_.scope_depth;
+                            nse.data      = new T(T(0));
+                            nse.var_node  = node_allocator_.allocate<variable_node_t>(*(T*)(nse.data));
+                            
+                            if (!sem_.add_element(nse))
+                            {
+                                set_error(
+                                          make_error(parser_error::e_syntax,
+                                                     current_token(),
+                                                     "ERR064 - Failed to add new local variable '" + loop_counter_symbol + "' to SEM"));
+                                
+                                sem_.free_element(nse);
+                                
+                                result = false;
+                            }
+                            else
+                            {
+                                exprtk_debug(("parse_for_loop() - INFO - Added new local variable: %s\n",nse.name.c_str()));
+                                
+                                state_.activate_side_effect("parse_for_loop()");
+                            }
+                        }
+                    }
+                }
+                
+                if (0 == (initialiser = parse_expression()))
+                {
+                    set_error(
+                              make_error(parser_error::e_syntax,
+                                         current_token(),
+                                         "ERR065 - Failed to parse initialiser of for-loop"));
+                    result = false;
+                }
+                else if (!token_is(token_t::e_eof))
+                {
+                    set_error(
+                              make_error(parser_error::e_syntax,
+                                         current_token(),
+                                         "ERR066 - Expected ';' after initialiser of for-loop"));
+                    result = false;
+                }
+            }
+            
+            if (!token_is(token_t::e_eof))
+            {
+                if (0 == (condition = parse_expression()))
+                {
+                    set_error(
+                              make_error(parser_error::e_syntax,
+                                         current_token(),
+                                         "ERR067 - Failed to parse condition of for-loop"));
+                    result = false;
+                }
+                else if (!token_is(token_t::e_eof))
+                {
+                    set_error(
+                              make_error(parser_error::e_syntax,
+                                         current_token(),
+                                         "ERR068 - Expected ';' after condition section of for-loop"));
+                    result = false;
+                }
+            }
+            
+            if (!token_is(token_t::e_rbracket))
+            {
+                if (0 == (incrementor = parse_expression()))
+                {
+                    set_error(
+                              make_error(parser_error::e_syntax,
+                                         current_token(),
+                                         "ERR069 - Failed to parse incrementor of for-loop"));
+                    result = false;
+                }
+                else if (!token_is(token_t::e_rbracket))
+                {
+                    set_error(
+                              make_error(parser_error::e_syntax,
+                                         current_token(),
+                                         "ERR070 - Expected ')' after incrementor section of for-loop"));
+                    result = false;
+                }
+            }
+            
+            if (result)
+            {
+                brkcnt_list_.push_front(false);
+                
+                if (0 == (loop_body = parse_multi_sequence("for-loop")))
+                {
+                    set_error(
+                              make_error(parser_error::e_syntax,
+                                         current_token(),
+                                         "ERR071 - Failed to parse body of for-loop"));
+                    result = false;
+                }
+            }
+            
+            if (!result)
+            {
+                if (se)
+                {
+                    se->ref_count--;
+                }
+                
+                sem_.cleanup();
+                
+                free_node(node_allocator_,initialiser);
+                free_node(node_allocator_,  condition);
+                free_node(node_allocator_,incrementor);
+                free_node(node_allocator_,  loop_body);
+                
+                if (!brkcnt_list_.empty())
+                {
+                    brkcnt_list_.pop_front();
+                }
+                
+                return error_node();
+            }
             else
-               return node_allocator_->allocate<for_loop_bc_node_t>(initialiser,
-                                                                    condition,
-                                                                    incrementor,
-                                                                    loop_body);
-            #else
-            return error_node();
-            #endif
-         }
-
-         template <typename Allocator,
-                   template <typename,typename> class Sequence>
-         inline expression_node_ptr const_optimize_switch(Sequence<expression_node_ptr,Allocator>& arg_list)
-         {
+            {
+                expression_node_ptr result_node =
+                expression_generator_.for_loop(initialiser,
+                                               condition,
+                                               incrementor,
+                                               loop_body,
+                                               brkcnt_list_.front());
+                brkcnt_list_.pop_front();
+                
+                return result_node;
+            }
+        }
+        
+        inline expression_node_ptr parse_switch_statement()
+        {
+            std::vector<expression_node_ptr> arg_list;
             expression_node_ptr result = error_node();
-
-            for (std::size_t i = 0; i < (arg_list.size() / 2); ++i)
+            
+            if (!details::imatch(current_token().value,"switch"))
             {
-               expression_node_ptr condition  = arg_list[(2 * i)    ];
-               expression_node_ptr consequent = arg_list[(2 * i) + 1];
-
-               if ((0 == result) && details::is_true(condition))
-               {
-                  result = consequent;
-                  break;
-               }
-            }
-
-            if (0 == result)
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR072 - Expected keyword 'switch'"));
+                
+                return error_node();
+            }
+            
+            scoped_vec_delete<expression_node_t> svd(*this,arg_list);
+            
+            next_token();
+            
+            if (!token_is(token_t::e_lcrlbracket))
             {
-               result = arg_list.back();
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR073 - Expected '{' for call to switch statement"));
+                
+                return error_node();
+            }
+            
+            for ( ; ; )
+            {
+                if (!details::imatch("case",current_token().value))
+                {
+                    set_error(
+                              make_error(parser_error::e_syntax,
+                                         current_token(),
+                                         "ERR074 - Expected either a 'case' or 'default' statement"));
+                    
+                    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(),
+                                         "ERR075 - Expected ':' for case of switch statement"));
+                    
+                    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(),
+                                         "ERR076 - Expected ';' at end of case for switch statement"));
+                    
+                    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);
+                    
+                    condition  = 0;
+                    consequent = 0;
+                }
+                else
+                {
+                    arg_list.push_back( condition);
+                    arg_list.push_back(consequent);
+                }
+                
+                if (details::imatch("default",current_token().value))
+                {
+                    next_token();
+                    if (!token_is(token_t::e_colon))
+                    {
+                        set_error(
+                                  make_error(parser_error::e_syntax,
+                                             current_token(),
+                                             "ERR077 - Expected ':' for default of switch statement"));
+                        
+                        return error_node();
+                    }
+                    
+                    expression_node_ptr default_statement = error_node();
+                    
+                    if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold))
+                        default_statement = parse_multi_sequence("switch-default");
+                    else
+                        default_statement = parse_expression();
+                    
+                    if (0 == default_statement)
+                        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(),
+                                             "ERR078 - Expected ';' at end of default for switch statement"));
+                        
+                        return error_node();
+                    }
+                    
+                    arg_list.push_back(default_statement);
+                    break;
+                }
             }
-
-            for (std::size_t i = 0; i < arg_list.size(); ++i)
+            
+            if (!token_is(token_t::e_rcrlbracket))
             {
-               expression_node_ptr current_expr = arg_list[i];
-
-               if (current_expr && (current_expr != result))
-               {
-                  free_node(*node_allocator_,current_expr);
-               }
-            }
-
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR079 - Expected '}' at end of switch statement"));
+                
+                return error_node();
+            }
+            
+            result = expression_generator_.switch_statement(arg_list);
+            
+            svd.delete_ptr = (0 == result);
+            
             return result;
-         }
-
-         template <typename Allocator,
-                   template <typename,typename> class Sequence>
-         inline expression_node_ptr const_optimize_mswitch(Sequence<expression_node_ptr,Allocator>& arg_list)
-         {
+        }
+        
+        inline expression_node_ptr parse_multi_switch_statement()
+        {
+            std::vector<expression_node_ptr> arg_list;
             expression_node_ptr result = error_node();
-
-            for (std::size_t i = 0; i < (arg_list.size() / 2); ++i)
-            {
-               expression_node_ptr condition  = arg_list[(2 * i)    ];
-               expression_node_ptr consequent = arg_list[(2 * i) + 1];
-
-               if (details::is_true(condition))
-               {
-                  result = consequent;
-               }
-            }
-
-            if (0 == result)
+            
+            if (!details::imatch(current_token().value,"[*]"))
             {
-               T zero = T(0);
-               result = node_allocator_->allocate<literal_node_t>(zero);
-            }
-
-            for (std::size_t i = 0; i < arg_list.size(); ++i)
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR080 - Expected token '[*]'"));
+                
+                return error_node();
+            }
+            
+            scoped_vec_delete<expression_node_t> svd(*this,arg_list);
+            
+            next_token();
+            
+            if (!token_is(token_t::e_lcrlbracket))
             {
-               expression_node_ptr& current_expr = arg_list[i];
-
-               if (current_expr && (current_expr != result))
-               {
-                  free_node(*node_allocator_,current_expr);
-               }
-            }
-
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR081 - Expected '{' for call to [*] statement"));
+                
+                return error_node();
+            }
+            
+            for ( ; ; )
+            {
+                if (!details::imatch("case",current_token().value))
+                {
+                    set_error(
+                              make_error(parser_error::e_syntax,
+                                         current_token(),
+                                         "ERR082 - Expected a 'case' statement for multi-switch"));
+                    
+                    return error_node();
+                }
+                
+                next_token();
+                
+                expression_node_ptr condition = parse_expression();
+                
+                if (0 == condition)
+                    return error_node();
+                
+                if (!token_is(token_t::e_colon))
+                {
+                    set_error(
+                              make_error(parser_error::e_syntax,
+                                         current_token(),
+                                         "ERR083 - Expected ':' for case of [*] statement"));
+                    
+                    return error_node();
+                }
+                
+                expression_node_ptr consequent = parse_expression();
+                
+                if (0 == consequent)
+                    return error_node();
+                
+                if (!token_is(token_t::e_eof))
+                {
+                    set_error(
+                              make_error(parser_error::e_syntax,
+                                         current_token(),
+                                         "ERR084 - Expected ';' at end of case for [*] statement"));
+                    
+                    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);
+                    
+                    condition  = 0;
+                    consequent = 0;
+                }
+                else
+                {
+                    arg_list.push_back(condition);
+                    arg_list.push_back(consequent);
+                }
+                
+                if (token_is(token_t::e_rcrlbracket,prsrhlpr_t::e_hold))
+                {
+                    break;
+                }
+            }
+            
+            if (!token_is(token_t::e_rcrlbracket))
+            {
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR085 - Expected '}' at end of [*] statement"));
+                
+                return error_node();
+            }
+            
+            result = expression_generator_.multi_switch_statement(arg_list);
+            
+            svd.delete_ptr = (0 == result);
+            
             return result;
-         }
-
-         template <typename Allocator,
-                   template <typename,typename> class Sequence>
-         inline expression_node_ptr switch_statement(Sequence<expression_node_ptr,Allocator>& arg_list)
-         {
-            if (!all_nodes_valid(arg_list))
-            {
-               details::free_all_nodes(*node_allocator_,arg_list);
-
-               return error_node();
-            }
-            else if (is_constant_foldable(arg_list))
-               return const_optimize_switch(arg_list);
+        }
+        
+        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;
+            
+            if (details::imatch(symbol,"~"))
+            {
+                next_token();
+                return parse_multi_sequence();
+            }
+            else if (details::imatch(symbol,"[*]"))
+            {
+                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
-               return node_allocator_->allocate<details::switch_node<Type> >(arg_list);
-         }
-
-         template <typename Allocator,
-                   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))
             {
-               details::free_all_nodes(*node_allocator_,arg_list);
-
-               return error_node();
-            }
-            else if (is_constant_foldable(arg_list))
-               return const_optimize_mswitch(arg_list);
-            else
-               return node_allocator_->allocate<details::multi_switch_node<Type> >(arg_list);
-         }
-
-         #define unary_opr_switch_statements           \
-         case_stmt(details::  e_abs,details::  abs_op) \
-         case_stmt(details:: e_acos,details:: acos_op) \
-         case_stmt(details::e_acosh,details::acosh_op) \
-         case_stmt(details:: e_asin,details:: asin_op) \
-         case_stmt(details::e_asinh,details::asinh_op) \
-         case_stmt(details:: e_atan,details:: atan_op) \
-         case_stmt(details::e_atanh,details::atanh_op) \
-         case_stmt(details:: e_ceil,details:: ceil_op) \
-         case_stmt(details::  e_cos,details::  cos_op) \
-         case_stmt(details:: e_cosh,details:: cosh_op) \
-         case_stmt(details::  e_exp,details::  exp_op) \
-         case_stmt(details::e_expm1,details::expm1_op) \
-         case_stmt(details::e_floor,details::floor_op) \
-         case_stmt(details::  e_log,details::  log_op) \
-         case_stmt(details::e_log10,details::log10_op) \
-         case_stmt(details:: e_log2,details:: log2_op) \
-         case_stmt(details::e_log1p,details::log1p_op) \
-         case_stmt(details::  e_neg,details::  neg_op) \
-         case_stmt(details::  e_pos,details::  pos_op) \
-         case_stmt(details::e_round,details::round_op) \
-         case_stmt(details::  e_sin,details::  sin_op) \
-         case_stmt(details:: e_sinc,details:: sinc_op) \
-         case_stmt(details:: e_sinh,details:: sinh_op) \
-         case_stmt(details:: e_sqrt,details:: sqrt_op) \
-         case_stmt(details::  e_tan,details::  tan_op) \
-         case_stmt(details:: e_tanh,details:: tanh_op) \
-         case_stmt(details::  e_cot,details::  cot_op) \
-         case_stmt(details::  e_sec,details::  sec_op) \
-         case_stmt(details::  e_csc,details::  csc_op) \
-         case_stmt(details::  e_r2d,details::  r2d_op) \
-         case_stmt(details::  e_d2r,details::  d2r_op) \
-         case_stmt(details::  e_d2g,details::  d2g_op) \
-         case_stmt(details::  e_g2d,details::  g2d_op) \
-         case_stmt(details:: e_notl,details:: notl_op) \
-         case_stmt(details::  e_sgn,details::  sgn_op) \
-         case_stmt(details::  e_erf,details::  erf_op) \
-         case_stmt(details:: e_erfc,details:: erfc_op) \
-         case_stmt(details:: e_ncdf,details:: ncdf_op) \
-         case_stmt(details:: e_frac,details:: frac_op) \
-         case_stmt(details::e_trunc,details::trunc_op) \
-
-         inline expression_node_ptr synthesize_uv_expression(const details::operator_type& operation,
-                                                             expression_node_ptr (&branch)[1])
-         {
-            T& v = static_cast<details::variable_node<T>*>(branch[0])->ref();
-
-            switch (operation)
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR086 - Unsupported vararg function: " + symbol));
+                
+                return error_node();
+            }
+            
+            scoped_vec_delete<expression_node_t> sdd(*this,arg_list);
+            
+            lodge_symbol(symbol,e_st_function);
+            
+            next_token();
+            
+            if (!token_is(token_t::e_lbracket))
             {
-               #define case_stmt(op0,op1)                                                          \
-               case op0 : return node_allocator_->                                                 \
-                             allocate<typename details::unary_variable_node<Type,op1<Type> > >(v); \
-
-               unary_opr_switch_statements
-               #undef case_stmt
-               default : return error_node();
-            }
-         }
-
-         inline expression_node_ptr synthesize_uvec_expression(const details::operator_type& operation,
-                                                               expression_node_ptr (&branch)[1])
-         {
-            switch (operation)
-            {
-               #define case_stmt(op0,op1)                                                    \
-               case op0 : return node_allocator_->                                           \
-                             allocate<typename details::unary_vector_node<Type,op1<Type> > > \
-                                (operation,branch[0]);                                       \
-
-               unary_opr_switch_statements
-               #undef case_stmt
-               default : return error_node();
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR087 - Expected '(' for call to vararg function: " + symbol));
+                
+                return error_node();
+            }
+            
+            for ( ; ; )
+            {
+                expression_node_ptr arg = parse_expression();
+                
+                if (0 == arg)
+                    return error_node();
+                else
+                    arg_list.push_back(arg);
+                
+                if (token_is(token_t::e_rbracket))
+                    break;
+                else if (!token_is(token_t::e_comma))
+                {
+                    set_error(
+                              make_error(parser_error::e_syntax,
+                                         current_token(),
+                                         "ERR088 - Expected ',' for call to vararg function: " + symbol));
+                    
+                    return error_node();
+                }
+            }
+            
+            result = expression_generator_.vararg_function(opt_type,arg_list);
+            
+            sdd.delete_ptr = (0 == result);
+            return result;
+        }
+        
+#ifndef exprtk_disable_string_capabilities
+        inline expression_node_ptr parse_string_range_statement(expression_node_ptr& expression)
+        {
+            if (!token_is(token_t::e_lsqrbracket))
+            {
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR089 - Expected '[' as start of string range definition"));
+                
+                free_node(node_allocator_,expression);
+                
+                return error_node();
             }
-         }
-
-         inline expression_node_ptr synthesize_unary_expression(const details::operator_type& operation,
-                                                                expression_node_ptr (&branch)[1])
-         {
-            switch (operation)
+            else if (token_is(token_t::e_rsqrbracket))
             {
-               #define case_stmt(op0,op1)                                                                \
-               case op0 : return node_allocator_->                                                       \
-                             allocate<typename details::unary_branch_node<Type,op1<Type> > >(branch[0]); \
-
-               unary_opr_switch_statements
-               #undef case_stmt
-               default : return error_node();
+                return node_allocator_.allocate<details::string_size_node<T> >(expression);
             }
-         }
-
-         inline expression_node_ptr const_optimize_sf3(const details::operator_type& operation,
-                                                       expression_node_ptr (&branch)[3])
-         {
-            expression_node_ptr temp_node = error_node();
-
-            switch (operation)
+            
+            range_t rp;
+            
+            if (!parse_range(rp,true))
             {
-               #define case_stmt(op0,op1)                                  \
-               case op0 : temp_node = node_allocator_->                    \
-                             allocate<details::sf3_node<Type,op1<Type> > > \
-                                (operation,branch);                        \
-                          break;                                           \
-
-               case_stmt(details::e_sf00,details::sf00_op) case_stmt(details::e_sf01,details::sf01_op)
-               case_stmt(details::e_sf02,details::sf02_op) case_stmt(details::e_sf03,details::sf03_op)
-               case_stmt(details::e_sf04,details::sf04_op) case_stmt(details::e_sf05,details::sf05_op)
-               case_stmt(details::e_sf06,details::sf06_op) case_stmt(details::e_sf07,details::sf07_op)
-               case_stmt(details::e_sf08,details::sf08_op) case_stmt(details::e_sf09,details::sf09_op)
-               case_stmt(details::e_sf10,details::sf10_op) case_stmt(details::e_sf11,details::sf11_op)
-               case_stmt(details::e_sf12,details::sf12_op) case_stmt(details::e_sf13,details::sf13_op)
-               case_stmt(details::e_sf14,details::sf14_op) case_stmt(details::e_sf15,details::sf15_op)
-               case_stmt(details::e_sf16,details::sf16_op) case_stmt(details::e_sf17,details::sf17_op)
-               case_stmt(details::e_sf18,details::sf18_op) case_stmt(details::e_sf19,details::sf19_op)
-               case_stmt(details::e_sf20,details::sf20_op) case_stmt(details::e_sf21,details::sf21_op)
-               case_stmt(details::e_sf22,details::sf22_op) case_stmt(details::e_sf23,details::sf23_op)
-               case_stmt(details::e_sf24,details::sf24_op) case_stmt(details::e_sf25,details::sf25_op)
-               case_stmt(details::e_sf26,details::sf26_op) case_stmt(details::e_sf27,details::sf27_op)
-               case_stmt(details::e_sf28,details::sf28_op) case_stmt(details::e_sf29,details::sf29_op)
-               case_stmt(details::e_sf30,details::sf30_op) case_stmt(details::e_sf31,details::sf31_op)
-               case_stmt(details::e_sf32,details::sf32_op) case_stmt(details::e_sf33,details::sf33_op)
-               case_stmt(details::e_sf34,details::sf34_op) case_stmt(details::e_sf35,details::sf35_op)
-               case_stmt(details::e_sf36,details::sf36_op) case_stmt(details::e_sf37,details::sf37_op)
-               case_stmt(details::e_sf38,details::sf38_op) case_stmt(details::e_sf39,details::sf39_op)
-               case_stmt(details::e_sf40,details::sf40_op) case_stmt(details::e_sf41,details::sf41_op)
-               case_stmt(details::e_sf42,details::sf42_op) case_stmt(details::e_sf43,details::sf43_op)
-               case_stmt(details::e_sf44,details::sf44_op) case_stmt(details::e_sf45,details::sf45_op)
-               case_stmt(details::e_sf46,details::sf46_op) case_stmt(details::e_sf47,details::sf47_op)
-               #undef case_stmt
-               default : return error_node();
+                free_node(node_allocator_,expression);
+                
+                return error_node();
             }
-
-            T v = temp_node->value();
-            node_allocator_->free(temp_node);
-            details::free_node(*node_allocator_,temp_node);
-
-            return node_allocator_->allocate<literal_node_t>(v);
-         }
-
-         inline expression_node_ptr varnode_optimize_sf3(const details::operator_type& operation, expression_node_ptr (&branch)[3])
-         {
-            typedef details::variable_node<Type>* variable_ptr;
-
-            const Type& v0 = static_cast<variable_ptr>(branch[0])->ref();
-            const Type& v1 = static_cast<variable_ptr>(branch[1])->ref();
-            const Type& v2 = static_cast<variable_ptr>(branch[2])->ref();
-
-            switch (operation)
-            {
-               #define case_stmt(op0,op1)                                          \
-               case op0 : return node_allocator_->                                 \
-                             allocate_rrr<details::sf3_var_node<Type,op1<Type> > > \
-                                (v0,v1,v2);                                        \
-
-               case_stmt(details::e_sf00,details::sf00_op) case_stmt(details::e_sf01,details::sf01_op)
-               case_stmt(details::e_sf02,details::sf02_op) case_stmt(details::e_sf03,details::sf03_op)
-               case_stmt(details::e_sf04,details::sf04_op) case_stmt(details::e_sf05,details::sf05_op)
-               case_stmt(details::e_sf06,details::sf06_op) case_stmt(details::e_sf07,details::sf07_op)
-               case_stmt(details::e_sf08,details::sf08_op) case_stmt(details::e_sf09,details::sf09_op)
-               case_stmt(details::e_sf10,details::sf10_op) case_stmt(details::e_sf11,details::sf11_op)
-               case_stmt(details::e_sf12,details::sf12_op) case_stmt(details::e_sf13,details::sf13_op)
-               case_stmt(details::e_sf14,details::sf14_op) case_stmt(details::e_sf15,details::sf15_op)
-               case_stmt(details::e_sf16,details::sf16_op) case_stmt(details::e_sf17,details::sf17_op)
-               case_stmt(details::e_sf18,details::sf18_op) case_stmt(details::e_sf19,details::sf19_op)
-               case_stmt(details::e_sf20,details::sf20_op) case_stmt(details::e_sf21,details::sf21_op)
-               case_stmt(details::e_sf22,details::sf22_op) case_stmt(details::e_sf23,details::sf23_op)
-               case_stmt(details::e_sf24,details::sf24_op) case_stmt(details::e_sf25,details::sf25_op)
-               case_stmt(details::e_sf26,details::sf26_op) case_stmt(details::e_sf27,details::sf27_op)
-               case_stmt(details::e_sf28,details::sf28_op) case_stmt(details::e_sf29,details::sf29_op)
-               case_stmt(details::e_sf30,details::sf30_op) case_stmt(details::e_sf31,details::sf31_op)
-               case_stmt(details::e_sf32,details::sf32_op) case_stmt(details::e_sf33,details::sf33_op)
-               case_stmt(details::e_sf34,details::sf34_op) case_stmt(details::e_sf35,details::sf35_op)
-               case_stmt(details::e_sf36,details::sf36_op) case_stmt(details::e_sf37,details::sf37_op)
-               case_stmt(details::e_sf38,details::sf38_op) case_stmt(details::e_sf39,details::sf39_op)
-               case_stmt(details::e_sf40,details::sf40_op) case_stmt(details::e_sf41,details::sf41_op)
-               case_stmt(details::e_sf42,details::sf42_op) case_stmt(details::e_sf43,details::sf43_op)
-               case_stmt(details::e_sf44,details::sf44_op) case_stmt(details::e_sf45,details::sf45_op)
-               case_stmt(details::e_sf46,details::sf46_op) case_stmt(details::e_sf47,details::sf47_op)
-               #undef case_stmt
-               default : return error_node();
-            }
-         }
-
-         inline expression_node_ptr special_function(const details::operator_type& operation, expression_node_ptr (&branch)[3])
-         {
-            if (!all_nodes_valid(branch))
-               return error_node();
-            else if (is_constant_foldable(branch))
-               return const_optimize_sf3(operation,branch);
-            else if (all_nodes_variables(branch))
-               return varnode_optimize_sf3(operation,branch);
-            else
+            
+            expression_node_ptr result = expression_generator_(expression,rp);
+            
+            if (0 == result)
             {
-               switch (operation)
-               {
-                  #define case_stmt(op0,op1)                                                     \
-                  case op0 : return node_allocator_->                                            \
-                                allocate<details::sf3_node<Type,op1<Type> > >(operation,branch); \
-
-                  case_stmt(details::e_sf00,details::sf00_op) case_stmt(details::e_sf01,details::sf01_op)
-                  case_stmt(details::e_sf02,details::sf02_op) case_stmt(details::e_sf03,details::sf03_op)
-                  case_stmt(details::e_sf04,details::sf04_op) case_stmt(details::e_sf05,details::sf05_op)
-                  case_stmt(details::e_sf06,details::sf06_op) case_stmt(details::e_sf07,details::sf07_op)
-                  case_stmt(details::e_sf08,details::sf08_op) case_stmt(details::e_sf09,details::sf09_op)
-                  case_stmt(details::e_sf10,details::sf10_op) case_stmt(details::e_sf11,details::sf11_op)
-                  case_stmt(details::e_sf12,details::sf12_op) case_stmt(details::e_sf13,details::sf13_op)
-                  case_stmt(details::e_sf14,details::sf14_op) case_stmt(details::e_sf15,details::sf15_op)
-                  case_stmt(details::e_sf16,details::sf16_op) case_stmt(details::e_sf17,details::sf17_op)
-                  case_stmt(details::e_sf18,details::sf18_op) case_stmt(details::e_sf19,details::sf19_op)
-                  case_stmt(details::e_sf20,details::sf20_op) case_stmt(details::e_sf21,details::sf21_op)
-                  case_stmt(details::e_sf22,details::sf22_op) case_stmt(details::e_sf23,details::sf23_op)
-                  case_stmt(details::e_sf24,details::sf24_op) case_stmt(details::e_sf25,details::sf25_op)
-                  case_stmt(details::e_sf26,details::sf26_op) case_stmt(details::e_sf27,details::sf27_op)
-                  case_stmt(details::e_sf28,details::sf28_op) case_stmt(details::e_sf29,details::sf29_op)
-                  case_stmt(details::e_sf30,details::sf30_op) case_stmt(details::e_sf31,details::sf31_op)
-                  case_stmt(details::e_sf32,details::sf32_op) case_stmt(details::e_sf33,details::sf33_op)
-                  case_stmt(details::e_sf34,details::sf34_op) case_stmt(details::e_sf35,details::sf35_op)
-                  case_stmt(details::e_sf36,details::sf36_op) case_stmt(details::e_sf37,details::sf37_op)
-                  case_stmt(details::e_sf38,details::sf38_op) case_stmt(details::e_sf39,details::sf39_op)
-                  case_stmt(details::e_sf40,details::sf40_op) case_stmt(details::e_sf41,details::sf41_op)
-                  case_stmt(details::e_sf42,details::sf42_op) case_stmt(details::e_sf43,details::sf43_op)
-                  case_stmt(details::e_sf44,details::sf44_op) case_stmt(details::e_sf45,details::sf45_op)
-                  case_stmt(details::e_sf46,details::sf46_op) case_stmt(details::e_sf47,details::sf47_op)
-                  #undef case_stmt
-                  default : return error_node();
-               }
-            }
-         }
-
-         inline expression_node_ptr const_optimize_sf4(const details::operator_type& operation, expression_node_ptr (&branch)[4])
-         {
-            expression_node_ptr temp_node = error_node();
-
-            switch (operation)
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR090 - Failed to generate string range node"));
+                
+                free_node(node_allocator_,expression);
+            }
+            
+            rp.clear();
+            
+            return result;
+        }
+#else
+        inline expression_node_ptr parse_string_range_statement(expression_node_ptr&)
+        {
+            return error_node();
+        }
+#endif
+        
+        inline void parse_pending_string_rangesize(expression_node_ptr& expression)
+        {
+            // Allow no more than 100 range calls, eg: s[][][]...[][]
+            const std::size_t max_rangesize_parses = 100;
+            
+            std::size_t i = 0;
+            
+            while
+                (
+                 (0 != expression)                     &&
+                 (i++ < max_rangesize_parses)          &&
+                 error_list_.empty()                   &&
+                 is_generally_string_node(expression)  &&
+                 token_is(token_t::e_lsqrbracket,prsrhlpr_t::e_hold)
+                 )
             {
-               #define case_stmt(op0,op1)                                                                 \
-               case op0 : temp_node = node_allocator_->                                                   \
-                                         allocate<details::sf4_node<Type,op1<Type> > >(operation,branch); \
-                          break;                                                                          \
-
-               case_stmt(details::e_sf48,details::sf48_op) case_stmt(details::e_sf49,details::sf49_op)
-               case_stmt(details::e_sf50,details::sf50_op) case_stmt(details::e_sf51,details::sf51_op)
-               case_stmt(details::e_sf52,details::sf52_op) case_stmt(details::e_sf53,details::sf53_op)
-               case_stmt(details::e_sf54,details::sf54_op) case_stmt(details::e_sf55,details::sf55_op)
-               case_stmt(details::e_sf56,details::sf56_op) case_stmt(details::e_sf57,details::sf57_op)
-               case_stmt(details::e_sf58,details::sf58_op) case_stmt(details::e_sf59,details::sf59_op)
-               case_stmt(details::e_sf60,details::sf60_op) case_stmt(details::e_sf61,details::sf61_op)
-               case_stmt(details::e_sf62,details::sf62_op) case_stmt(details::e_sf63,details::sf63_op)
-               case_stmt(details::e_sf64,details::sf64_op) case_stmt(details::e_sf65,details::sf65_op)
-               case_stmt(details::e_sf66,details::sf66_op) case_stmt(details::e_sf67,details::sf67_op)
-               case_stmt(details::e_sf68,details::sf68_op) case_stmt(details::e_sf69,details::sf69_op)
-               case_stmt(details::e_sf70,details::sf70_op) case_stmt(details::e_sf71,details::sf71_op)
-               case_stmt(details::e_sf72,details::sf72_op) case_stmt(details::e_sf73,details::sf73_op)
-               case_stmt(details::e_sf74,details::sf74_op) case_stmt(details::e_sf75,details::sf75_op)
-               case_stmt(details::e_sf76,details::sf76_op) case_stmt(details::e_sf77,details::sf77_op)
-               case_stmt(details::e_sf78,details::sf78_op) case_stmt(details::e_sf79,details::sf79_op)
-               case_stmt(details::e_sf80,details::sf80_op) case_stmt(details::e_sf81,details::sf81_op)
-               case_stmt(details::e_sf82,details::sf82_op) case_stmt(details::e_sf83,details::sf83_op)
-               case_stmt(details::e_sf84,details::sf84_op) case_stmt(details::e_sf85,details::sf85_op)
-               case_stmt(details::e_sf86,details::sf86_op) case_stmt(details::e_sf87,details::sf87_op)
-               case_stmt(details::e_sf88,details::sf88_op) case_stmt(details::e_sf89,details::sf89_op)
-               case_stmt(details::e_sf90,details::sf90_op) case_stmt(details::e_sf91,details::sf91_op)
-               case_stmt(details::e_sf92,details::sf92_op) case_stmt(details::e_sf93,details::sf93_op)
-               case_stmt(details::e_sf94,details::sf94_op) case_stmt(details::e_sf95,details::sf95_op)
-               case_stmt(details::e_sf96,details::sf96_op) case_stmt(details::e_sf97,details::sf97_op)
-               case_stmt(details::e_sf98,details::sf98_op) case_stmt(details::e_sf99,details::sf99_op)
-               #undef case_stmt
-               default : return error_node();
+                expression = parse_string_range_statement(expression);
+            }
+        }
+        
+        template <typename Allocator1,
+        typename Allocator2,
+        template <typename,typename> class Sequence>
+        inline expression_node_ptr simplify(Sequence<expression_node_ptr,Allocator1>& expression_list,
+                                            Sequence<bool,Allocator2>& side_effect_list)
+        {
+            if (expression_list.empty())
+                return error_node();
+            else if (1 == expression_list.size())
+                return expression_list[0];
+            
+            Sequence<expression_node_ptr,Allocator1> tmp_expression_list;
+            
+            bool return_node_present = false;
+            
+            for (std::size_t i = 0; i < (expression_list.size() - 1); ++i)
+            {
+                if (is_variable_node(expression_list[i]))
+                    continue;
+                else if (
+                         is_return_node  (expression_list[i]) ||
+                         is_break_node   (expression_list[i]) ||
+                         is_continue_node(expression_list[i])
+                         )
+                {
+                    tmp_expression_list.push_back(expression_list[i]);
+                    
+                    // Remove all subexpressions after first short-circuit
+                    // node has been encountered.
+                    
+                    for (std::size_t j = i + 1; j < expression_list.size(); ++j)
+                    {
+                        free_node(node_allocator_,expression_list[j]);
+                    }
+                    
+                    return_node_present = true;
+                    
+                    break;
+                }
+                else if (
+                         is_constant_node(expression_list[i]) ||
+                         is_null_node    (expression_list[i]) ||
+                         !side_effect_list[i]
+                         )
+                {
+                    free_node(node_allocator_,expression_list[i]);
+                    continue;
+                }
+                else
+                    tmp_expression_list.push_back(expression_list[i]);
             }
-
-            T v = temp_node->value();
-            details::free_node(*node_allocator_,temp_node);
-
-            return node_allocator_->allocate<literal_node_t>(v);
-         }
-
-         inline expression_node_ptr varnode_optimize_sf4(const details::operator_type& operation, expression_node_ptr (&branch)[4])
-         {
-            typedef details::variable_node<Type>* variable_ptr;
-
-            const Type& v0 = static_cast<variable_ptr>(branch[0])->ref();
-            const Type& v1 = static_cast<variable_ptr>(branch[1])->ref();
-            const Type& v2 = static_cast<variable_ptr>(branch[2])->ref();
-            const Type& v3 = static_cast<variable_ptr>(branch[3])->ref();
-
-            switch (operation)
+            
+            if (!return_node_present)
             {
-               #define case_stmt(op0,op1)                                                         \
-               case op0 : return node_allocator_->                                                \
-                             allocate_rrrr<details::sf4_var_node<Type,op1<Type> > >(v0,v1,v2,v3); \
-
-               case_stmt(details::e_sf48,details::sf48_op) case_stmt(details::e_sf49,details::sf49_op)
-               case_stmt(details::e_sf50,details::sf50_op) case_stmt(details::e_sf51,details::sf51_op)
-               case_stmt(details::e_sf52,details::sf52_op) case_stmt(details::e_sf53,details::sf53_op)
-               case_stmt(details::e_sf54,details::sf54_op) case_stmt(details::e_sf55,details::sf55_op)
-               case_stmt(details::e_sf56,details::sf56_op) case_stmt(details::e_sf57,details::sf57_op)
-               case_stmt(details::e_sf58,details::sf58_op) case_stmt(details::e_sf59,details::sf59_op)
-               case_stmt(details::e_sf60,details::sf60_op) case_stmt(details::e_sf61,details::sf61_op)
-               case_stmt(details::e_sf62,details::sf62_op) case_stmt(details::e_sf63,details::sf63_op)
-               case_stmt(details::e_sf64,details::sf64_op) case_stmt(details::e_sf65,details::sf65_op)
-               case_stmt(details::e_sf66,details::sf66_op) case_stmt(details::e_sf67,details::sf67_op)
-               case_stmt(details::e_sf68,details::sf68_op) case_stmt(details::e_sf69,details::sf69_op)
-               case_stmt(details::e_sf70,details::sf70_op) case_stmt(details::e_sf71,details::sf71_op)
-               case_stmt(details::e_sf72,details::sf72_op) case_stmt(details::e_sf73,details::sf73_op)
-               case_stmt(details::e_sf74,details::sf74_op) case_stmt(details::e_sf75,details::sf75_op)
-               case_stmt(details::e_sf76,details::sf76_op) case_stmt(details::e_sf77,details::sf77_op)
-               case_stmt(details::e_sf78,details::sf78_op) case_stmt(details::e_sf79,details::sf79_op)
-               case_stmt(details::e_sf80,details::sf80_op) case_stmt(details::e_sf81,details::sf81_op)
-               case_stmt(details::e_sf82,details::sf82_op) case_stmt(details::e_sf83,details::sf83_op)
-               case_stmt(details::e_sf84,details::sf84_op) case_stmt(details::e_sf85,details::sf85_op)
-               case_stmt(details::e_sf86,details::sf86_op) case_stmt(details::e_sf87,details::sf87_op)
-               case_stmt(details::e_sf88,details::sf88_op) case_stmt(details::e_sf89,details::sf89_op)
-               case_stmt(details::e_sf90,details::sf90_op) case_stmt(details::e_sf91,details::sf91_op)
-               case_stmt(details::e_sf92,details::sf92_op) case_stmt(details::e_sf93,details::sf93_op)
-               case_stmt(details::e_sf94,details::sf94_op) case_stmt(details::e_sf95,details::sf95_op)
-               case_stmt(details::e_sf96,details::sf96_op) case_stmt(details::e_sf97,details::sf97_op)
-               case_stmt(details::e_sf98,details::sf98_op) case_stmt(details::e_sf99,details::sf99_op)
-               #undef case_stmt
-               default : return error_node();
-            }
-         }
-
-         inline expression_node_ptr special_function(const details::operator_type& operation, expression_node_ptr (&branch)[4])
-         {
-            if (!all_nodes_valid(branch))
-               return error_node();
-            else if (is_constant_foldable(branch))
-               return const_optimize_sf4(operation,branch);
-            else if (all_nodes_variables(branch))
-               return varnode_optimize_sf4(operation,branch);
-            switch (operation)
-            {
-               #define case_stmt(op0,op1)                                                     \
-               case op0 : return node_allocator_->                                            \
-                             allocate<details::sf4_node<Type,op1<Type> > >(operation,branch); \
-
-               case_stmt(details::e_sf48,details::sf48_op) case_stmt(details::e_sf49,details::sf49_op)
-               case_stmt(details::e_sf50,details::sf50_op) case_stmt(details::e_sf51,details::sf51_op)
-               case_stmt(details::e_sf52,details::sf52_op) case_stmt(details::e_sf53,details::sf53_op)
-               case_stmt(details::e_sf54,details::sf54_op) case_stmt(details::e_sf55,details::sf55_op)
-               case_stmt(details::e_sf56,details::sf56_op) case_stmt(details::e_sf57,details::sf57_op)
-               case_stmt(details::e_sf58,details::sf58_op) case_stmt(details::e_sf59,details::sf59_op)
-               case_stmt(details::e_sf60,details::sf60_op) case_stmt(details::e_sf61,details::sf61_op)
-               case_stmt(details::e_sf62,details::sf62_op) case_stmt(details::e_sf63,details::sf63_op)
-               case_stmt(details::e_sf64,details::sf64_op) case_stmt(details::e_sf65,details::sf65_op)
-               case_stmt(details::e_sf66,details::sf66_op) case_stmt(details::e_sf67,details::sf67_op)
-               case_stmt(details::e_sf68,details::sf68_op) case_stmt(details::e_sf69,details::sf69_op)
-               case_stmt(details::e_sf70,details::sf70_op) case_stmt(details::e_sf71,details::sf71_op)
-               case_stmt(details::e_sf72,details::sf72_op) case_stmt(details::e_sf73,details::sf73_op)
-               case_stmt(details::e_sf74,details::sf74_op) case_stmt(details::e_sf75,details::sf75_op)
-               case_stmt(details::e_sf76,details::sf76_op) case_stmt(details::e_sf77,details::sf77_op)
-               case_stmt(details::e_sf78,details::sf78_op) case_stmt(details::e_sf79,details::sf79_op)
-               case_stmt(details::e_sf80,details::sf80_op) case_stmt(details::e_sf81,details::sf81_op)
-               case_stmt(details::e_sf82,details::sf82_op) case_stmt(details::e_sf83,details::sf83_op)
-               case_stmt(details::e_sf84,details::sf84_op) case_stmt(details::e_sf85,details::sf85_op)
-               case_stmt(details::e_sf86,details::sf86_op) case_stmt(details::e_sf87,details::sf87_op)
-               case_stmt(details::e_sf88,details::sf88_op) case_stmt(details::e_sf89,details::sf89_op)
-               case_stmt(details::e_sf90,details::sf90_op) case_stmt(details::e_sf91,details::sf91_op)
-               case_stmt(details::e_sf92,details::sf92_op) case_stmt(details::e_sf93,details::sf93_op)
-               case_stmt(details::e_sf94,details::sf94_op) case_stmt(details::e_sf95,details::sf95_op)
-               case_stmt(details::e_sf96,details::sf96_op) case_stmt(details::e_sf97,details::sf97_op)
-               case_stmt(details::e_sf98,details::sf98_op) case_stmt(details::e_sf99,details::sf99_op)
-               #undef case_stmt
-               default : return error_node();
-            }
-         }
-
-         template <typename Allocator,
-                   template <typename,typename> class Sequence>
-         inline expression_node_ptr const_optimize_varargfunc(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list)
-         {
-            expression_node_ptr temp_node = error_node();
-
-            switch (operation)
-            {
-               #define case_stmt(op0,op1)                                                 \
-               case op0 : temp_node = node_allocator_->                                   \
-                                         allocate<details::vararg_node<Type,op1<Type> > > \
-                                            (arg_list);                                   \
-                          break;                                                          \
-
-               case_stmt(details::e_sum,  details::vararg_add_op  )
-               case_stmt(details::e_prod, details::vararg_mul_op  )
-               case_stmt(details::e_avg,  details::vararg_avg_op  )
-               case_stmt(details::e_min,  details::vararg_min_op  )
-               case_stmt(details::e_max,  details::vararg_max_op  )
-               case_stmt(details::e_mand, details::vararg_mand_op )
-               case_stmt(details::e_mor,  details::vararg_mor_op  )
-               case_stmt(details::e_multi,details::vararg_multi_op)
-               #undef case_stmt
-               default : return error_node();
+                tmp_expression_list.push_back(expression_list.back());
             }
-
-            T v = temp_node->value();
-            details::free_node(*node_allocator_,temp_node);
-
-            return node_allocator_->allocate<literal_node_t>(v);
-         }
-
-         inline bool special_one_parameter_vararg(const details::operator_type& operation)
-         {
-            return (
-                     (details::e_sum  == operation) ||
-                     (details::e_prod == operation) ||
-                     (details::e_avg  == operation) ||
-                     (details::e_min  == operation) ||
-                     (details::e_max  == operation)
-                   );
-         }
-
-         template <typename Allocator,
-                   template <typename,typename> class Sequence>
-         inline expression_node_ptr varnode_optimize_varargfunc(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list)
-         {
-            switch (operation)
-            {
-               #define case_stmt(op0,op1)                                                   \
-               case op0 : return node_allocator_->                                          \
-                             allocate<details::vararg_varnode<Type,op1<Type> > >(arg_list); \
-
-               case_stmt(details::e_sum,  details::vararg_add_op  )
-               case_stmt(details::e_prod, details::vararg_mul_op  )
-               case_stmt(details::e_avg,  details::vararg_avg_op  )
-               case_stmt(details::e_min,  details::vararg_min_op  )
-               case_stmt(details::e_max,  details::vararg_max_op  )
-               case_stmt(details::e_mand, details::vararg_mand_op )
-               case_stmt(details::e_mor,  details::vararg_mor_op  )
-               case_stmt(details::e_multi,details::vararg_multi_op)
-               #undef case_stmt
-               default : return error_node();
-            }
-         }
-
-         template <typename Allocator,
-                   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())
-            {
-               switch (operation)
-               {
-                  #define case_stmt(op0,op1)                                                      \
-                  case op0 : return node_allocator_->                                             \
-                                allocate<details::vectorize_node<Type,op1<Type> > >(arg_list[0]); \
-
-                  case_stmt(details::e_sum,  details::vec_add_op)
-                  case_stmt(details::e_prod, details::vec_mul_op)
-                  case_stmt(details::e_avg,  details::vec_avg_op)
-                  case_stmt(details::e_min,  details::vec_min_op)
-                  case_stmt(details::e_max,  details::vec_max_op)
-                  #undef case_stmt
-                  default : return error_node();
-               }
+            
+            expression_list.swap(tmp_expression_list);
+            
+            if (tmp_expression_list.size() > expression_list.size())
+            {
+                exprtk_debug(("simplify() - Reduced subexpressions from %d to %d\n",
+                              static_cast<int>(tmp_expression_list.size()),
+                              static_cast<int>(expression_list    .size())));
             }
+            
+            if (
+                return_node_present          ||
+                side_effect_list.back()      ||
+                (expression_list.size() > 1)
+                )
+                state_.activate_side_effect("simplify()");
+            
+            if (1 == expression_list.size())
+                return expression_list[0];
             else
-               return error_node();
-         }
-
-         template <typename Allocator,
-                   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))
-            {
-               details::free_all_nodes(*node_allocator_,arg_list);
-
-               return error_node();
-            }
-            else if (is_constant_foldable(arg_list))
-               return const_optimize_varargfunc(operation,arg_list);
-            else if ((arg_list.size() == 1) && details::is_ivector_node(arg_list[0]))
-               return vectorize_func(operation,arg_list);
-            else if ((arg_list.size() == 1) && special_one_parameter_vararg(operation))
-               return arg_list[0];
-            else if (all_nodes_variables(arg_list))
-               return varnode_optimize_varargfunc(operation,arg_list);
-
-            switch (operation)
+                return expression_generator_.vararg_function(details::e_multi,expression_list);
+        }
+        
+        inline expression_node_ptr parse_multi_sequence(const std::string& source = "")
+        {
+            token_t::token_type close_bracket = token_t::e_rcrlbracket;
+            token_t::token_type seperator     = token_t::e_eof;
+            
+            if (!token_is(token_t::e_lcrlbracket))
+            {
+                if (token_is(token_t::e_lbracket))
+                {
+                    close_bracket = token_t::e_rbracket;
+                    seperator     = token_t::e_comma;
+                }
+                else
+                {
+                    set_error(
+                              make_error(parser_error::e_syntax,
+                                         current_token(),
+                                         "ERR091 - Expected '" + token_t::to_str(close_bracket) + "' for call to multi-sequence" +
+                                         ((!source.empty()) ? std::string(" section of " + source): "")));
+                    
+                    return error_node();
+                }
+            }
+            else if (token_is(token_t::e_rcrlbracket))
+            {
+                return node_allocator_.allocate<details::null_node<T> >();
+            }
+            
+            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);
+            
+            scope_handler sh(*this);
+            
+            scoped_bool_or_restorer sbr(state_.side_effect_present);
+            
+            for ( ; ; )
+            {
+                state_.side_effect_present = false;
+                
+                expression_node_ptr arg = parse_expression();
+                
+                if (0 == arg)
+                    return error_node();
+                else
+                {
+                    arg_list.push_back(arg);
+                    side_effect_list.push_back(state_.side_effect_present);
+                }
+                
+                if (token_is(close_bracket))
+                    break;
+                
+                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(),
+                                         "ERR092 - Expected '" + details::to_str(seperator) + "' for call to multi-sequence section of " + source));
+                    
+                    return error_node();
+                }
+                
+                if (token_is(close_bracket))
+                    break;
+            }
+            
+            result = simplify(arg_list,side_effect_list);
+            
+            sdd.delete_ptr = (0 == result);
+            return result;
+        }
+        
+        inline bool parse_range(range_t& rp, const bool skip_lsqr = false)
+        {
+            // Examples of valid ranges:
+            // 1. [1:5]     -> 1..5
+            // 2. [ :5]     -> 0..5
+            // 3. [1: ]     -> 1..end
+            // 4. [x:y]     -> x..y where x <= y
+            // 5. [x+1:y/2] -> x+1..y/2 where x+1 <= y/2
+            // 6. [ :y]     -> 0..y where 0 <= y
+            // 7. [x: ]     -> x..end where x <= end
+            
+            rp.clear();
+            
+            if (!skip_lsqr && !token_is(token_t::e_lsqrbracket))
+            {
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR093 - Expected '[' for start of range"));
+                
+                return false;
+            }
+            
+            if (token_is(token_t::e_colon))
             {
-               #define case_stmt(op0,op1)                                                \
-               case op0 : return node_allocator_->                                       \
-                             allocate<details::vararg_node<Type,op1<Type> > >(arg_list); \
-
-               case_stmt(details::e_sum,  details::vararg_add_op  )
-               case_stmt(details::e_prod, details::vararg_mul_op  )
-               case_stmt(details::e_avg,  details::vararg_avg_op  )
-               case_stmt(details::e_min,  details::vararg_min_op  )
-               case_stmt(details::e_max,  details::vararg_max_op  )
-               case_stmt(details::e_mand, details::vararg_mand_op )
-               case_stmt(details::e_mor,  details::vararg_mor_op  )
-               case_stmt(details::e_multi,details::vararg_multi_op)
-               #undef case_stmt
-               default : return error_node();
-            }
-         }
-
-         template <std::size_t N>
-         inline expression_node_ptr function(ifunction_t* f, expression_node_ptr (&b)[N])
-         {
-            typedef typename details::function_N_node<T,ifunction_t,N> function_N_node_t;
-            expression_node_ptr result = synthesize_expression<function_N_node_t,N>(f,b);
-
-            if (0 == result)
-               return error_node();
+                rp.n0_c.first  = true;
+                rp.n0_c.second = 0;
+                rp.cache.first = 0;
+            }
             else
             {
-               // Can the function call be completely optimized?
-               if (details::is_constant_node(result))
-                  return result;
-               else if (!all_nodes_valid(b))
-                  return error_node();
-               else if (N != f->param_count)
-               {
-                  details::free_all_nodes(*node_allocator_,b);
-
-                  return error_node();
-               }
-
-               function_N_node_t* func_node_ptr = static_cast<function_N_node_t*>(result);
-
-               if (func_node_ptr->init_branches(b))
-                  return result;
-               else
-               {
-                  details::free_all_nodes(*node_allocator_,b);
-
-                  return error_node();
-               }
+                expression_node_ptr r0 = parse_expression();
+                
+                if (0 == r0)
+                {
+                    set_error(
+                              make_error(parser_error::e_syntax,
+                                         current_token(),
+                                         "ERR094 - Failed parse begin section of range"));
+                    
+                    return false;
+                    
+                }
+                else if (is_constant_node(r0))
+                {
+                    T r0_value = r0->value();
+                    
+                    if (r0_value >= T(0))
+                    {
+                        rp.n0_c.first  = true;
+                        rp.n0_c.second = static_cast<std::size_t>(details::numeric::to_int64(r0_value));
+                        rp.cache.first = rp.n0_c.second;
+                    }
+                    
+                    free_node(node_allocator_,r0);
+                    
+                    if (r0_value < T(0))
+                    {
+                        set_error(
+                                  make_error(parser_error::e_syntax,
+                                             current_token(),
+                                             "ERR095 - Range lower bound less than zero! Constraint: r0 >= 0"));
+                        
+                        return false;
+                    }
+                }
+                else
+                {
+                    rp.n0_e.first  = true;
+                    rp.n0_e.second = r0;
+                }
+                
+                if (!token_is(token_t::e_colon))
+                {
+                    set_error(
+                              make_error(parser_error::e_syntax,
+                                         current_token(),
+                                         "ERR096 - Expected ':' for break  in range"));
+                    
+                    rp.free();
+                    return false;
+                }
+            }
+            
+            if (token_is(token_t::e_rsqrbracket))
+            {
+                rp.n1_c.first  = true;
+                rp.n1_c.second = std::numeric_limits<std::size_t>::max();
             }
-         }
-
-         inline expression_node_ptr function(ifunction_t* f)
-         {
-            typedef typename details::function_N_node<Type,ifunction_t,0> function_N_node_t;
-            return node_allocator_->allocate<function_N_node_t>(f);
-         }
-
-         inline expression_node_ptr vararg_function_call(ivararg_function_t* vaf,
-                                                         std::vector<expression_node_ptr>& arg_list)
-         {
-            if (!all_nodes_valid(arg_list))
+            else
             {
-               details::free_all_nodes(*node_allocator_,arg_list);
-
-               return error_node();
+                expression_node_ptr r1 = parse_expression();
+                
+                if (0 == r1)
+                {
+                    set_error(
+                              make_error(parser_error::e_syntax,
+                                         current_token(),
+                                         "ERR097 - Failed parse end section of range"));
+                    
+                    rp.free();
+                    return false;
+                    
+                }
+                else if (is_constant_node(r1))
+                {
+                    T r1_value = r1->value();
+                    
+                    if (r1_value >= T(0))
+                    {
+                        rp.n1_c.first   = true;
+                        rp.n1_c.second  = static_cast<std::size_t>(details::numeric::to_int64(r1_value));
+                        rp.cache.second = rp.n1_c.second;
+                    }
+                    
+                    free_node(node_allocator_,r1);
+                    
+                    if (r1_value < T(0))
+                    {
+                        set_error(
+                                  make_error(parser_error::e_syntax,
+                                             current_token(),
+                                             "ERR098 - Range upper bound less than zero! Constraint: r1 >= 0"));
+                        
+                        return false;
+                    }
+                }
+                else
+                {
+                    rp.n1_e.first  = true;
+                    rp.n1_e.second = r1;
+                }
+                
+                if (!token_is(token_t::e_rsqrbracket))
+                {
+                    set_error(
+                              make_error(parser_error::e_syntax,
+                                         current_token(),
+                                         "ERR099 - Expected ']' for start of range"));
+                    
+                    rp.free();
+                    return false;
+                }
+            }
+            
+            if (rp.const_range())
+            {
+                std::size_t r0 = 0;
+                std::size_t r1 = 0;
+                
+                bool rp_result = rp(r0,r1);
+                
+                if (!rp_result || (r0 > r1))
+                {
+                    set_error(
+                              make_error(parser_error::e_syntax,
+                                         current_token(),
+                                         "ERR100 - Invalid range, Constraint: r0 <= r1"));
+                    
+                    return false;
+                }
+            }
+            
+            return true;
+        }
+        
+        inline void lodge_symbol(const std::string& symbol,
+                                 const symbol_type st)
+        {
+            dec_.add_symbol(symbol,st);
+        }
+        
+#ifndef exprtk_disable_string_capabilities
+        inline expression_node_ptr parse_string()
+        {
+            const std::string symbol = current_token().value;
+            
+            typedef details::stringvar_node<T>* strvar_node_t;
+            
+            expression_node_ptr result   = error_node();
+            strvar_node_t const_str_node = static_cast<strvar_node_t>(0);
+            bool is_const_string         = false;
+            
+            scope_element& se = sem_.get_active_element(symbol);
+            
+            if (scope_element::e_string == se.type)
+            {
+                se.active = true;
+                result    = se.str_node;
+                lodge_symbol(symbol,e_st_local_string);
             }
-
-            typedef details::vararg_function_node<Type,ivararg_function_t> alloc_type;
-
-            expression_node_ptr result = node_allocator_->allocate<alloc_type>(vaf,arg_list);
-
-            if (
-                 !arg_list.empty()      &&
-                 !vaf->has_side_effects &&
-                 is_constant_foldable(arg_list)
-               )
+            else
             {
-               Type v = result->value();
-               details::free_node(*node_allocator_,result);
-               result = node_allocator_->allocate<literal_node_t>(v);
+                if (!symtab_store_.is_conststr_stringvar(symbol))
+                {
+                    set_error(
+                              make_error(parser_error::e_syntax,
+                                         current_token(),
+                                         "ERR101 - Unknown string symbol"));
+                    
+                    return error_node();
+                }
+                
+                result = symtab_store_.get_stringvar(symbol);
+                
+                is_const_string = symtab_store_.is_constant_string(symbol);
+                
+                if (is_const_string)
+                {
+                    const_str_node = static_cast<strvar_node_t>(result);
+                    result = expression_generator_(const_str_node->str());
+                }
+                
+                lodge_symbol(symbol,e_st_string);
+            }
+            
+            if (peek_token_is(token_t::e_lsqrbracket))
+            {
+                next_token();
+                
+                if (peek_token_is(token_t::e_rsqrbracket))
+                {
+                    next_token();
+                    next_token();
+                    
+                    if (const_str_node)
+                    {
+                        free_node(node_allocator_,result);
+                        
+                        return expression_generator_(T(const_str_node->size()));
+                    }
+                    else
+                        return node_allocator_.allocate<details::stringvar_size_node<T> >
+                        (static_cast<details::stringvar_node<T>*>(result)->ref());
+                }
+                
+                range_t rp;
+                
+                if (!parse_range(rp))
+                {
+                    free_node(node_allocator_,result);
+                    
+                    return error_node();
+                }
+                else if (const_str_node)
+                {
+                    free_node(node_allocator_,result);
+                    result = expression_generator_(const_str_node->ref(),rp);
+                }
+                else
+                    result = expression_generator_(static_cast<details::stringvar_node<T>*>(result)->ref(),rp);
+                
+                if (result)
+                    rp.clear();
             }
-
+            else
+                next_token();
+            
             return result;
-         }
-
-         inline expression_node_ptr generic_function_call(igeneric_function_t* gf,
-                                                          std::vector<expression_node_ptr>& arg_list,
-                                                          const std::size_t& param_seq_index = std::numeric_limits<std::size_t>::max())
-         {
-            if (!all_nodes_valid(arg_list))
-            {
-               details::free_all_nodes(*node_allocator_,arg_list);
-               return error_node();
+        }
+#else
+        inline expression_node_ptr parse_string()
+        {
+            return error_node();
+        }
+#endif
+        
+#ifndef exprtk_disable_string_capabilities
+        inline expression_node_ptr parse_const_string()
+        {
+            const std::string const_str = current_token().value;
+            expression_node_ptr result = expression_generator_(const_str);
+            
+            if (peek_token_is(token_t::e_lsqrbracket))
+            {
+                next_token();
+                
+                if (peek_token_is(token_t::e_rsqrbracket))
+                {
+                    next_token();
+                    next_token();
+                    
+                    free_node(node_allocator_,result);
+                    
+                    return expression_generator_(T(const_str.size()));
+                }
+                
+                range_t rp;
+                
+                if (!parse_range(rp))
+                {
+                    free_node(node_allocator_,result);
+                    
+                    return error_node();
+                }
+                
+                free_node(node_allocator_,result);
+                
+                if (rp.n1_c.first && (rp.n1_c.second == std::numeric_limits<std::size_t>::max()))
+                {
+                    rp.n1_c.second  = const_str.size() - 1;
+                    rp.cache.second = rp.n1_c.second;
+                }
+                
+                if (
+                    (rp.n0_c.first && (rp.n0_c.second >= const_str.size())) ||
+                    (rp.n1_c.first && (rp.n1_c.second >= const_str.size()))
+                    )
+                {
+                    set_error(
+                              make_error(parser_error::e_syntax,
+                                         current_token(),
+                                         "ERR102 - 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)) : "?") + "]"));
+                    
+                    return error_node();
+                }
+                
+                result = expression_generator_(const_str,rp);
+                
+                if (result)
+                    rp.clear();
             }
-
-            typedef details::generic_function_node     <Type,igeneric_function_t> alloc_type1;
-            typedef details::multimode_genfunction_node<Type,igeneric_function_t> alloc_type2;
-
-            const std::size_t no_psi = std::numeric_limits<std::size_t>::max();
-
-            expression_node_ptr result = error_node();
-
-            if (no_psi == param_seq_index)
-               result = node_allocator_->allocate<alloc_type1>(gf,arg_list);
             else
-               result = node_allocator_->allocate<alloc_type2>(gf,param_seq_index,arg_list);
-
-            alloc_type1* genfunc_node_ptr = static_cast<alloc_type1*>(result);
-
+                next_token();
+            
+            return result;
+        }
+#else
+        inline expression_node_ptr parse_const_string()
+        {
+            return error_node();
+        }
+#endif
+        
+        inline expression_node_ptr parse_vector()
+        {
+            const std::string symbol = current_token().value;
+            
+            vector_holder_ptr vec = vector_holder_ptr(0);
+            
+            const scope_element& se = sem_.get_active_element(symbol);
+            
             if (
-                 !arg_list.empty()     &&
-                 !gf->has_side_effects &&
-                 is_constant_foldable(arg_list)
-               )
-            {
-               genfunc_node_ptr->init_branches();
-               Type v = result->value();
-               details::free_node(*node_allocator_,result);
-               return node_allocator_->allocate<literal_node_t>(v);
-            }
-            else if (genfunc_node_ptr->init_branches())
-               return result;
+                (se.name != symbol)             ||
+                (se.depth > state_.scope_depth) ||
+                (scope_element::e_vector != se.type)
+                )
+            {
+                if (0 == (vec = symtab_store_.get_vector(symbol)))
+                {
+                    set_error(
+                              make_error(parser_error::e_syntax,
+                                         current_token(),
+                                         "ERR103 - Symbol '" + symbol+ " not a vector"));
+                    
+                    return error_node();
+                }
+            }
             else
+                vec = se.vec_node;
+            
+            expression_node_ptr index_expr = error_node();
+            
+            next_token();
+            
+            if (!token_is(token_t::e_lsqrbracket))
             {
-               details::free_node(*node_allocator_,result);
-               details::free_all_nodes(*node_allocator_,arg_list);
-               return error_node();
+                return node_allocator_.allocate<vector_node_t>(vec);
             }
-         }
-
-         inline expression_node_ptr string_function_call(igeneric_function_t* gf,
-                                                          std::vector<expression_node_ptr>& arg_list,
-                                                          const std::size_t& param_seq_index = std::numeric_limits<std::size_t>::max())
-         {
-            if (!all_nodes_valid(arg_list))
+            else if (token_is(token_t::e_rsqrbracket))
             {
-               details::free_all_nodes(*node_allocator_,arg_list);
-               return error_node();
+                return expression_generator_(T(vec->size()));
             }
-
-            typedef details::string_function_node      <Type,igeneric_function_t> alloc_type1;
-            typedef details::multimode_strfunction_node<Type,igeneric_function_t> alloc_type2;
-
-            const std::size_t no_psi = std::numeric_limits<std::size_t>::max();
-
-            expression_node_ptr result = error_node();
-
-            if (no_psi == param_seq_index)
-               result = node_allocator_->allocate<alloc_type1>(gf,arg_list);
-            else
-               result = node_allocator_->allocate<alloc_type2>(gf,param_seq_index,arg_list);
-
-            alloc_type1* strfunc_node_ptr = static_cast<alloc_type1*>(result);
-
-            if (
-                 !arg_list.empty()     &&
-                 !gf->has_side_effects &&
-                 is_constant_foldable(arg_list)
-               )
-            {
-               strfunc_node_ptr->init_branches();
-               Type v = result->value();
-               details::free_node(*node_allocator_,result);
-               return node_allocator_->allocate<literal_node_t>(v);
-            }
-            else if (strfunc_node_ptr->init_branches())
-               return result;
-            else
+            else if (0 == (index_expr = parse_expression()))
             {
-               details::free_node(*node_allocator_,result);
-               details::free_all_nodes(*node_allocator_,arg_list);
-               return error_node();
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR104 - Failed to parse index for vector: '" + symbol + "'"));
+                
+                return error_node();
             }
-         }
-
-         inline expression_node_ptr vector_element(const std::string& symbol,
-                                                   vector_holder_ptr vector_base,
-                                                   expression_node_ptr index)
-         {
-            expression_node_ptr result = error_node();
-
-            if (details::is_constant_node(index))
+            else if (!token_is(token_t::e_rsqrbracket))
             {
-               std::size_t i = static_cast<std::size_t>(details::numeric::to_int64(index->value()));
-               details::free_node(*node_allocator_,index);
-               Type* v = (*vector_base)[i];
-
-               scope_element& se = parser_->sem_.get_element(symbol,i);
-
-               if (se.index == i)
-               {
-                  result = se.var_node;
-               }
-               else
-               {
-                  scope_element nse;
-                  nse.name     = symbol;
-                  nse.type     = scope_element::e_vecelem;
-                  nse.index    = i;
-                  nse.depth    = parser_->scope_depth_;
-                  nse.data     = 0;
-                  nse.var_node = new variable_node_t((*v));
-
-                  if (!parser_->sem_.add_element(nse))
-                  {
-                     parser_->set_synthesis_error("Failed to add new local vector element to SEM [1]");
-                     result = error_node();
-                  }
-                  else
-                     exprtk_debug(("vector_element() - INFO - Added new local vector element: %s\n",nse.name.c_str()));
-
-                  result = nse.var_node;
-               }
-            }
-            else
-               result = node_allocator_->allocate<details::vector_elem_node<Type> >(index,(*vector_base)[0]);
-
-            return result;
-         }
-
-      private:
-
-         template <std::size_t N, typename NodePtr>
-         inline bool is_constant_foldable(NodePtr (&b)[N]) const
-         {
-            for (std::size_t i = 0; i < N; ++i)
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR105 - Expected ']' for index of vector: '" + symbol + "'"));
+                
+                free_node(node_allocator_,index_expr);
+                
+                return error_node();
+            }
+            
+            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)
+        {
+            std::vector<expression_node_ptr> arg_list;
+            expression_node_ptr result = error_node();
+            
+            scoped_vec_delete<expression_node_t> sdd(*this,arg_list);
+            
+            next_token();
+            
+            if (token_is(token_t::e_lbracket))
             {
-               if (0 == b[i])
-                  return false;
-               else if (!details::is_constant_node(b[i]))
-                  return false;
+                if (token_is(token_t::e_rbracket))
+                {
+                    if (!vararg_function->allow_zero_parameters())
+                    {
+                        set_error(
+                                  make_error(parser_error::e_syntax,
+                                             current_token(),
+                                             "ERR106 - Zero parameter call to vararg function: "
+                                             + vararg_function_name + " not allowed"));
+                        
+                        return error_node();
+                    }
+                }
+                else
+                {
+                    for ( ; ; )
+                    {
+                        expression_node_ptr arg = parse_expression();
+                        
+                        if (0 == arg)
+                            return error_node();
+                        else
+                            arg_list.push_back(arg);
+                        
+                        if (token_is(token_t::e_rbracket))
+                            break;
+                        else if (!token_is(token_t::e_comma))
+                        {
+                            set_error(
+                                      make_error(parser_error::e_syntax,
+                                                 current_token(),
+                                                 "ERR107 - Expected ',' for call to vararg function: "
+                                                 + vararg_function_name));
+                            
+                            return error_node();
+                        }
+                    }
+                }
             }
-
-            return true;
-         }
-
-         template <typename NodePtr,
-                   typename Allocator,
-                   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)
+            else if (!vararg_function->allow_zero_parameters())
             {
-               if (0 == b[i])
-                  return false;
-               else if (!details::is_constant_node(b[i]))
-                  return false;
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR108 - Zero parameter call to vararg function: "
+                                     + vararg_function_name + " not allowed"));
+                
+                return error_node();
             }
-
-            return true;
-         }
-
-         void lodge_assignment(symbol_type cst, expression_node_ptr node)
-         {
-            if (!parser_->dec_.collect_assignments())
-               return;
-
-            std::string symbol_name;
-
-            switch (cst)
+            
+            if (arg_list.size() < vararg_function->min_num_args())
             {
-               case e_st_variable : symbol_name = parser_->symbol_table_
-                                                     .get_variable_name(node);
-                                    break;
-
-               case e_st_string   : symbol_name = parser_->symbol_table_
-                                                     .get_stringvar_name(node);
-                                    break;
-
-               case e_st_vector   : {
-                                       typedef details::vector_holder<T> vector_holder_t;
-
-                                       vector_holder_t& vh = static_cast<vector_node_t*>(node)->ref();
-
-                                       symbol_name = parser_->symbol_table_.get_vector_name(&vh);
-                                    }
-                                    break;
-
-               default            : return;
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR109 - 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"));
+                
+                return error_node();
             }
-
-            parser_->dec_.add_assignment(symbol_name,cst);
-         }
-
-         inline expression_node_ptr synthesize_assignment_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
-         {
-            if (details::is_variable_node(branch[0]))
+            else if (arg_list.size() > vararg_function->max_num_args())
             {
-               lodge_assignment(e_st_variable,branch[0]);
-
-               return synthesize_expression<assignment_node_t,2>(operation,branch);
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR110 - 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"));
+                
+                return error_node();
+            }
+            
+            result = expression_generator_.vararg_function_call(vararg_function,arg_list);
+            
+            sdd.delete_ptr = (0 == result);
+            
+            return result;
+        }
+        
+        class type_checker
+        {
+        public:
+            
+            typedef parser<T> parser_t;
+            typedef std::vector<std::string> param_seq_list_t;
+            
+            type_checker(parser_t& p,
+                         const std::string& func_name,
+                         const std::string& param_seq)
+            : invalid_state_(true),
+            parser_(p),
+            function_name_(func_name)
+            {
+                split(param_seq);
+            }
+            
+            bool verify(const std::string& param_seq, std::size_t& pseq_index)
+            {
+                if (param_seq_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)
+                {
+                    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);
+                    
+                    if (result)
+                    {
+                        pseq_index = i;
+                        return true;
+                    }
+                    else
+                        error_list.push_back(std::make_pair(diff_index,diff_value));
+                }
+                
+                if (1 == error_list.size())
+                {
+                    parser_.
+                    set_error(
+                              make_error(parser_error::e_syntax,
+                                         parser_.current_token(),
+                                         "ERR111 - Failed parameter type check for function '" + function_name_ + "', "
+                                         "Expected '" + param_seq_list_[0] + "'  call set: '" + param_seq +"'"));
+                }
+                else
+                {
+                    // find first with largest diff_index;
+                    std::size_t max_diff_index = 0;
+                    
+                    for (std::size_t i = 1; i < error_list.size(); ++i)
+                    {
+                        if (error_list[i].first > error_list[max_diff_index].first)
+                        {
+                            max_diff_index = i;
+                        }
+                    }
+                    
+                    parser_.
+                    set_error(
+                              make_error(parser_error::e_syntax,
+                                         parser_.current_token(),
+                                         "ERR112 - Failed parameter type check for function '" + function_name_ + "', "
+                                         "Best match: '" + param_seq_list_[max_diff_index] + "'  call set: '" + param_seq +"'"));
+                }
+                
+                return false;
+            }
+            
+            std::size_t paramseq_count() const
+            {
+                return param_seq_list_.size();
+            }
+            
+            std::string paramseq(const std::size_t& index) const
+            {
+                return param_seq_list_[index];
+            }
+            
+            bool invalid() const
+            {
+                return !invalid_state_;
+            }
+            
+            bool allow_zero_parameters() const
+            {
+                return
+                param_seq_list_.end() != std::find(param_seq_list_.begin(),
+                                                   param_seq_list_.end(),
+                                                   "Z");
+            }
+            
+        private:
+            
+            void split(const std::string& s)
+            {
+                if (s.empty())
+                    return;
+                
+                std::size_t start = 0;
+                std::size_t end   = 0;
+                
+                param_seq_list_t param_seq_list;
+                
+                struct token_validator
+                {
+                    static inline bool process(const std::string& str,
+                                               std::size_t s, std::size_t e,
+                                               param_seq_list_t& psl)
+                    {
+                        if (
+                            (e - s) &&
+                            (std::string::npos == str.find("?*")) &&
+                            (std::string::npos == str.find("**"))
+                            )
+                        {
+                            const std::string curr_str = str.substr(s,e - s);
+                            
+                            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;
+                            }
+                        }
+                        
+                        return false;
+                    }
+                };
+                
+                while (std::string::npos != (end = s.find('|',start)))
+                {
+                    if (!token_validator::process(s,start,end,param_seq_list))
+                    {
+                        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(),
+                                             "ERR113 - Invalid parameter sequence of '" + err_param_seq +
+                                             "'  for function: " + function_name_));
+                        
+                        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
+                    {
+                        const std::string err_param_seq = s.substr(start,s.size() - start);
+                        
+                        parser_.
+                        set_error(
+                                  make_error(parser_error::e_syntax,
+                                             parser_.current_token(),
+                                             "ERR114 - Invalid parameter sequence of '" + err_param_seq +
+                                             "'  for function: " + function_name_));
+                        return;
+                    }
+                }
+            }
+            
+            type_checker(const type_checker&);
+            type_checker& operator=(const type_checker&);
+            
+            bool invalid_state_;
+            parser_t& parser_;
+            std::string function_name_;
+            param_seq_list_t param_seq_list_;
+        };
+        
+        inline expression_node_ptr parse_generic_function_call(igeneric_function<T>* function, const std::string& function_name)
+        {
+            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 (tc.invalid())
+            {
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR115 - Type checker instantiation failure for generic function: " + function_name));
+                
+                return error_node();
             }
-            else if (details::is_vector_elem_node(branch[0]))
-               return synthesize_expression<assignment_vec_elem_node_t,2>(operation,branch);
-            else if (details::is_string_node(branch[0]))
+            
+            if (
+                !function->parameter_sequence.empty() &&
+                function->allow_zero_parameters    () &&
+                !tc      .allow_zero_parameters    ()
+                )
             {
-               lodge_assignment(e_st_string,branch[0]);
-
-               return synthesize_expression<assignment_string_node_t,2>(operation,branch);
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR116 - Mismatch in zero parameter condition for generic function: "
+                                     + function_name));
+                
+                return error_node();
             }
-            else if (details::is_string_range_node(branch[0]))
+            
+            if (token_is(token_t::e_lbracket))
             {
-               lodge_assignment(e_st_string,branch[0]);
-
-               return synthesize_expression<assignment_string_range_node_t,2>(operation,branch);
+                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(),
+                                             "ERR117 - Zero parameter call to generic function: "
+                                             + function_name + " not allowed"));
+                        
+                        return error_node();
+                    }
+                }
+                else
+                {
+                    for ( ; ; )
+                    {
+                        expression_node_ptr arg = parse_expression();
+                        
+                        if (0 == arg)
+                            return error_node();
+                        
+                        if (is_ivector_node(arg))
+                            param_type_list += 'V';
+                        else if (is_generally_string_node(arg))
+                            param_type_list += 'S';
+                        else // Everything else is assumed to be a scalar returning expression
+                            param_type_list += 'T';
+                        
+                        arg_list.push_back(arg);
+                        
+                        if (token_is(token_t::e_rbracket))
+                            break;
+                        else if (!token_is(token_t::e_comma))
+                        {
+                            set_error(
+                                      make_error(parser_error::e_syntax,
+                                                 current_token(),
+                                                 "ERR118 - Expected ',' for call to generic function: " + function_name));
+                            
+                            return error_node();
+                        }
+                    }
+                }
             }
-            else if (details::is_vector_node(branch[0]))
+            else if (
+                     !function->parameter_sequence.empty() &&
+                     function->allow_zero_parameters    () &&
+                     !tc      .allow_zero_parameters    ()
+                     )
             {
-               lodge_assignment(e_st_vector,branch[0]);
-
-               if (details::is_ivector_node(branch[1]))
-                  return synthesize_expression<assignment_vecvec_node_t,2>(operation,branch);
-              else
-                  return synthesize_expression<assignment_vec_node_t,2>(operation,branch);
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR119 - Zero parameter call to generic function: "
+                                     + function_name + " not allowed"));
+                
+                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(),
+                                     "ERR120 - Expected ',' for call to generic function: " + function_name));
+                
+                return error_node();
             }
+            
+            expression_node_ptr result = error_node();
+            
+            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);
+            
+            sdd.delete_ptr = (0 == result);
+            
+            return result;
+        }
+        
+        inline expression_node_ptr parse_string_function_call(igeneric_function<T>* function, const std::string& function_name)
+        {
+            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())
+                )
             {
-               parser_->set_synthesis_error("Invalid assignment operation.[1]");
-
-               return error_node();
+                return error_node();
             }
-         }
-
-         inline expression_node_ptr synthesize_assignment_operation_expression(const details::operator_type& operation,
-                                                                               expression_node_ptr (&branch)[2])
-         {
-            if (details::is_variable_node(branch[0]))
+            
+            if (token_is(token_t::e_lbracket))
             {
-               lodge_assignment(e_st_variable,branch[0]);
-
-               switch (operation)
-               {
-                  #define case_stmt(op0,op1)                                                                  \
-                  case op0 : return node_allocator_->                                                         \
-                                template allocate_rrr<typename details::assignment_op_node<Type,op1<Type> > > \
-                                   (operation,branch[0],branch[1]);                                           \
-
-                  case_stmt(details::e_addass,details::add_op)
-                  case_stmt(details::e_subass,details::sub_op)
-                  case_stmt(details::e_mulass,details::mul_op)
-                  case_stmt(details::e_divass,details::div_op)
-                  case_stmt(details::e_modass,details::mod_op)
-                  #undef case_stmt
-                  default : return error_node();
-               }
-            }
-            else if (details::is_vector_elem_node(branch[0]))
-            {
-               switch (operation)
-               {
-                  #define case_stmt(op0,op1)                                                                            \
-                  case op0 : return node_allocator_->                                                                   \
-                                 template allocate_rrr<typename details::assignment_vec_elem_op_node<Type,op1<Type> > > \
-                                    (operation,branch[0],branch[1]);                                                    \
-
-                  case_stmt(details::e_addass,details::add_op)
-                  case_stmt(details::e_subass,details::sub_op)
-                  case_stmt(details::e_mulass,details::mul_op)
-                  case_stmt(details::e_divass,details::div_op)
-                  case_stmt(details::e_modass,details::mod_op)
-                  #undef case_stmt
-                  default : return error_node();
-               }
-            }
-            else if (details::is_vector_node(branch[0]))
-            {
-               lodge_assignment(e_st_vector,branch[0]);
-
-               if (details::is_ivector_node(branch[1]))
-               {
-                  switch (operation)
-                  {
-                     #define case_stmt(op0,op1)                                                                         \
-                     case op0 : return node_allocator_->                                                                \
-                                   template allocate_rrr<typename details::assignment_vecvec_op_node<Type,op1<Type> > > \
-                                      (operation,branch[0],branch[1]);                                                  \
-
-                     case_stmt(details::e_addass,details::add_op)
-                     case_stmt(details::e_subass,details::sub_op)
-                     case_stmt(details::e_mulass,details::mul_op)
-                     case_stmt(details::e_divass,details::div_op)
-                     case_stmt(details::e_modass,details::mod_op)
-                     #undef case_stmt
-                     default : return error_node();
-                  }
-               }
-               else
-               {
-                  switch (operation)
-                  {
-                     #define case_stmt(op0,op1)                                                                      \
-                     case op0 : return node_allocator_->                                                             \
-                                   template allocate_rrr<typename details::assignment_vec_op_node<Type,op1<Type> > > \
-                                      (operation,branch[0],branch[1]);                                               \
-
-                     case_stmt(details::e_addass,details::add_op)
-                     case_stmt(details::e_subass,details::sub_op)
-                     case_stmt(details::e_mulass,details::mul_op)
-                     case_stmt(details::e_divass,details::div_op)
-                     case_stmt(details::e_modass,details::mod_op)
-                     #undef case_stmt
-                     default : return error_node();
-                  }
-               }
+                if (!token_is(token_t::e_rbracket))
+                {
+                    for ( ; ; )
+                    {
+                        expression_node_ptr arg = parse_expression();
+                        
+                        if (0 == arg)
+                            return error_node();
+                        
+                        if (is_ivector_node(arg))
+                            param_type_list += 'V';
+                        else if (is_generally_string_node(arg))
+                            param_type_list += 'S';
+                        else // Everything else is a scalar returning expression
+                            param_type_list += 'T';
+                        
+                        arg_list.push_back(arg);
+                        
+                        if (token_is(token_t::e_rbracket))
+                            break;
+                        else if (!token_is(token_t::e_comma))
+                        {
+                            set_error(
+                                      make_error(parser_error::e_syntax,
+                                                 current_token(),
+                                                 "ERR121 - Expected ',' for call to string function: " + function_name));
+                            
+                            return error_node();
+                        }
+                    }
+                }
             }
-            else if (
-                      (details::e_addass == operation) &&
-                      details::is_string_node(branch[0])
-                    )
+            
+            std::size_t param_seq_index = 0;
+            
+            if (!tc.verify(param_type_list, param_seq_index))
             {
-               typedef details::assignment_string_node<T,details::asn_addassignment> addass_t;
-
-               lodge_assignment(e_st_string,branch[0]);
-
-               return synthesize_expression<addass_t,2>(operation,branch);
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR122 - Expected ',' for call to string function: " + function_name));
+                
+                return error_node();
             }
+            
+            expression_node_ptr result = error_node();
+            
+            if (tc.paramseq_count() <= 1)
+                result = expression_generator_
+                .string_function_call(function,arg_list);
             else
-            {
-               parser_->set_synthesis_error("Invalid assignment operation[2]");
-
-               return error_node();
-            }
-         }
-
-         inline expression_node_ptr synthesize_veceqineq_operation_expression(const details::operator_type& operation,
-                                                                              expression_node_ptr (&branch)[2])
-         {
-            const bool is_b0_ivec = details::is_ivector_node(branch[0]);
-            const bool is_b1_ivec = details::is_ivector_node(branch[1]);
-
-            if (is_b0_ivec && is_b1_ivec)
-            {
-               switch (operation)
-               {
-                  #define case_stmt(op0,op1)                                                                  \
-                  case op0 : return node_allocator_->                                                         \
-                                template allocate_rrr<typename details::eqineq_vecvec_node<Type,op1<Type> > > \
-                                   (operation,branch[0],branch[1]);                                           \
-
-                  case_stmt(details::  e_lt,details::  lt_op)
-                  case_stmt(details:: e_lte,details:: lte_op)
-                  case_stmt(details::  e_gt,details::  gt_op)
-                  case_stmt(details:: e_gte,details:: gte_op)
-                  case_stmt(details::  e_eq,details::  eq_op)
-                  case_stmt(details::  e_ne,details::  ne_op)
-                  #undef case_stmt
-                  default : return error_node();
-               }
-            }
-            else if (is_b0_ivec && !is_b1_ivec)
-            {
-               switch (operation)
-               {
-                  #define case_stmt(op0,op1)                                                                  \
-                  case op0 : return node_allocator_->                                                         \
-                                template allocate_rrr<typename details::eqineq_vecval_node<Type,op1<Type> > > \
-                                   (operation,branch[0],branch[1]);                                           \
-
-                  case_stmt(details::  e_lt,details::  lt_op)
-                  case_stmt(details:: e_lte,details:: lte_op)
-                  case_stmt(details::  e_gt,details::  gt_op)
-                  case_stmt(details:: e_gte,details:: gte_op)
-                  case_stmt(details::  e_eq,details::  eq_op)
-                  case_stmt(details::  e_ne,details::  ne_op)
-                  #undef case_stmt
-                  default : return error_node();
-               }
-            }
-            else if (!is_b0_ivec && is_b1_ivec)
-            {
-               switch (operation)
-               {
-                  #define case_stmt(op0,op1)                                                                  \
-                  case op0 : return node_allocator_->                                                         \
-                                template allocate_rrr<typename details::eqineq_valvec_node<Type,op1<Type> > > \
-                                   (operation,branch[0],branch[1]);                                           \
-
-                  case_stmt(details::  e_lt,details::  lt_op)
-                  case_stmt(details:: e_lte,details:: lte_op)
-                  case_stmt(details::  e_gt,details::  gt_op)
-                  case_stmt(details:: e_gte,details:: gte_op)
-                  case_stmt(details::  e_eq,details::  eq_op)
-                  case_stmt(details::  e_ne,details::  ne_op)
-                  #undef case_stmt
-                  default : return error_node();
-               }
-            }
-            else
-               return error_node();
-         }
-
-         inline expression_node_ptr synthesize_vecarithmetic_operation_expression(const details::operator_type& operation,
-                                                                                  expression_node_ptr (&branch)[2])
-         {
-            const bool is_b0_ivec = details::is_ivector_node(branch[0]);
-            const bool is_b1_ivec = details::is_ivector_node(branch[1]);
-
-            #define vector_ops                        \
-            case_stmt(details::e_add,details::add_op) \
-            case_stmt(details::e_sub,details::sub_op) \
-            case_stmt(details::e_mul,details::mul_op) \
-            case_stmt(details::e_div,details::div_op) \
-            case_stmt(details::e_mod,details::mod_op) \
-
-            if (is_b0_ivec && is_b1_ivec)
-            {
-               switch (operation)
-               {
-                  #define case_stmt(op0,op1)                                                                    \
-                  case op0 : return node_allocator_->                                                           \
-                                template allocate_rrr<typename details::vecarith_vecvec_node<Type,op1<Type> > > \
-                                   (operation,branch[0],branch[1]);                                             \
-
-                  vector_ops
-                  case_stmt(details::e_pow,details:: pow_op)
-                  #undef case_stmt
-                  default : return error_node();
-               }
-            }
-            else if (is_b0_ivec && !is_b1_ivec)
-            {
-               switch (operation)
-               {
-                  #define case_stmt(op0,op1)                                                                    \
-                  case op0 : return node_allocator_->                                                           \
-                                template allocate_rrr<typename details::vecarith_vecval_node<Type,op1<Type> > > \
-                                   (operation,branch[0],branch[1]);                                             \
-
-                  vector_ops
-                  case_stmt(details::e_pow,details:: pow_op)
-                  #undef case_stmt
-                  default : return error_node();
-               }
-            }
-            else if (!is_b0_ivec && is_b1_ivec)
-            {
-               switch (operation)
-               {
-                  #define case_stmt(op0,op1)                                                                    \
-                  case op0 : return node_allocator_->                                                           \
-                                template allocate_rrr<typename details::vecarith_valvec_node<Type,op1<Type> > > \
-                                   (operation,branch[0],branch[1]);                                             \
-
-                  vector_ops
-                  #undef case_stmt
-                  default : return error_node();
-               }
+                result = expression_generator_
+                .string_function_call(function,arg_list,param_seq_index);
+            
+            sdd.delete_ptr = (0 == result);
+            
+            return result;
+        }
+        
+        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)
+            {
+                expression_node_ptr branch[NumberOfParameters];
+                expression_node_ptr result  = error_node();
+                std::fill_n(branch,NumberOfParameters,reinterpret_cast<expression_node_ptr>(0));
+                scoped_delete<expression_node_t,NumberOfParameters> sd(p,branch);
+                
+                p.next_token();
+                
+                if (!p.token_is(token_t::e_lbracket))
+                {
+                    p.set_error(
+                                make_error(parser_error::e_syntax,
+                                           p.current_token(),
+                                           "ERR123 - Expected '(' for special function"));
+                    
+                    return error_node();
+                }
+                
+                for (std::size_t i = 0; i < NumberOfParameters; ++i)
+                {
+                    branch[i] = p.parse_expression();
+                    
+                    if (0 == branch[i])
+                    {
+                        return p.error_node();
+                    }
+                    else if (i < (NumberOfParameters - 1))
+                    {
+                        if (!p.token_is(token_t::e_comma))
+                        {
+                            p.set_error(
+                                        make_error(parser_error::e_syntax,
+                                                   p.current_token(),
+                                                   "ERR124 - Expected ',' before next parameter of special function"));
+                            
+                            return p.error_node();
+                        }
+                    }
+                }
+                
+                if (!p.token_is(token_t::e_rbracket))
+                    return p.error_node();
+                else
+                    result = p.expression_generator_.special_function(opt_type,branch);
+                
+                sd.delete_ptr = (0 == result);
+                
+                return result;
             }
-            else
-               return error_node();
-
-            #undef vector_ops
-         }
-
-         inline expression_node_ptr synthesize_swap_expression(expression_node_ptr (&branch)[2])
-         {
-            const bool v0_is_ivar = details::is_ivariable_node(branch[0]);
-            const bool v1_is_ivar = details::is_ivariable_node(branch[1]);
-
-            const bool v0_is_ivec = details::is_ivector_node(branch[0]);
-            const bool v1_is_ivec = details::is_ivector_node(branch[1]);
-
-            const bool v0_is_str = details::is_generally_string_node(branch[0]);
-            const bool v1_is_str = details::is_generally_string_node(branch[1]);
-
-            if (v0_is_ivar && v1_is_ivar)
+        };
+        
+        inline expression_node_ptr parse_special_function()
+        {
+            // 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])
+                )
+            {
+                set_error(
+                          make_error(parser_error::e_token,
+                                     current_token(),
+                                     "ERR125 - Invalid special function[1]: " + current_token().value));
+                
+                return error_node();
+            }
+            
+            const unsigned int id = (current_token().value[2] - '0') * 10 + (current_token().value[3] - '0');
+            
+            if (id >= details::e_sffinal)
+            {
+                set_error(
+                          make_error(parser_error::e_token,
+                                     current_token(),
+                                     "ERR126 - Invalid special function[2]: " + current_token().value));
+                
+                return error_node();
+            }
+            
+            const std::size_t sf_3_to_4 = details::e_sf48;
+            const details::operator_type opt_type = details::operator_type(id + 1000);
+            const std::size_t NumberOfParameters = (id < (sf_3_to_4 - 1000)) ? 3 : 4;
+            
+            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);
+                default : return error_node();
+            }
+        }
+        
+        inline expression_node_ptr parse_null_statement()
+        {
+            next_token();
+            return node_allocator_.allocate<details::null_node<T> >();
+        }
+        
+#ifndef exprtk_disable_break_continue
+        inline expression_node_ptr parse_break_statement()
+        {
+            if (state_.parsing_break_stmt)
+            {
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR127 - Break call within a break call is not allowed"));
+                
+                return error_node();
+            }
+            
+            scoped_bool_negator sbn(state_.parsing_break_stmt);
+            
+            if (!brkcnt_list_.empty())
             {
-               typedef details::variable_node<T>* variable_node_ptr;
-
-               variable_node_ptr v0 = variable_node_ptr(0);
-               variable_node_ptr v1 = variable_node_ptr(0);
-
-               if (
-                    (0 != (v0 = dynamic_cast<variable_node_ptr>(branch[0]))) &&
-                    (0 != (v1 = dynamic_cast<variable_node_ptr>(branch[1])))
-                  )
-               {
-                  return node_allocator_->allocate<details::swap_node<T> >(v0,v1);
-               }
-               else
-                  return node_allocator_->allocate<details::swap_generic_node<T> >(branch[0],branch[1]);
+                next_token();
+                
+                brkcnt_list_.front() = true;
+                
+                expression_node_ptr return_expr = error_node();
+                
+                if (token_is(token_t::e_lsqrbracket))
+                {
+                    if (0 == (return_expr = parse_expression()))
+                    {
+                        set_error(
+                                  make_error(parser_error::e_syntax,
+                                             current_token(),
+                                             "ERR128 - Failed to parse return expression for 'break' statement"));
+                        
+                        return error_node();
+                    }
+                    else if (!token_is(token_t::e_rsqrbracket))
+                    {
+                        set_error(
+                                  make_error(parser_error::e_syntax,
+                                             current_token(),
+                                             "ERR129 - Expected ']' at the completion of break's return expression"));
+                        
+                        free_node(node_allocator_,return_expr);
+                        
+                        return error_node();
+                    }
+                }
+                
+                state_.activate_side_effect("parse_break_statement()");
+                
+                return node_allocator_.allocate<details::break_node<T> >(return_expr);
             }
-            else if (v0_is_ivec && v1_is_ivec)
+            else
             {
-               return node_allocator_->allocate<details::swap_vecvec_node<T> >(branch[0],branch[1]);
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR130 - Invalid use of 'break', allowed only in the scope of a loop"));
             }
-            else if (v0_is_str && v1_is_str)
+            
+            return error_node();
+        }
+        
+        inline expression_node_ptr parse_continue_statement()
+        {
+            if (!brkcnt_list_.empty())
             {
-               return node_allocator_->allocate<details::swap_string_node<T> >(branch[0],branch[1]);
+                next_token();
+                
+                brkcnt_list_.front() = true;
+                state_.activate_side_effect("parse_continue_statement()");
+                
+                return node_allocator_.allocate<details::continue_node<T> >();
             }
             else
             {
-               parser_->set_synthesis_error("Only variables, strings, vectors or vector elements can be swapped");
-
-               return error_node();
-            }
-         }
-
-         #ifndef exprtk_disable_sc_andor
-         inline expression_node_ptr synthesize_shortcircuit_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
-         {
-            expression_node_ptr result = error_node();
-
-            if (details::is_constant_node(branch[0]))
-            {
-               if (
-                    (details::e_scand == operation) &&
-                    std::equal_to<T>()(T(0),branch[0]->value())
-                  )
-                  result = node_allocator_->allocate_c<literal_node_t>(T(0));
-               else if (
-                         (details::e_scor == operation) &&
-                         std::not_equal_to<T>()(T(0),branch[0]->value())
-                       )
-                  result = node_allocator_->allocate_c<literal_node_t>(T(1));
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR131 - Invalid use of 'continue', allowed only in the scope of a loop"));
+                
+                return error_node();
             }
-
-            if (details::is_constant_node(branch[1]) && (0 == result))
-            {
-               if (
-                    (details::e_scand == operation) &&
-                    std::equal_to<T>()(T(0),branch[1]->value())
-                  )
-                  result = node_allocator_->allocate_c<literal_node_t>(T(0));
-               else if (
-                         (details::e_scor == operation) &&
-                         std::not_equal_to<T>()(T(0),branch[1]->value())
-                       )
-                  result = node_allocator_->allocate_c<literal_node_t>(T(1));
+        }
+#endif
+        
+        inline expression_node_ptr parse_define_vector_statement(const std::string& vec_name)
+        {
+            expression_node_ptr size_expr = error_node();
+            
+            if (!token_is(token_t::e_lsqrbracket))
+            {
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR132 - Expected '[' as part of vector size definition"));
+                
+                return error_node();
             }
-
-            if (result)
+            else if (0 == (size_expr = parse_expression()))
             {
-               free_node(*node_allocator_,branch[0]);
-               free_node(*node_allocator_,branch[1]);
-
-               return result;
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR133 - Failed to determine size of vector '" + vec_name + "'"));
+                
+                return error_node();
             }
-            else if (details::e_scand == operation)
-               return synthesize_expression<scand_node_t,2>(operation,branch);
-            else if (details::e_scor == operation)
-               return synthesize_expression<scor_node_t,2>(operation,branch);
-            else
-               return error_node();
-         }
-         #else
-         inline expression_node_ptr synthesize_shortcircuit_expression(const details::operator_type&, expression_node_ptr (&)[2])
-         {
-            return error_node();
-         }
-         #endif
-
-         #define basic_opr_switch_statements       \
-         case_stmt(details::e_add,details::add_op) \
-         case_stmt(details::e_sub,details::sub_op) \
-         case_stmt(details::e_mul,details::mul_op) \
-         case_stmt(details::e_div,details::div_op) \
-         case_stmt(details::e_mod,details::mod_op) \
-         case_stmt(details::e_pow,details::pow_op) \
-
-         #define extended_opr_switch_statements      \
-         case_stmt(details::  e_lt,details::  lt_op) \
-         case_stmt(details:: e_lte,details:: lte_op) \
-         case_stmt(details::  e_gt,details::  gt_op) \
-         case_stmt(details:: e_gte,details:: gte_op) \
-         case_stmt(details::  e_eq,details::  eq_op) \
-         case_stmt(details::  e_ne,details::  ne_op) \
-         case_stmt(details:: e_and,details:: and_op) \
-         case_stmt(details::e_nand,details::nand_op) \
-         case_stmt(details::  e_or,details::  or_op) \
-         case_stmt(details:: e_nor,details:: nor_op) \
-         case_stmt(details:: e_xor,details:: xor_op) \
-         case_stmt(details::e_xnor,details::xnor_op) \
-
-         #ifndef exprtk_disable_cardinal_pow_optimisation
-         template <template <typename,typename> class IPowNode>
-         inline expression_node_ptr cardinal_pow_optimization_impl(const T& v, const unsigned int& p)
-         {
-            switch (p)
-            {
-               #define case_stmt(cp)                                                     \
-               case cp : return node_allocator_->                                        \
-                            allocate<IPowNode<T,details::numeric::fast_exp<T,cp> > >(v); \
-
-               case_stmt( 1) case_stmt( 2) case_stmt( 3) case_stmt( 4)
-               case_stmt( 5) case_stmt( 6) case_stmt( 7) case_stmt( 8)
-               case_stmt( 9) case_stmt(10) case_stmt(11) case_stmt(12)
-               case_stmt(13) case_stmt(14) case_stmt(15) case_stmt(16)
-               case_stmt(17) case_stmt(18) case_stmt(19) case_stmt(20)
-               case_stmt(21) case_stmt(22) case_stmt(23) case_stmt(24)
-               case_stmt(25) case_stmt(26) case_stmt(27) case_stmt(28)
-               case_stmt(29) case_stmt(30) case_stmt(31) case_stmt(32)
-               case_stmt(33) case_stmt(34) case_stmt(35) case_stmt(36)
-               case_stmt(37) case_stmt(38) case_stmt(39) case_stmt(40)
-               case_stmt(41) case_stmt(42) case_stmt(43) case_stmt(44)
-               case_stmt(45) case_stmt(46) case_stmt(47) case_stmt(48)
-               case_stmt(49) case_stmt(50) case_stmt(51) case_stmt(52)
-               case_stmt(53) case_stmt(54) case_stmt(55) case_stmt(56)
-               case_stmt(57) case_stmt(58) case_stmt(59) case_stmt(60)
-               #undef case_stmt
-               default : return error_node();
-            }
-         }
-
-         inline expression_node_ptr cardinal_pow_optimization(const T& v, const T& c)
-         {
-            const bool not_recipricol = (c >= T(0));
-            const int p = details::numeric::to_int32(details::numeric::abs(c));
-
-            if (0 == p)
-               return node_allocator_->allocate_c<literal_node_t>(T(1));
-            else if (std::equal_to<T>()(T(2),c))
+            else if (!is_constant_node(size_expr))
             {
-               return node_allocator_->
-                  template allocate_rr<typename details::vov_node<Type,details::mul_op<Type> > >(v,v);
-            }
-            else
+                free_node(node_allocator_,size_expr);
+                
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR134 - Expected a literal number as size of vector '" + vec_name + "'"));
+                
+                return error_node();
+            }
+            
+            T vector_size = size_expr->value();
+            
+            free_node(node_allocator_,size_expr);
+            
+            if (
+                (vector_size <= T(0)) ||
+                std::not_equal_to<T>()
+                (T(0),vector_size - details::numeric::trunc(vector_size))
+                )
+            {
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR135 - Invalid vector size. Must be an integer greater than zero, size: " +
+                                     details::to_str(details::numeric::to_int32(vector_size))));
+                
+                return error_node();
+            }
+            
+            std::vector<expression_node_ptr> vec_initilizer_list;
+            
+            scoped_vec_delete<expression_node_t> svd(*this,vec_initilizer_list);
+            
+            bool single_value_initialiser = false;
+            bool vec_to_vec_initialiser   = false;
+            bool null_initialisation      = false;
+            
+            if (!token_is(token_t::e_rsqrbracket))
             {
-               if (not_recipricol)
-                  return cardinal_pow_optimization_impl<details::ipow_node>(v,p);
-               else
-                  return cardinal_pow_optimization_impl<details::ipowinv_node>(v,p);
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR136 - Expected ']' as part of vector size definition"));
+                
+                return error_node();
             }
-         }
-
-         inline bool cardinal_pow_optimizable(const details::operator_type& operation, const T& c)
-         {
-            return (details::e_pow == operation) && (details::numeric::abs(c) <= T(60)) && details::numeric::is_integer(c);
-         }
-         #else
-         inline expression_node_ptr cardinal_pow_optimization(T&, const T&)
-         {
-            return error_node();
-         }
-
-         inline bool cardinal_pow_optimizable(const details::operator_type&, const T&)
-         {
-            return false;
-         }
-         #endif
-
-         struct synthesize_binary_ext_expression
-         {
-            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
-                                                      const details::operator_type& operation,
-                                                      expression_node_ptr (&branch)[2])
-            {
-               const bool left_neg  = is_neg_unary_node(branch[0]);
-               const bool right_neg = is_neg_unary_node(branch[1]);
-
-               if (left_neg && right_neg)
-               {
-                  if (
-                       (details::e_add == operation) ||
-                       (details::e_sub == operation) ||
-                       (details::e_mul == operation) ||
-                       (details::e_div == operation)
-                     )
-                  {
-                     if (
-                          !expr_gen.parser_->simplify_unary_negation_branch(branch[0]) ||
-                          !expr_gen.parser_->simplify_unary_negation_branch(branch[1])
-                        )
-                     {
-                        details::free_all_nodes(*expr_gen.node_allocator_,branch);
-
-                        return error_node();
-                     }
-                  }
-
-                  switch (operation)
-                  {
-                                           // -f(x + 1) + -g(y + 1) --> -(f(x + 1) + g(y + 1))
-                     case details::e_add : return expr_gen(details::e_neg,
-                                              expr_gen.node_allocator_->
-                                                 template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > >
-                                                    (branch[0],branch[1]));
-
-                                           // -f(x + 1) - -g(y + 1) --> g(y + 1) - f(x + 1)
-                     case details::e_sub : return expr_gen.node_allocator_->
-                                              template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > >
-                                                 (branch[1],branch[0]);
-
-                     default             : break;
-                  }
-               }
-               else if (left_neg && !right_neg)
-               {
-                  if (
-                       (details::e_add == operation) ||
-                       (details::e_sub == operation) ||
-                       (details::e_mul == operation) ||
-                       (details::e_div == operation)
-                     )
-                  {
-                     if (!expr_gen.parser_->simplify_unary_negation_branch(branch[0]))
-                     {
-                        details::free_all_nodes(*expr_gen.node_allocator_,branch);
-
+            else if (!token_is(token_t::e_eof))
+            {
+                if (!token_is(token_t::e_assign))
+                {
+                    set_error(
+                              make_error(parser_error::e_syntax,
+                                         current_token(),
+                                         "ERR137 - Expected ':=' as part of vector definition"));
+                    
+                    return error_node();
+                }
+                else if (token_is(token_t::e_lsqrbracket))
+                {
+                    expression_node_ptr initialiser = parse_expression();
+                    
+                    if (0 == initialiser)
+                    {
+                        set_error(
+                                  make_error(parser_error::e_syntax,
+                                             current_token(),
+                                             "ERR138 - Failed to parse single vector initialiser"));
+                        
                         return error_node();
-                     }
-
-                     switch (operation)
-                     {
-                                              // -f(x + 1) + g(y + 1) --> g(y + 1) - f(x + 1)
-                        case details::e_add : return expr_gen.node_allocator_->
-                                                 template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > >
-                                                   (branch[1],branch[0]);
-
-                                              // -f(x + 1) - g(y + 1) --> -(f(x + 1) + g(y + 1))
-                        case details::e_sub : return expr_gen(details::e_neg,
-                                                 expr_gen.node_allocator_->
-                                                    template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > >
-                                                       (branch[0],branch[1]));
-
-                                              // -f(x + 1) * g(y + 1) --> -(f(x + 1) * g(y + 1))
-                        case details::e_mul : return expr_gen(details::e_neg,
-                                                 expr_gen.node_allocator_->
-                                                    template allocate<typename details::binary_ext_node<Type,details::mul_op<Type> > >
-                                                       (branch[0],branch[1]));
-
-                                              // -f(x + 1) / g(y + 1) --> -(f(x + 1) / g(y + 1))
-                        case details::e_div : return expr_gen(details::e_neg,
-                                                 expr_gen.node_allocator_->
-                                                    template allocate<typename details::binary_ext_node<Type,details::div_op<Type> > >
-                                                       (branch[0],branch[1]));
-
-                        default             : return error_node();
-                     }
-                  }
-               }
-               else if (!left_neg && right_neg)
-               {
-                  if (
-                       (details::e_add == operation) ||
-                       (details::e_sub == operation) ||
-                       (details::e_mul == operation) ||
-                       (details::e_div == operation)
-                     )
-                  {
-                     if (!expr_gen.parser_->simplify_unary_negation_branch(branch[1]))
-                     {
-                        details::free_all_nodes(*expr_gen.node_allocator_,branch);
-
+                    }
+                    
+                    vec_initilizer_list.push_back(initialiser);
+                    
+                    if (!token_is(token_t::e_rsqrbracket))
+                    {
+                        set_error(
+                                  make_error(parser_error::e_syntax,
+                                             current_token(),
+                                             "ERR139 - Expected ']' to close single value vector initialiser"));
+                        
                         return error_node();
-                     }
-
-                     switch (operation)
-                     {
-                                              // f(x + 1) + -g(y + 1) --> f(x + 1) - g(y + 1)
-                        case details::e_add : return expr_gen.node_allocator_->
-                                                 template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > >
-                                                   (branch[0],branch[1]);
-
-                                              // f(x + 1) - - g(y + 1) --> f(x + 1) + g(y + 1)
-                        case details::e_sub : return expr_gen.node_allocator_->
-                                                 template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > >
-                                                   (branch[0],branch[1]);
-
-                                              // f(x + 1) * -g(y + 1) --> -(f(x + 1) * g(y + 1))
-                        case details::e_mul : return expr_gen(details::e_neg,
-                                                 expr_gen.node_allocator_->
-                                                    template allocate<typename details::binary_ext_node<Type,details::mul_op<Type> > >
-                                                       (branch[0],branch[1]));
-
-                                              // f(x + 1) / -g(y + 1) --> -(f(x + 1) / g(y + 1))
-                        case details::e_div : return expr_gen(details::e_neg,
-                                                 expr_gen.node_allocator_->
-                                                    template allocate<typename details::binary_ext_node<Type,details::div_op<Type> > >
-                                                       (branch[0],branch[1]));
-
-                        default             : return error_node();
-                     }
-                  }
-               }
-
-               switch (operation)
-               {
-                  #define case_stmt(op0,op1)                                                           \
-                  case op0 : return expr_gen.node_allocator_->                                         \
-                                template allocate<typename details::binary_ext_node<Type,op1<Type> > > \
-                                   (branch[0],branch[1]);                                              \
-
-                  basic_opr_switch_statements
-                  extended_opr_switch_statements
-                  #undef case_stmt
-                  default : return error_node();
-               }
-            }
-         };
-
-         struct synthesize_vob_expression
-         {
-            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
-                                                      const details::operator_type& operation,
-                                                      expression_node_ptr (&branch)[2])
-            {
-               const Type& v = static_cast<details::variable_node<Type>*>(branch[0])->ref();
-
-               #ifndef exprtk_disable_enhanced_features
-               if (details::is_sf3ext_node(branch[1]))
-               {
-                  expression_node_ptr result = error_node();
-
-                  if (synthesize_sf4ext_expression::template compile_right<vtype>(expr_gen,v,operation,branch[1],result))
-                  {
-                     free_node(*expr_gen.node_allocator_,branch[1]);
-                     return result;
-                  }
-               }
-               #endif
-
-               if (
-                    (details::e_mul == operation) ||
-                    (details::e_div == operation)
-                  )
-               {
-                  if (details::is_uv_node(branch[1]))
-                  {
-                     details::operator_type o = static_cast<details::uv_base_node<Type>*>(branch[1])->operation();
-
-                     if (details::e_neg == o)
-                     {
-                        const Type& v1 = static_cast<details::uv_base_node<Type>*>(branch[1])->v();
-
-                        free_node(*expr_gen.node_allocator_,branch[1]);
-
-                        switch (operation)
+                    }
+                    
+                    single_value_initialiser = true;
+                }
+                else if (!token_is(token_t::e_lcrlbracket))
+                {
+                    expression_node_ptr initialiser = error_node();
+                    
+                    // Is this a vector to vector assignment and initialisation?
+                    if (token_t::e_symbol == current_token().type)
+                    {
+                        // Is it a locally defined vector?
+                        scope_element& se = sem_.get_active_element(current_token().value);
+                        
+                        if (scope_element::e_vector == se.type)
                         {
-                           case details::e_mul : return expr_gen(details::e_neg,
-                                                    expr_gen.node_allocator_->
-                                                       template allocate_rr<typename details::
-                                                          vov_node<Type,details::mul_op<Type> > >(v,v1));
-
-                           case details::e_div : return expr_gen(details::e_neg,
-                                                    expr_gen.node_allocator_->
-                                                       template allocate_rr<typename details::
-                                                          vov_node<Type,details::div_op<Type> > >(v,v1));
-
-                           default             : break;
+                            if (0 != (initialiser = parse_expression()))
+                                vec_initilizer_list.push_back(initialiser);
+                            else
+                                return error_node();
                         }
-                     }
-                  }
-               }
-
-               switch (operation)
-               {
-                  #define case_stmt(op0,op1)                                                       \
-                  case op0 : return expr_gen.node_allocator_->                                     \
-                                template allocate_rc<typename details::vob_node<Type,op1<Type> > > \
-                                   (v,branch[1]);                                                  \
-
-                  basic_opr_switch_statements
-                  extended_opr_switch_statements
-                  #undef case_stmt
-                  default : return error_node();
-               }
-            }
-         };
-
-         struct synthesize_bov_expression
-         {
-            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
-                                                      const details::operator_type& operation,
-                                                      expression_node_ptr (&branch)[2])
-            {
-               const Type& v = static_cast<details::variable_node<Type>*>(branch[1])->ref();
-
-               #ifndef exprtk_disable_enhanced_features
-               if (details::is_sf3ext_node(branch[0]))
-               {
-                  expression_node_ptr result = error_node();
-
-                  if (synthesize_sf4ext_expression::template compile_left<vtype>(expr_gen,v,operation,branch[0],result))
-                  {
-                     free_node(*expr_gen.node_allocator_,branch[0]);
-                     return result;
-                  }
-               }
-               #endif
-
-               if (
-                    (details::e_add == operation) ||
-                    (details::e_sub == operation) ||
-                    (details::e_mul == operation) ||
-                    (details::e_div == operation)
-                  )
-               {
-                  if (details::is_uv_node(branch[0]))
-                  {
-                     details::operator_type o = static_cast<details::uv_base_node<Type>*>(branch[0])->operation();
-
-                     if (details::e_neg == o)
-                     {
-                        const Type& v0 = static_cast<details::uv_base_node<Type>*>(branch[0])->v();
-
-                        free_node(*expr_gen.node_allocator_,branch[0]);
-
-                        switch (operation)
+                        // Are we dealing with a user defined vector?
+                        else if (symtab_store_.is_vector(current_token().value))
                         {
-                           case details::e_add : return expr_gen.node_allocator_->
-                                                    template allocate_rr<typename details::
-                                                       vov_node<Type,details::sub_op<Type> > >(v,v0);
-
-                           case details::e_sub : return expr_gen(details::e_neg,
-                                                    expr_gen.node_allocator_->
-                                                       template allocate_rr<typename details::
-                                                          vov_node<Type,details::add_op<Type> > >(v0,v));
-
-                           case details::e_mul : return expr_gen(details::e_neg,
-                                                    expr_gen.node_allocator_->
-                                                       template allocate_rr<typename details::
-                                                          vov_node<Type,details::mul_op<Type> > >(v0,v));
-
-                           case details::e_div : return expr_gen(details::e_neg,
-                                                    expr_gen.node_allocator_->
-                                                       template allocate_rr<typename details::
-                                                          vov_node<Type,details::div_op<Type> > >(v0,v));
-                           default : break;
+                            lodge_symbol(current_token().value,e_st_vector);
+                            
+                            if (0 != (initialiser = parse_expression()))
+                                vec_initilizer_list.push_back(initialiser);
+                            else
+                                return error_node();
                         }
-                     }
-                  }
-               }
-
-               switch (operation)
-               {
-                  #define case_stmt(op0,op1)                                                       \
-                  case op0 : return expr_gen.node_allocator_->                                     \
-                                template allocate_cr<typename details::bov_node<Type,op1<Type> > > \
-                                   (branch[0],v);                                                  \
-
-                  basic_opr_switch_statements
-                  extended_opr_switch_statements
-                  #undef case_stmt
-                  default : return error_node();
-               }
-            }
-         };
-
-         struct synthesize_cob_expression
-         {
-            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
-                                                      const details::operator_type& operation,
-                                                      expression_node_ptr (&branch)[2])
-            {
-               const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value();
-               free_node(*expr_gen.node_allocator_,branch[0]);
-
-               if (details::is_cob_node(branch[1]))
-               {
-                  // Simplify expressions of the form:
-                  // 1. (1 * (2 * (3 * (4 * (5 * (6 * (7 * (8 * (9 + x))))))))) --> 40320 * (9 + x)
-                  // 2. (1 + (2 + (3 + (4 + (5 + (6 + (7 + (8 + (9 + x))))))))) --> 45 + x
-                  if (
-                       (operation == details::e_mul) ||
-                       (operation == details::e_add)
-                     )
-                  {
-                     details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]);
-
-                     if (operation == cobnode->operation())
-                     {
-                        switch (operation)
+                        // Are we dealing with a null initialisation vector definition?
+                        else if (token_is(token_t::e_symbol,"null"))
+                            null_initialisation = true;
+                    }
+                    
+                    if (!null_initialisation)
+                    {
+                        if (0 == initialiser)
                         {
-                           case details::e_add : cobnode->set_c(c + cobnode->c()); break;
-                           case details::e_mul : cobnode->set_c(c * cobnode->c()); break;
-                           default             : return error_node();
+                            set_error(
+                                      make_error(parser_error::e_syntax,
+                                                 current_token(),
+                                                 "ERR140 - Expected '{' as part of vector initialiser list"));
+                            
+                            return error_node();
                         }
-
-                        return cobnode;
-                     }
-                  }
-
-                  if (operation == details::e_mul)
-                  {
-                     details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]);
-                     details::operator_type cob_opr = cobnode->operation();
-
-                     if (
-                          (details::e_div == cob_opr) ||
-                          (details::e_mul == cob_opr)
-                        )
-                     {
-                        switch (cob_opr)
+                        else
+                            vec_to_vec_initialiser = true;
+                    }
+                }
+                else if (!token_is(token_t::e_rcrlbracket))
+                {
+                    for ( ; ; )
+                    {
+                        expression_node_ptr initialiser = parse_expression();
+                        
+                        if (0 == initialiser)
                         {
-                           case details::e_div : cobnode->set_c(c * cobnode->c()); break;
-                           case details::e_mul : cobnode->set_c(cobnode->c() / c); break;
-                           default             : return error_node();
+                            set_error(
+                                      make_error(parser_error::e_syntax,
+                                                 current_token(),
+                                                 "ERR141 - Expected '{' as part of vector initialiser list"));
+                            
+                            return error_node();
                         }
-
-                        return cobnode;
-                     }
-                  }
-                  else if (operation == details::e_div)
-                  {
-                     details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]);
-                     details::operator_type cob_opr = cobnode->operation();
-
-                     if (
-                          (details::e_div == cob_opr) ||
-                          (details::e_mul == cob_opr)
-                        )
-                     {
-                        details::expression_node<Type>* new_cobnode = error_node();
-
-                        switch (cob_opr)
+                        else
+                            vec_initilizer_list.push_back(initialiser);
+                        
+                        if (token_is(token_t::e_rcrlbracket))
+                            break;
+                        
+                        bool is_next_close = peek_token_is(token_t::e_rcrlbracket);
+                        
+                        if (!token_is(token_t::e_comma) && is_next_close)
                         {
-                           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));
-                                                 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));
-                                                 break;
-
-                           default             : return error_node();
+                            set_error(
+                                      make_error(parser_error::e_syntax,
+                                                 current_token(),
+                                                 "ERR142 - Expected ',' between vector initialisers"));
+                            
+                            return error_node();
                         }
-
-                        free_node(*expr_gen.node_allocator_,branch[1]);
-
-                        return new_cobnode;
-                     }
-                  }
-               }
-               #ifndef exprtk_disable_enhanced_features
-               else if (details::is_sf3ext_node(branch[1]))
-               {
-                  expression_node_ptr result = error_node();
-
-                  if (synthesize_sf4ext_expression::template compile_right<ctype>(expr_gen,c,operation,branch[1],result))
-                  {
-                     free_node(*expr_gen.node_allocator_,branch[1]);
-
-                     return result;
-                  }
-               }
-               #endif
-
-               switch (operation)
-               {
-                  #define case_stmt(op0,op1)                                                       \
-                  case op0 : return expr_gen.node_allocator_->                                     \
-                                template allocate_tt<typename details::cob_node<Type,op1<Type> > > \
-                                   (c,branch[1]);                                                  \
-
-                  basic_opr_switch_statements
-                  extended_opr_switch_statements
-                  #undef case_stmt
-                  default : return error_node();
-               }
+                        
+                        if (token_is(token_t::e_rcrlbracket))
+                            break;
+                    }
+                }
+                
+                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)
+                    )
+                {
+                    if (!token_is(token_t::e_eof))
+                    {
+                        set_error(
+                                  make_error(parser_error::e_syntax,
+                                             current_token(),
+                                             "ERR143 - Expected ';' at end of vector definition"));
+                        
+                        return error_node();
+                    }
+                }
+                
+                if (vec_initilizer_list.size() > vector_size)
+                {
+                    set_error(
+                              make_error(parser_error::e_syntax,
+                                         current_token(),
+                                         "ERR144 - Initialiser list larger than the number of elements in the vector: '" + vec_name + "'"));
+                    
+                    return error_node();
+                }
+            }
+            
+            typename symbol_table_t::vector_holder_ptr vec_holder = typename symbol_table_t::vector_holder_ptr(0);
+            
+            std::size_t vec_size = static_cast<std::size_t>(details::numeric::to_int32(vector_size));
+            
+            scope_element& se = sem_.get_element(vec_name);
+            
+            if (se.name == vec_name)
+            {
+                if (se.active)
+                {
+                    set_error(
+                              make_error(parser_error::e_syntax,
+                                         current_token(),
+                                         "ERR145 - Illegal redefinition of local vector: '" + vec_name + "'"));
+                    
+                    return error_node();
+                }
+                else if (
+                         (se.size == vec_size) &&
+                         (scope_element::e_vector == se.type)
+                         )
+                {
+                    vec_holder = se.vec_node;
+                    se.active  = true;
+                    se.depth   = state_.scope_depth;
+                    se.ref_count++;
+                }
+            }
+            
+            if (0 == vec_holder)
+            {
+                scope_element nse;
+                nse.name      = vec_name;
+                nse.active    = true;
+                nse.ref_count = 1;
+                nse.type      = scope_element::e_vector;
+                nse.depth     = state_.scope_depth;
+                nse.size      = vec_size;
+                nse.data      = new T[vec_size];
+                nse.vec_node  = new typename scope_element::vector_holder_t((T*)(nse.data),nse.size);
+                
+                if (!sem_.add_element(nse))
+                {
+                    set_error(
+                              make_error(parser_error::e_syntax,
+                                         current_token(),
+                                         "ERR146 - Failed to add new local vector '" + vec_name + "' to SEM"));
+                    
+                    sem_.free_element(nse);
+                    
+                    return error_node();
+                }
+                
+                vec_holder = nse.vec_node;
+                
+                exprtk_debug(("parse_define_vector_statement() - INFO - Added new local vector: %s[%d]\n",
+                              nse.name.c_str(),
+                              static_cast<int>(nse.size)));
+            }
+            
+            state_.activate_side_effect("parse_define_vector_statement()");
+            
+            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)
+                result = expression_generator_(
+                                               details::e_assign,
+                                               node_allocator_.allocate<vector_node_t>(vec_holder),
+                                               vec_initilizer_list[0]);
+            else
+                result = node_allocator_
+                .allocate<details::vector_assignment_node<T> >(
+                                                               (*vec_holder)[0],
+                                                               vec_size,
+                                                               vec_initilizer_list,
+                                                               single_value_initialiser);
+            
+            svd.delete_ptr = (0 == result);
+            
+            return result;
+        }
+        
+#ifndef exprtk_disable_string_capabilities
+        inline expression_node_ptr parse_define_string_statement(const std::string& str_name, expression_node_ptr initialisation_expression)
+        {
+            stringvar_node_t* str_node = reinterpret_cast<stringvar_node_t*>(0);
+            
+            scope_element& se = sem_.get_element(str_name);
+            
+            if (se.name == str_name)
+            {
+                if (se.active)
+                {
+                    set_error(
+                              make_error(parser_error::e_syntax,
+                                         current_token(),
+                                         "ERR147 - Illegal redefinition of local variable: '" + str_name + "'"));
+                    
+                    free_node(node_allocator_,initialisation_expression);
+                    
+                    return error_node();
+                }
+                else if (scope_element::e_string == se.type)
+                {
+                    str_node  = se.str_node;
+                    se.active = true;
+                    se.depth  = state_.scope_depth;
+                    se.ref_count++;
+                }
+            }
+            
+            if (0 == str_node)
+            {
+                scope_element nse;
+                nse.name      = str_name;
+                nse.active    = true;
+                nse.ref_count = 1;
+                nse.type      = scope_element::e_string;
+                nse.depth     = state_.scope_depth;
+                nse.data      = new std::string;
+                nse.str_node  = new stringvar_node_t(*(std::string*)(nse.data));
+                
+                if (!sem_.add_element(nse))
+                {
+                    set_error(
+                              make_error(parser_error::e_syntax,
+                                         current_token(),
+                                         "ERR148 - Failed to add new local string variable '" + str_name + "' to SEM"));
+                    
+                    free_node(node_allocator_,initialisation_expression);
+                    
+                    sem_.free_element(nse);
+                    
+                    return error_node();
+                }
+                
+                str_node = nse.str_node;
+                
+                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);
+            
+            state_.activate_side_effect("parse_define_string_statement()");
+            
+            expression_node_ptr branch[2] = {0};
+            
+            branch[0] = str_node;
+            branch[1] = initialisation_expression;
+            
+            return expression_generator_(details::e_assign,branch);
+        }
+#else
+        inline expression_node_ptr parse_define_string_statement(const std::string&, expression_node_ptr)
+        {
+            return error_node();
+        }
+#endif
+        
+        inline bool local_variable_is_shadowed(const std::string& symbol)
+        {
+            const scope_element& se = sem_.get_element(symbol);
+            return (se.name == symbol) && se.active;
+        }
+        
+        inline expression_node_ptr parse_define_var_statement()
+        {
+            if (settings_.vardef_disabled())
+            {
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR149 - Illegal variable definition"));
+                
+                return error_node();
             }
-         };
-
-         struct synthesize_boc_expression
-         {
-            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
-                                                      const details::operator_type& operation,
-                                                      expression_node_ptr (&branch)[2])
-            {
-               const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
-               details::free_node(*(expr_gen.node_allocator_),branch[1]);
-
-               if (details::is_boc_node(branch[0]))
-               {
-                  // Simplify expressions of the form:
-                  // 1. (((((((((x + 9) * 8) * 7) * 6) * 5) * 4) * 3) * 2) * 1) --> (x + 9) * 40320
-                  // 2. (((((((((x + 9) + 8) + 7) + 6) + 5) + 4) + 3) + 2) + 1) --> x + 45
-                  if (
-                       (operation == details::e_mul) ||
-                       (operation == details::e_add)
-                     )
-                  {
-                     details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]);
-
-                     if (operation == bocnode->operation())
-                     {
-                        switch (operation)
-                        {
-                           case details::e_add : bocnode->set_c(c + bocnode->c()); break;
-                           case details::e_mul : bocnode->set_c(c * bocnode->c()); break;
-                           default             : return error_node();
-                        }
-
-                        return bocnode;
-                     }
-                  }
-                  else if (operation == details::e_div)
-                  {
-                     details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]);
-                     details::operator_type boc_opr = bocnode->operation();
-
-                     if (
-                          (details::e_div == boc_opr) ||
-                          (details::e_mul == boc_opr)
-                        )
-                     {
-                        switch (boc_opr)
-                        {
-                           case details::e_div : bocnode->set_c(c * bocnode->c()); break;
-                           case details::e_mul : bocnode->set_c(bocnode->c() / c); break;
-                           default             : return error_node();
-                        }
-
-                        return bocnode;
-                     }
-                  }
-               }
-
-               #ifndef exprtk_disable_enhanced_features
-               if (details::is_sf3ext_node(branch[0]))
-               {
-                  expression_node_ptr result = error_node();
-
-                  if (synthesize_sf4ext_expression::template compile_left<ctype>(expr_gen,c,operation,branch[0],result))
-                  {
-                     free_node(*expr_gen.node_allocator_,branch[0]);
-
-                     return result;
-                  }
-               }
-               #endif
-
-               switch (operation)
-               {
-                  #define case_stmt(op0,op1)                                                       \
-                  case op0 : return expr_gen.node_allocator_->                                     \
-                                template allocate_cr<typename details::boc_node<Type,op1<Type> > > \
-                                   (branch[0],c);                                                  \
-
-                  basic_opr_switch_statements
-                  extended_opr_switch_statements
-                  #undef case_stmt
-                  default : return error_node();
-               }
+            else if (!details::imatch(current_token().value,"var"))
+            {
+                return error_node();
             }
-         };
-
-         struct synthesize_cocob_expression
-         {
-            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
-                                                      const details::operator_type& operation,
-                                                      expression_node_ptr (&branch)[2])
+            else
+                next_token();
+            
+            const std::string var_name = current_token().value;
+            
+            expression_node_ptr initialisation_expression = error_node();
+            
+            if (!token_is(token_t::e_symbol))
+            {
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR150 - Expected a symbol for variable definition"));
+                
+                return error_node();
+            }
+            else if (details::is_reserved_symbol(var_name))
             {
-               expression_node_ptr result = error_node();
-
-               // (cob) o c --> cob
-               if (details::is_cob_node(branch[0]))
-               {
-                  details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[0]);
-                  const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
-
-                  bool op_addsub = (details::e_add == cobnode->operation()) ||
-                                   (details::e_sub == cobnode->operation());
-
-                  if (op_addsub)
-                  {
-                     switch (operation)
-                     {
-                        case details::e_add : cobnode->set_c(cobnode->c() + c); break;
-                        case details::e_sub : cobnode->set_c(cobnode->c() - c); break;
-                        default             : return error_node();
-                     }
-
-                     result = cobnode;
-
-                  }
-                  else if (details::e_mul == cobnode->operation())
-                  {
-                     switch (operation)
-                     {
-                        case details::e_mul : cobnode->set_c(cobnode->c() * c); break;
-                        case details::e_div : cobnode->set_c(cobnode->c() / c); break;
-                        default             : return error_node();
-                     }
-
-                     result = cobnode;
-                  }
-                  else if (details::e_div == cobnode->operation())
-                  {
-                     if (details::e_mul == operation)
-                     {
-                        cobnode->set_c(cobnode->c() * c);
-                        result = cobnode;
-                     }
-                     else if (details::e_div == operation)
-                     {
-                        result = expr_gen.node_allocator_->
-                                    template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
-                                       (cobnode->c() / c,cobnode->move_branch(0));
-                        free_node(*expr_gen.node_allocator_,branch[0]);
-                     }
-                  }
-
-                  if (result)
-                  {
-                     free_node(*expr_gen.node_allocator_,branch[1]);
-                  }
-               }
-
-               // c o (cob) --> cob
-               else if (details::is_cob_node(branch[1]))
-               {
-                  details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]);
-                  const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value();
-
-                  if (details::e_add == cobnode->operation())
-                  {
-                     if (details::e_add == operation)
-                     {
-                        cobnode->set_c(c + cobnode->c());
-                        result = cobnode;
-                     }
-                     else if (details::e_sub == operation)
-                     {
-                        result = expr_gen.node_allocator_->
-                                    template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > >
-                                       (c - cobnode->c(),cobnode->move_branch(0));
-                        free_node(*expr_gen.node_allocator_,branch[1]);
-                     }
-                  }
-                  else if (details::e_sub == cobnode->operation())
-                  {
-                     if (details::e_add == operation)
-                     {
-                        cobnode->set_c(c + cobnode->c());
-                        result = cobnode;
-                     }
-                     else if (details::e_sub == operation)
-                     {
-                        result = expr_gen.node_allocator_->
-                                    template allocate_tt<typename details::cob_node<Type,details::add_op<Type> > >
-                                       (c - cobnode->c(),cobnode->move_branch(0));
-                        free_node(*expr_gen.node_allocator_,branch[1]);
-                     }
-                  }
-                  else if (details::e_mul == cobnode->operation())
-                  {
-                     if (details::e_mul == operation)
-                     {
-                        cobnode->set_c(c * cobnode->c());
-                        result = cobnode;
-                     }
-                     else if (details::e_div == operation)
-                     {
-                        result = expr_gen.node_allocator_->
-                                    template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
-                                       (c / cobnode->c(),cobnode->move_branch(0));
-                        free_node(*expr_gen.node_allocator_,branch[1]);
-                     }
-                  }
-                  else if (details::e_div == cobnode->operation())
-                  {
-                     if (details::e_mul == operation)
-                     {
-                        cobnode->set_c(c * cobnode->c());
-                        result = cobnode;
-                     }
-                     else if (details::e_div == operation)
-                     {
-                        result = expr_gen.node_allocator_->
-                                    template allocate_tt<typename details::cob_node<Type,details::mul_op<Type> > >
-                                       (c / cobnode->c(),cobnode->move_branch(0));
-                        free_node(*expr_gen.node_allocator_,branch[1]);
-                     }
-                  }
-
-                  if (result)
-                  {
-                     free_node(*expr_gen.node_allocator_,branch[0]);
-                  }
-               }
-
-               return result;
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR151 - Illegal redefinition of reserved keyword: '" + var_name + "'"));
+                
+                return error_node();
             }
-         };
-
-         struct synthesize_coboc_expression
-         {
-            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
-                                                      const details::operator_type& operation,
-                                                      expression_node_ptr (&branch)[2])
+            else if (symtab_store_.symbol_exists(var_name))
             {
-               expression_node_ptr result = error_node();
-
-               // (boc) o c --> boc
-               if (details::is_boc_node(branch[0]))
-               {
-                  details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]);
-                  const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
-
-                  if (details::e_add == bocnode->operation())
-                  {
-                     switch (operation)
-                     {
-                        case details::e_add : bocnode->set_c(bocnode->c() + c); break;
-                        case details::e_sub : bocnode->set_c(bocnode->c() - c); break;
-                        default             : return error_node();
-                     }
-
-                     result = bocnode;
-                  }
-                  else if (details::e_mul == bocnode->operation())
-                  {
-                     switch (operation)
-                     {
-                        case details::e_mul : bocnode->set_c(bocnode->c() * c); break;
-                        case details::e_div : bocnode->set_c(bocnode->c() / c); break;
-                        default             : return error_node();
-                     }
-
-                     result = bocnode;
-                  }
-                  else if (details::e_sub == bocnode->operation())
-                  {
-                     if (details::e_add == operation)
-                     {
-                        result = expr_gen.node_allocator_->
-                                    template allocate_tt<typename details::boc_node<Type,details::add_op<Type> > >
-                                       (bocnode->move_branch(0),c - bocnode->c());
-                        free_node(*expr_gen.node_allocator_,branch[0]);
-                     }
-                     else if (details::e_sub == operation)
-                     {
-                        bocnode->set_c(bocnode->c() + c);
-                        result = bocnode;
-                     }
-                  }
-                  else if (details::e_div == bocnode->operation())
-                  {
-                     switch (operation)
-                     {
-                        case details::e_div : bocnode->set_c(bocnode->c() * c); break;
-                        case details::e_mul : bocnode->set_c(bocnode->c() / c); break;
-                        default             : return error_node();
-                     }
-
-                     result = bocnode;
-                  }
-
-                  if (result)
-                  {
-                     free_node(*expr_gen.node_allocator_,branch[1]);
-                  }
-               }
-
-               // c o (boc) --> boc
-               else if (details::is_boc_node(branch[1]))
-               {
-                  details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[1]);
-                  const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value();
-
-                  if (details::e_add == bocnode->operation())
-                  {
-                     if (details::e_add == operation)
-                     {
-                        bocnode->set_c(c + bocnode->c());
-                        result = bocnode;
-                     }
-                     else if (details::e_sub == operation)
-                     {
-                        result = expr_gen.node_allocator_->
-                                    template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > >
-                                       (c - bocnode->c(),bocnode->move_branch(0));
-                        free_node(*expr_gen.node_allocator_,branch[1]);
-                     }
-                  }
-                  else if (details::e_sub == bocnode->operation())
-                  {
-                     if (details::e_add == operation)
-                     {
-                        result = expr_gen.node_allocator_->
-                                    template allocate_tt<typename details::boc_node<Type,details::add_op<Type> > >
-                                       (bocnode->move_branch(0),c - bocnode->c());
-                        free_node(*expr_gen.node_allocator_,branch[1]);
-                     }
-                     else if (details::e_sub == operation)
-                     {
-                        result = expr_gen.node_allocator_->
-                                    template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > >
-                                       (c + bocnode->c(),bocnode->move_branch(0));
-                        free_node(*expr_gen.node_allocator_,branch[1]);
-                     }
-                  }
-                  else if (details::e_mul == bocnode->operation())
-                  {
-                     if (details::e_mul == operation)
-                     {
-                        bocnode->set_c(c * bocnode->c());
-                        result = bocnode;
-                     }
-                     else if (details::e_div == operation)
-                     {
-                        result = expr_gen.node_allocator_->
-                                    template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
-                                       (c / bocnode->c(),bocnode->move_branch(0));
-                        free_node(*expr_gen.node_allocator_,branch[1]);
-                     }
-                  }
-                  else if (details::e_div == bocnode->operation())
-                  {
-                     if (details::e_mul == operation)
-                     {
-                        bocnode->set_c(bocnode->c() / c);
-                        result = bocnode;
-                     }
-                     else if (details::e_div == operation)
-                     {
-                        result = expr_gen.node_allocator_->
-                                    template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
-                                       (c * bocnode->c(),bocnode->move_branch(0));
-                        free_node(*expr_gen.node_allocator_,branch[1]);
-                     }
-                  }
-
-                  if (result)
-                  {
-                     free_node(*expr_gen.node_allocator_,branch[0]);
-                  }
-               }
-
-               return result;
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR152 - Illegal redefinition of variable '" + var_name + "'"));
+                
+                return error_node();
             }
-         };
-
-         #ifndef exprtk_disable_enhanced_features
-         inline bool synthesize_expression(const details::operator_type& operation,
-                                           expression_node_ptr (&branch)[2],
-                                           expression_node_ptr& result)
-         {
-            result = error_node();
-
-            if (!operation_optimizable(operation))
-               return false;
-
-            const std::string node_id = branch_to_id(branch);
-            typename synthesize_map_t::iterator itr = synthesize_map_.find(node_id);
-
-            if (synthesize_map_.end() != itr)
+            else if (local_variable_is_shadowed(var_name))
             {
-               result = itr->second(*this,operation,branch);
-
-               return true;
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR153 - Illegal redefinition of local variable: '" + var_name + "'"));
+                
+                return error_node();
             }
-            else
-               return false;
-         }
-
-         struct synthesize_vov_expression
-         {
-            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
-                                                      const details::operator_type& operation,
-                                                      expression_node_ptr (&branch)[2])
-            {
-               const Type& v1 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
-               const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
-
-               switch (operation)
-               {
-                  #define case_stmt(op0,op1)                                                       \
-                  case op0 : return expr_gen.node_allocator_->                                     \
-                                template allocate_rr<typename details::vov_node<Type,op1<Type> > > \
-                                   (v1,v2);                                                        \
-
-                  basic_opr_switch_statements
-                  extended_opr_switch_statements
-                  #undef case_stmt
-                  default : return error_node();
-               }
+            else if (token_is(token_t::e_lsqrbracket,prsrhlpr_t::e_hold))
+            {
+                return parse_define_vector_statement(var_name);
             }
-         };
-
-         struct synthesize_cov_expression
-         {
-            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
-                                                      const details::operator_type& operation,
-                                                      expression_node_ptr (&branch)[2])
-            {
-               const Type  c = static_cast<details::literal_node<Type>*> (branch[0])->value();
-               const Type& v = static_cast<details::variable_node<Type>*>(branch[1])->ref();
-
-               details::free_node(*(expr_gen.node_allocator_),branch[0]);
-
-               switch (operation)
-               {
-                  #define case_stmt(op0,op1)                                                       \
-                  case op0 : return expr_gen.node_allocator_->                                     \
-                                template allocate_cr<typename details::cov_node<Type,op1<Type> > > \
-                                   (c,v);                                                          \
-
-                  basic_opr_switch_statements
-                  extended_opr_switch_statements
-                  #undef case_stmt
-                  default : return error_node();
-               }
+            else if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold))
+            {
+                return parse_uninitialised_var_statement(var_name);
             }
-         };
-
-         struct synthesize_voc_expression
-         {
-            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
-                                                      const details::operator_type& operation,
-                                                      expression_node_ptr (&branch)[2])
-            {
-               const Type& v = static_cast<details::variable_node<Type>*>(branch[0])->ref();
-               const Type  c = static_cast<details::literal_node<Type>*> (branch[1])->value();
-
-               details::free_node(*(expr_gen.node_allocator_),branch[1]);
-
-               if (expr_gen.cardinal_pow_optimizable(operation,c))
-               {
-                  if (std::equal_to<T>()(T(1),c))
-                     return branch[0];
-                  else
-                     return expr_gen.cardinal_pow_optimization(v,c);
-               }
-
-               switch (operation)
-               {
-                  #define case_stmt(op0,op1)                                                       \
-                  case op0 : return expr_gen.node_allocator_->                                     \
-                                template allocate_rc<typename details::voc_node<Type,op1<Type> > > \
-                                   (v,c);                                                          \
-
-                  basic_opr_switch_statements
-                  extended_opr_switch_statements
-                  #undef case_stmt
-                  default : return error_node();
-               }
+            else if (token_is(token_t::e_assign))
+            {
+                if (0 == (initialisation_expression = parse_expression()))
+                {
+                    set_error(
+                              make_error(parser_error::e_syntax,
+                                         current_token(),
+                                         "ERR154 - Failed to parse initialisation expression"));
+                    
+                    return error_node();
+                }
             }
-         };
-
-         struct synthesize_sf3ext_expression
-         {
-            template <typename T0, typename T1, typename T2>
-            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
-                                                      const details::operator_type& sf3opr,
-                                                      T0 t0, T1 t1, T2 t2)
-            {
-               switch (sf3opr)
-               {
-                  #define case_stmt(op0,op1)                                          \
-                  case op0 : return details::T0oT1oT2_sf3ext<T,T0,T1,T2,op1<Type> >:: \
-                                allocate(*(expr_gen.node_allocator_),t0,t1,t2);       \
-
-                  case_stmt(details::e_sf00,details::sf00_op) case_stmt(details::e_sf01,details::sf01_op)
-                  case_stmt(details::e_sf02,details::sf02_op) case_stmt(details::e_sf03,details::sf03_op)
-                  case_stmt(details::e_sf04,details::sf04_op) case_stmt(details::e_sf05,details::sf05_op)
-                  case_stmt(details::e_sf06,details::sf06_op) case_stmt(details::e_sf07,details::sf07_op)
-                  case_stmt(details::e_sf08,details::sf08_op) case_stmt(details::e_sf09,details::sf09_op)
-                  case_stmt(details::e_sf10,details::sf10_op) case_stmt(details::e_sf11,details::sf11_op)
-                  case_stmt(details::e_sf12,details::sf12_op) case_stmt(details::e_sf13,details::sf13_op)
-                  case_stmt(details::e_sf14,details::sf14_op) case_stmt(details::e_sf15,details::sf15_op)
-                  case_stmt(details::e_sf16,details::sf16_op) case_stmt(details::e_sf17,details::sf17_op)
-                  case_stmt(details::e_sf18,details::sf18_op) case_stmt(details::e_sf19,details::sf19_op)
-                  case_stmt(details::e_sf20,details::sf20_op) case_stmt(details::e_sf21,details::sf21_op)
-                  case_stmt(details::e_sf22,details::sf22_op) case_stmt(details::e_sf23,details::sf23_op)
-                  case_stmt(details::e_sf24,details::sf24_op) case_stmt(details::e_sf25,details::sf25_op)
-                  case_stmt(details::e_sf26,details::sf26_op) case_stmt(details::e_sf27,details::sf27_op)
-                  case_stmt(details::e_sf28,details::sf28_op) case_stmt(details::e_sf29,details::sf29_op)
-                  case_stmt(details::e_sf30,details::sf30_op)
-                  #undef case_stmt
-                  default : return error_node();
-               }
+            
+            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)
+                )
+            {
+                if (!token_is(token_t::e_eof,prsrhlpr_t::e_hold))
+                {
+                    set_error(
+                              make_error(parser_error::e_syntax,
+                                         current_token(),
+                                         "ERR155 - Expected ';' after variable definition"));
+                    
+                    free_node(node_allocator_,initialisation_expression);
+                    
+                    return error_node();
+                }
+            }
+            
+            if (
+                (0 != initialisation_expression) &&
+                details::is_generally_string_node(initialisation_expression)
+                )
+            {
+                return parse_define_string_statement(var_name,initialisation_expression);
+            }
+            
+            expression_node_ptr var_node = reinterpret_cast<expression_node_ptr>(0);
+            
+            scope_element& se = sem_.get_element(var_name);
+            
+            if (se.name == var_name)
+            {
+                if (se.active)
+                {
+                    set_error(
+                              make_error(parser_error::e_syntax,
+                                         current_token(),
+                                         "ERR156 - Illegal redefinition of local variable: '" + var_name + "'"));
+                    
+                    free_node(node_allocator_,initialisation_expression);
+                    
+                    return error_node();
+                }
+                else if (scope_element::e_variable == se.type)
+                {
+                    var_node  = se.var_node;
+                    se.active = true;
+                    se.depth  = state_.scope_depth;
+                    se.ref_count++;
+                }
+            }
+            
+            if (0 == var_node)
+            {
+                scope_element nse;
+                nse.name      = var_name;
+                nse.active    = true;
+                nse.ref_count = 1;
+                nse.type      = scope_element::e_variable;
+                nse.depth     = state_.scope_depth;
+                nse.data      = new T(T(0));
+                nse.var_node  = node_allocator_.allocate<variable_node_t>(*(T*)(nse.data));
+                
+                if (!sem_.add_element(nse))
+                {
+                    set_error(
+                              make_error(parser_error::e_syntax,
+                                         current_token(),
+                                         "ERR157 - Failed to add new local variable '" + var_name + "' to SEM"));
+                    
+                    free_node(node_allocator_,initialisation_expression);
+                    
+                    sem_.free_element(nse);
+                    
+                    return error_node();
+                }
+                
+                var_node = nse.var_node;
+                
+                exprtk_debug(("parse_define_var_statement() - INFO - Added new local variable: %s\n",nse.name.c_str()));
+            }
+            
+            state_.activate_side_effect("parse_define_var_statement()");
+            
+            lodge_symbol(var_name,e_st_local_variable);
+            
+            expression_node_ptr branch[2] = {0};
+            
+            branch[0] = var_node;
+            branch[1] = initialisation_expression ? initialisation_expression : expression_generator_(T(0));
+            
+            return expression_generator_(details::e_assign,branch);
+        }
+        
+        inline expression_node_ptr parse_uninitialised_var_statement(const std::string& var_name)
+        {
+            if (
+                !token_is(token_t::e_lcrlbracket) ||
+                !token_is(token_t::e_rcrlbracket)
+                )
+            {
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR158 - Expected a '{}' for uninitialised var definition"));
+                
+                return error_node();
             }
-
-            template <typename T0, typename T1, typename T2>
-            static inline bool compile(expression_generator<Type>& expr_gen, const std::string& id,
-                                       T0 t0, T1 t1, T2 t2,
-                                       expression_node_ptr& result)
+            else if (!token_is(token_t::e_eof,prsrhlpr_t::e_hold))
             {
-               details::operator_type sf3opr;
-
-               if (!expr_gen.sf3_optimizable(id,sf3opr))
-                  return false;
-               else
-                  result = synthesize_sf3ext_expression::template process<T0,T1,T2>(expr_gen,sf3opr,t0,t1,t2);
-
-               return true;
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR159 - Expected ';' after uninitialised variable definition"));
+                
+                return error_node();
+            }
+            
+            expression_node_ptr var_node = reinterpret_cast<expression_node_ptr>(0);
+            
+            scope_element& se = sem_.get_element(var_name);
+            
+            if (se.name == var_name)
+            {
+                if (se.active)
+                {
+                    set_error(
+                              make_error(parser_error::e_syntax,
+                                         current_token(),
+                                         "ERR160 - Illegal redefinition of local variable: '" + var_name + "'"));
+                    
+                    return error_node();
+                }
+                else if (scope_element::e_variable == se.type)
+                {
+                    var_node  = se.var_node;
+                    se.active = true;
+                    se.ref_count++;
+                }
+            }
+            
+            if (0 == var_node)
+            {
+                scope_element nse;
+                nse.name      = var_name;
+                nse.active    = true;
+                nse.ref_count = 1;
+                nse.type      = scope_element::e_variable;
+                nse.depth     = state_.scope_depth;
+                nse.ip_index  = sem_.next_ip_index();
+                nse.data      = new T(T(0));
+                nse.var_node  = node_allocator_.allocate<variable_node_t>(*(T*)(nse.data));
+                
+                if (!sem_.add_element(nse))
+                {
+                    set_error(
+                              make_error(parser_error::e_syntax,
+                                         current_token(),
+                                         "ERR161 - Failed to add new local variable '" + var_name + "' to SEM"));
+                    
+                    sem_.free_element(nse);
+                    
+                    return error_node();
+                }
+                
+                exprtk_debug(("parse_uninitialised_var_statement() - INFO - Added new local variable: %s\n",
+                              nse.name.c_str()));
+            }
+            
+            lodge_symbol(var_name,e_st_local_variable);
+            
+            state_.activate_side_effect("parse_uninitialised_var_statement()");
+            
+            return expression_generator_(T(0));
+        }
+        
+        inline expression_node_ptr parse_swap_statement()
+        {
+            if (!details::imatch(current_token().value,"swap"))
+            {
+                return error_node();
             }
-         };
-
-         struct synthesize_sf4ext_expression
-         {
-            template <typename T0, typename T1, typename T2, typename T3>
-            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
-                                                      const details::operator_type& sf4opr,
-                                                      T0 t0, T1 t1, T2 t2, T3 t3)
-            {
-               switch (sf4opr)
-               {
-                  #define case_stmt(op0,op1)                                                   \
-                  case op0 : return details::T0oT1oT2oT3_sf4ext<Type,T0,T1,T2,T3,op1<Type> >:: \
-                                allocate(*(expr_gen.node_allocator_),t0,t1,t2,t3);             \
-
-                  case_stmt(details::e_sf48,details::sf48_op) case_stmt(details::e_sf49,details::sf49_op)
-                  case_stmt(details::e_sf50,details::sf50_op) case_stmt(details::e_sf51,details::sf51_op)
-                  case_stmt(details::e_sf52,details::sf52_op) case_stmt(details::e_sf53,details::sf53_op)
-                  case_stmt(details::e_sf54,details::sf54_op) case_stmt(details::e_sf55,details::sf55_op)
-                  case_stmt(details::e_sf56,details::sf56_op) case_stmt(details::e_sf57,details::sf57_op)
-                  case_stmt(details::e_sf58,details::sf58_op) case_stmt(details::e_sf59,details::sf59_op)
-                  case_stmt(details::e_sf60,details::sf60_op) case_stmt(details::e_sf61,details::sf61_op)
-                  case_stmt(details::e_sf62,details::sf62_op) case_stmt(details::e_sf63,details::sf63_op)
-                  case_stmt(details::e_sf64,details::sf64_op) case_stmt(details::e_sf65,details::sf65_op)
-                  case_stmt(details::e_sf66,details::sf66_op) case_stmt(details::e_sf67,details::sf67_op)
-                  case_stmt(details::e_sf68,details::sf68_op) case_stmt(details::e_sf69,details::sf69_op)
-                  case_stmt(details::e_sf70,details::sf70_op) case_stmt(details::e_sf71,details::sf71_op)
-                  case_stmt(details::e_sf72,details::sf72_op) case_stmt(details::e_sf73,details::sf73_op)
-                  case_stmt(details::e_sf74,details::sf74_op) case_stmt(details::e_sf75,details::sf75_op)
-                  case_stmt(details::e_sf76,details::sf76_op) case_stmt(details::e_sf77,details::sf77_op)
-                  case_stmt(details::e_sf78,details::sf78_op) case_stmt(details::e_sf79,details::sf79_op)
-                  case_stmt(details::e_sf80,details::sf80_op) case_stmt(details::e_sf81,details::sf81_op)
-                  case_stmt(details::e_sf82,details::sf82_op) case_stmt(details::e_sf83,details::sf83_op)
-                  case_stmt(details::e_sf4ext00,details::sfext00_op) case_stmt(details::e_sf4ext01,details::sfext01_op)
-                  case_stmt(details::e_sf4ext02,details::sfext02_op) case_stmt(details::e_sf4ext03,details::sfext03_op)
-                  case_stmt(details::e_sf4ext04,details::sfext04_op) case_stmt(details::e_sf4ext05,details::sfext05_op)
-                  case_stmt(details::e_sf4ext06,details::sfext06_op) case_stmt(details::e_sf4ext07,details::sfext07_op)
-                  case_stmt(details::e_sf4ext08,details::sfext08_op) case_stmt(details::e_sf4ext09,details::sfext09_op)
-                  case_stmt(details::e_sf4ext10,details::sfext10_op) case_stmt(details::e_sf4ext11,details::sfext11_op)
-                  case_stmt(details::e_sf4ext12,details::sfext12_op) case_stmt(details::e_sf4ext13,details::sfext13_op)
-                  case_stmt(details::e_sf4ext14,details::sfext14_op) case_stmt(details::e_sf4ext15,details::sfext15_op)
-                  case_stmt(details::e_sf4ext16,details::sfext16_op) case_stmt(details::e_sf4ext17,details::sfext17_op)
-                  case_stmt(details::e_sf4ext18,details::sfext18_op) case_stmt(details::e_sf4ext19,details::sfext19_op)
-                  case_stmt(details::e_sf4ext20,details::sfext20_op) case_stmt(details::e_sf4ext21,details::sfext21_op)
-                  case_stmt(details::e_sf4ext22,details::sfext22_op) case_stmt(details::e_sf4ext23,details::sfext23_op)
-                  case_stmt(details::e_sf4ext24,details::sfext24_op) case_stmt(details::e_sf4ext25,details::sfext25_op)
-                  case_stmt(details::e_sf4ext26,details::sfext26_op) case_stmt(details::e_sf4ext27,details::sfext27_op)
-                  case_stmt(details::e_sf4ext28,details::sfext28_op) case_stmt(details::e_sf4ext29,details::sfext29_op)
-                  case_stmt(details::e_sf4ext30,details::sfext30_op) case_stmt(details::e_sf4ext31,details::sfext31_op)
-                  case_stmt(details::e_sf4ext32,details::sfext32_op) case_stmt(details::e_sf4ext33,details::sfext33_op)
-                  case_stmt(details::e_sf4ext34,details::sfext34_op) case_stmt(details::e_sf4ext35,details::sfext35_op)
-                  case_stmt(details::e_sf4ext36,details::sfext36_op) case_stmt(details::e_sf4ext37,details::sfext37_op)
-                  case_stmt(details::e_sf4ext38,details::sfext38_op) case_stmt(details::e_sf4ext39,details::sfext39_op)
-                  case_stmt(details::e_sf4ext40,details::sfext40_op) case_stmt(details::e_sf4ext41,details::sfext41_op)
-                  case_stmt(details::e_sf4ext42,details::sfext42_op) case_stmt(details::e_sf4ext43,details::sfext43_op)
-                  case_stmt(details::e_sf4ext44,details::sfext44_op) case_stmt(details::e_sf4ext45,details::sfext45_op)
-                  case_stmt(details::e_sf4ext46,details::sfext46_op) case_stmt(details::e_sf4ext47,details::sfext47_op)
-                  case_stmt(details::e_sf4ext48,details::sfext48_op) case_stmt(details::e_sf4ext49,details::sfext49_op)
-                  case_stmt(details::e_sf4ext50,details::sfext50_op) case_stmt(details::e_sf4ext51,details::sfext51_op)
-                  case_stmt(details::e_sf4ext52,details::sfext52_op) case_stmt(details::e_sf4ext53,details::sfext53_op)
-                  case_stmt(details::e_sf4ext54,details::sfext54_op) case_stmt(details::e_sf4ext55,details::sfext55_op)
-                  case_stmt(details::e_sf4ext56,details::sfext56_op) case_stmt(details::e_sf4ext57,details::sfext57_op)
-                  case_stmt(details::e_sf4ext58,details::sfext58_op) case_stmt(details::e_sf4ext59,details::sfext59_op)
-
-                  #undef case_stmt
-                  default : return error_node();
-               }
+            else
+                next_token();
+            
+            if (!token_is(token_t::e_lbracket))
+            {
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR162 - Expected '(' at start of swap statement"));
+                
+                return error_node();
+            }
+            
+            expression_node_ptr variable0 = error_node();
+            expression_node_ptr variable1 = error_node();
+            
+            bool variable0_generated = false;
+            bool variable1_generated = false;
+            
+            const std::string var0_name = current_token().value;
+            
+            if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold))
+            {
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR163 - Expected a symbol for variable or vector element definition"));
+                
+                return error_node();
+            }
+            else if (peek_token_is(token_t::e_lsqrbracket))
+            {
+                if (0 == (variable0 = parse_vector()))
+                {
+                    set_error(
+                              make_error(parser_error::e_syntax,
+                                         current_token(),
+                                         "ERR164 - First parameter to swap is an invalid vector element: '" + var0_name + "'"));
+                    
+                    return error_node();
+                }
+                
+                variable0_generated = true;
             }
-
-            template <typename T0, typename T1, typename T2, typename T3>
-            static inline bool compile(expression_generator<Type>& expr_gen, const std::string& id,
-                                       T0 t0, T1 t1, T2 t2, T3 t3,
-                                       expression_node_ptr& result)
+            else
             {
-               details::operator_type sf4opr;
-
-               if (!expr_gen.sf4_optimizable(id,sf4opr))
-                  return false;
-               else
-                  result = synthesize_sf4ext_expression::template process<T0,T1,T2,T3>(expr_gen,sf4opr,t0,t1,t2,t3);
-
-               return true;
+                if (symtab_store_.is_variable(var0_name))
+                {
+                    variable0 = symtab_store_.get_variable(var0_name);
+                }
+                
+                scope_element& se = sem_.get_element(var0_name);
+                
+                if (
+                    (se.active)            &&
+                    (se.name == var0_name) &&
+                    (scope_element::e_variable == se.type)
+                    )
+                {
+                    variable0 = se.var_node;
+                }
+                
+                lodge_symbol(var0_name,e_st_variable);
+                
+                if (0 == variable0)
+                {
+                    set_error(
+                              make_error(parser_error::e_syntax,
+                                         current_token(),
+                                         "ERR165 - First parameter to swap is an invalid variable: '" + var0_name + "'"));
+                    
+                    return error_node();
+                }
+                else
+                    next_token();
+            }
+            
+            if (!token_is(token_t::e_comma))
+            {
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR166 - Expected ',' between parameters to swap"));
+                
+                if (variable0_generated)
+                {
+                    free_node(node_allocator_,variable0);
+                }
+                
+                return error_node();
+            }
+            
+            const std::string var1_name = current_token().value;
+            
+            if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold))
+            {
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR167 - Expected a symbol for variable or vector element definition"));
+                
+                if (variable0_generated)
+                {
+                    free_node(node_allocator_,variable0);
+                }
+                
+                return error_node();
+            }
+            else if (peek_token_is(token_t::e_lsqrbracket))
+            {
+                if (0 == (variable1 = parse_vector()))
+                {
+                    set_error(
+                              make_error(parser_error::e_syntax,
+                                         current_token(),
+                                         "ERR168 - Second parameter to swap is an invalid vector element: '" + var1_name + "'"));
+                    
+                    if (variable0_generated)
+                    {
+                        free_node(node_allocator_,variable0);
+                    }
+                    
+                    return error_node();
+                }
+                
+                variable1_generated = true;
             }
-
-            // T o (sf3ext)
-            template <typename ExternalType>
-            static inline bool compile_right(expression_generator<Type>& expr_gen,
-                                             ExternalType t,
-                                             const details::operator_type& operation,
-                                             expression_node_ptr& sf3node,
-                                             expression_node_ptr& result)
-            {
-               if (!details::is_sf3ext_node(sf3node))
-                  return false;
-
-               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() + ")";
-
-               switch (n->type())
-               {
-                  case details::expression_node<Type>::e_covoc : return compile_right_impl
-                                                                    <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>
-                                                                       (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>
-                                                                       (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>
-                                                                       (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>
-                                                                       (expr_gen,id,t,sf3node,result);
-
-                  default                                      : return false;
-               }
+            else
+            {
+                if (symtab_store_.is_variable(var1_name))
+                {
+                    variable1 = symtab_store_.get_variable(var1_name);
+                }
+                
+                scope_element& se = sem_.get_element(var1_name);
+                
+                if (
+                    (se.active) &&
+                    (se.name == var1_name) &&
+                    (scope_element::e_variable == se.type)
+                    )
+                {
+                    variable1 = se.var_node;
+                }
+                
+                lodge_symbol(var1_name,e_st_variable);
+                
+                if (0 == variable1)
+                {
+                    set_error(
+                              make_error(parser_error::e_syntax,
+                                         current_token(),
+                                         "ERR169 - Second parameter to swap is an invalid variable: '" + var1_name + "'"));
+                    
+                    if (variable0_generated)
+                    {
+                        free_node(node_allocator_,variable0);
+                    }
+                    
+                    return error_node();
+                }
+                else
+                    next_token();
+            }
+            
+            if (!token_is(token_t::e_rbracket))
+            {
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR170 - Expected ')' at end of swap statement"));
+                
+                if (variable0_generated)
+                {
+                    free_node(node_allocator_,variable0);
+                }
+                
+                if (variable1_generated)
+                {
+                    free_node(node_allocator_,variable1);
+                }
+                
+                return error_node();
+            }
+            
+            typedef details::variable_node<T>* variable_node_ptr;
+            variable_node_ptr v0 = variable_node_ptr(0);
+            variable_node_ptr v1 = variable_node_ptr(0);
+            
+            expression_node_ptr result = error_node();
+            
+            if (
+                (0 != (v0 = dynamic_cast<variable_node_ptr>(variable0))) &&
+                (0 != (v1 = dynamic_cast<variable_node_ptr>(variable1)))
+                )
+            {
+                result = node_allocator_.allocate<details::swap_node<T> >(v0,v1);
+                
+                if (variable0_generated)
+                {
+                    free_node(node_allocator_,variable0);
+                }
+                
+                if (variable1_generated)
+                {
+                    free_node(node_allocator_,variable1);
+                }
             }
-
-            // (sf3ext) o T
-            template <typename ExternalType>
-            static inline bool compile_left(expression_generator<Type>& expr_gen,
-                                            ExternalType t,
-                                            const details::operator_type& operation,
-                                            expression_node_ptr& sf3node,
-                                            expression_node_ptr& result)
-            {
-               if (!details::is_sf3ext_node(sf3node))
-                  return false;
-
-               typedef details::T0oT1oT2_base_node<Type>* sf3ext_base_ptr;
-
-               sf3ext_base_ptr n = static_cast<sf3ext_base_ptr>(sf3node);
-               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>
-                                                                       (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>
-                                                                       (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>
-                                                                       (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>
-                                                                       (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>
-                                                                       (expr_gen,id,t,sf3node,result);
-
-                  default                                      : return false;
-               }
+            else
+                result = node_allocator_.allocate<details::swap_generic_node<T> >(variable0,variable1);
+            
+            state_.activate_side_effect("parse_swap_statement()");
+            
+            return result;
+        }
+        
+        inline expression_node_ptr parse_return_statement()
+        {
+            if (state_.parsing_return_stmt)
+            {
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR171 - Return call within a return call is not allowed"));
+                
+                return error_node();
+            }
+            
+            scoped_bool_negator sbn(state_.parsing_return_stmt);
+            
+            std::vector<expression_node_ptr> arg_list;
+            
+            scoped_vec_delete<expression_node_t> sdd(*this,arg_list);
+            
+            if (!details::imatch(current_token().value,"return"))
+            {
+                return error_node();
             }
-
-            template <typename SF3TypeNode, typename ExternalType, typename T0, typename T1, typename T2>
-            static inline bool compile_right_impl(expression_generator<Type>& expr_gen,
-                                                  const std::string& id,
-                                                  ExternalType t,
-                                                  expression_node_ptr& node,
-                                                  expression_node_ptr& result)
-            {
-               SF3TypeNode* n = dynamic_cast<SF3TypeNode*>(node);
-
-               if (n)
-               {
-                  T0 t0 = n->t0();
-                  T1 t1 = n->t1();
-                  T2 t2 = n->t2();
-
-                  return synthesize_sf4ext_expression::
-                           template compile<ExternalType,T0,T1,T2>(expr_gen,id,t,t0,t1,t2,result);
-               }
-               else
-                  return false;
+            else
+                next_token();
+            
+            if (!token_is(token_t::e_lsqrbracket))
+            {
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR172 - Expected '[' at start of return statement"));
+                
+                return error_node();
             }
-
-            template <typename SF3TypeNode, typename ExternalType, typename T0, typename T1, typename T2>
-            static inline bool compile_left_impl(expression_generator<Type>& expr_gen,
-                                                 const std::string& id,
-                                                 ExternalType t,
-                                                 expression_node_ptr& node,
-                                                 expression_node_ptr& result)
+            else if (!token_is(token_t::e_rsqrbracket))
             {
-               SF3TypeNode* n = dynamic_cast<SF3TypeNode*>(node);
-
-               if (n)
-               {
-                  T0 t0 = n->t0();
-                  T1 t1 = n->t1();
-                  T2 t2 = n->t2();
-
-                  return synthesize_sf4ext_expression::
-                           template compile<T0,T1,T2,ExternalType>(expr_gen,id,t0,t1,t2,t,result);
-               }
-               else
-                  return false;
+                for ( ; ; )
+                {
+                    expression_node_ptr arg = parse_expression();
+                    
+                    if (0 == arg)
+                        return error_node();
+                    
+                    arg_list.push_back(arg);
+                    
+                    if (token_is(token_t::e_rsqrbracket))
+                        break;
+                    else if (!token_is(token_t::e_comma))
+                    {
+                        set_error(
+                                  make_error(parser_error::e_syntax,
+                                             current_token(),
+                                             "ERR173 - Expected ',' between values during call to return"));
+                        
+                        return error_node();
+                    }
+                }
             }
-         };
-
-         struct synthesize_vovov_expression0
-         {
-            typedef typename vovov_t::type0 node_type;
-            typedef typename vovov_t::sf3_type sf3_type;
-
-            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
-                                                      const details::operator_type& operation,
-                                                      expression_node_ptr (&branch)[2])
-            {
-               // (v0 o0 v1) o1 (v2)
-               const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]);
-               const Type& v0 = vov->v0();
-               const Type& v1 = vov->v1();
-               const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
-               const details::operator_type o0 = vov->operation();
-               const details::operator_type o1 = operation;
-
-               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
-
-               details::free_node(*(expr_gen.node_allocator_),branch[0]);
-
-               expression_node_ptr result = error_node();
-
-               if (expr_gen.strength_reduction_enabled())
-               {
-                  // (v0 / v1) / v2 --> (vovov) v0 / (v1 * v2)
-                  if ((details::e_div == o0) && (details::e_div == o1))
-                  {
-                     const bool synthesis_result =
-                        synthesize_sf3ext_expression::
-                           template compile<vtype,vtype,vtype>(expr_gen,"t/(t*t)",v0,v1,v2,result);
-
-                     exprtk_debug(("(v0 / v1) / v2 --> (vovov) v0 / (v1 * v2)\n"));
-
-                     return (synthesis_result) ? result : error_node();
-                  }
-               }
-
-               if (synthesize_sf3ext_expression::template compile<vtype,vtype,vtype>(expr_gen,id(expr_gen,o0,o1),v0,v1,v2,result))
-                  return result;
-               else if (!expr_gen.valid_operator(o0,f0))
-                  return error_node();
-               else if (!expr_gen.valid_operator(o1,f1))
-                  return error_node();
-               else
-                  return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,f0,f1);
+            else if (settings_.zero_return_disabled())
+            {
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR174 - Zero parameter return statement not allowed"));
+                
+                return error_node();
+            }
+            
+            lexer::token prev_token = current_token();
+            
+            if (token_is(token_t::e_rsqrbracket))
+            {
+                if (!arg_list.empty())
+                {
+                    set_error(
+                              make_error(parser_error::e_syntax,
+                                         prev_token,
+                                         "ERR175 - Invalid ']' found during return call"));
+                    
+                    return error_node();
+                }
+            }
+            
+            std::string ret_param_type_list;
+            
+            for (std::size_t i = 0; i < arg_list.size(); ++i)
+            {
+                if (0 == arg_list[i])
+                    return error_node();
+                else if (is_ivector_node(arg_list[i]))
+                    ret_param_type_list += 'V';
+                else if (is_generally_string_node(arg_list[i]))
+                    ret_param_type_list += 'S';
+                else
+                    ret_param_type_list += 'T';
+            }
+            
+            dec_.retparam_list_.push_back(ret_param_type_list);
+            
+            expression_node_ptr result = expression_generator_.return_call(arg_list);
+            
+            sdd.delete_ptr = (0 == result);
+            
+            state_.return_stmt_present = true;
+            
+            state_.activate_side_effect("parse_return_statement()");
+            
+            return result;
+        }
+        
+        inline bool post_variable_process(const std::string& symbol)
+        {
+            if (
+                peek_token_is(token_t::e_lbracket   ) ||
+                peek_token_is(token_t::e_lcrlbracket) ||
+                peek_token_is(token_t::e_lsqrbracket)
+                )
+            {
+                if (!settings_.commutative_check_enabled())
+                {
+                    set_error(
+                              make_error(parser_error::e_syntax,
+                                         current_token(),
+                                         "ERR176 - Invalid sequence of variable '"+ symbol + "' and bracket"));
+                    
+                    return false;
+                }
+                
+                lexer().insert_front(token_t::e_mul);
+            }
+            
+            return true;
+        }
+        
+        inline bool post_bracket_process(const typename token_t::token_type& token, expression_node_ptr& branch)
+        {
+            bool implied_mul = false;
+            
+            if (is_generally_string_node(branch))
+                return true;
+            
+            const lexer::parser_helper::token_advance_mode hold = prsrhlpr_t::e_hold;
+            
+            switch (token)
+            {
+                case token_t::e_lcrlbracket : implied_mul = token_is(token_t::e_lbracket   ,hold) ||
+                    token_is(token_t::e_lcrlbracket,hold) ||
+                    token_is(token_t::e_lsqrbracket,hold) ;
+                    break;
+                    
+                case token_t::e_lbracket    : implied_mul = token_is(token_t::e_lbracket   ,hold) ||
+                    token_is(token_t::e_lcrlbracket,hold) ||
+                    token_is(token_t::e_lsqrbracket,hold) ;
+                    break;
+                    
+                case token_t::e_lsqrbracket : implied_mul = token_is(token_t::e_lbracket   ,hold) ||
+                    token_is(token_t::e_lcrlbracket,hold) ||
+                    token_is(token_t::e_lsqrbracket,hold) ;
+                    break;
+                    
+                default                     : return true;
+            }
+            
+            if (implied_mul)
+            {
+                if (!settings_.commutative_check_enabled())
+                {
+                    set_error(
+                              make_error(parser_error::e_syntax,
+                                         current_token(),
+                                         "ERR177 - Invalid sequence of brackets"));
+                    
+                    return false;
+                }
+                else if (token_t::e_eof != current_token().type)
+                {
+                    lexer().insert_front(current_token().type);
+                    lexer().insert_front(token_t::e_mul);
+                    next_token();
+                }
+            }
+            
+            return true;
+        }
+        
+        inline expression_node_ptr parse_symtab_symbol()
+        {
+            const std::string symbol = current_token().value;
+            
+            // Are we dealing with a variable or a special constant?
+            expression_node_ptr variable = symtab_store_.get_variable(symbol);
+            
+            if (variable)
+            {
+                if (symtab_store_.is_constant_node(symbol))
+                {
+                    variable = expression_generator_(variable->value());
+                }
+                
+                if (!post_variable_process(symbol))
+                    return error_node();
+                
+                lodge_symbol(symbol,e_st_variable);
+                next_token();
+                
+                return variable;
+            }
+            
+            // Are we dealing with a locally defined variable, vector or string?
+            if (!sem_.empty())
+            {
+                scope_element& se = sem_.get_active_element(symbol);
+                
+                if (se.active && (se.name == symbol))
+                {
+                    if (scope_element::e_variable == se.type)
+                    {
+                        se.active = true;
+                        lodge_symbol(symbol,e_st_local_variable);
+                        
+                        if (!post_variable_process(symbol))
+                            return error_node();
+                        
+                        next_token();
+                        
+                        return se.var_node;
+                    }
+                    else if (scope_element::e_vector == se.type)
+                    {
+                        return parse_vector();
+                    }
+#ifndef exprtk_disable_string_capabilities
+                    else if (scope_element::e_string == se.type)
+                    {
+                        return parse_string();
+                    }
+#endif
+                }
             }
-
-            static inline std::string id(expression_generator<Type>& expr_gen,
-                                         const details::operator_type o0, const details::operator_type o1)
+            
+#ifndef exprtk_disable_string_capabilities
+            // Are we dealing with a string variable?
+            if (symtab_store_.is_stringvar(symbol))
             {
-               return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t");
+                return parse_string();
             }
-         };
-
-         struct synthesize_vovov_expression1
-         {
-            typedef typename vovov_t::type1 node_type;
-            typedef typename vovov_t::sf3_type sf3_type;
-
-            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
-                                                      const details::operator_type& operation,
-                                                      expression_node_ptr (&branch)[2])
-            {
-               // (v0) o0 (v1 o1 v2)
-               const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]);
-               const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
-               const Type& v1 = vov->v0();
-               const Type& v2 = vov->v1();
-               const details::operator_type o0 = operation;
-               const details::operator_type o1 = vov->operation();
-
-               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
-
-               details::free_node(*(expr_gen.node_allocator_),branch[1]);
-
-               expression_node_ptr result = error_node();
-
-               if (expr_gen.strength_reduction_enabled())
-               {
-                  // v0 / (v1 / v2) --> (vovov) (v0 * v2) / v1
-                  if ((details::e_div == o0) && (details::e_div == o1))
-                  {
-                     const bool synthesis_result =
-                        synthesize_sf3ext_expression::
-                           template compile<vtype,vtype,vtype>(expr_gen,"(t*t)/t",v0,v2,v1,result);
-
-                     exprtk_debug(("v0 / (v1 / v2) --> (vovov) (v0 * v2) / v1\n"));
-
-                     return (synthesis_result) ? result : error_node();
-                  }
-               }
-
-               if (synthesize_sf3ext_expression::template compile<vtype,vtype,vtype>(expr_gen,id(expr_gen,o0,o1),v0,v1,v2,result))
-                  return result;
-               else if (!expr_gen.valid_operator(o0,f0))
-                  return error_node();
-               else if (!expr_gen.valid_operator(o1,f1))
-                  return error_node();
-               else
-                  return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,f0,f1);
+#endif
+            
+            {
+                // Are we dealing with a function?
+                ifunction<T>* function = symtab_store_.get_function(symbol);
+                
+                if (function)
+                {
+                    lodge_symbol(symbol,e_st_function);
+                    
+                    expression_node_ptr func_node =
+                    parse_function_invocation(function,symbol);
+                    
+                    if (func_node)
+                        return func_node;
+                    else
+                    {
+                        set_error(
+                                  make_error(parser_error::e_syntax,
+                                             current_token(),
+                                             "ERR178 - Failed to generate node for function: '" + symbol + "'"));
+                        
+                        return error_node();
+                    }
+                }
+            }
+            
+            {
+                // Are we dealing with a vararg function?
+                ivararg_function<T>* vararg_function = symtab_store_.get_vararg_function(symbol);
+                
+                if (vararg_function)
+                {
+                    lodge_symbol(symbol,e_st_function);
+                    
+                    expression_node_ptr vararg_func_node =
+                    parse_vararg_function_call(vararg_function,symbol);
+                    
+                    if (vararg_func_node)
+                        return vararg_func_node;
+                    else
+                    {
+                        set_error(
+                                  make_error(parser_error::e_syntax,
+                                             current_token(),
+                                             "ERR179 - Failed to generate node for vararg function: '" + symbol + "'"));
+                        
+                        return error_node();
+                    }
+                }
+            }
+            
+            {
+                // Are we dealing with a vararg generic function?
+                igeneric_function<T>* generic_function = symtab_store_.get_generic_function(symbol);
+                
+                if (generic_function)
+                {
+                    lodge_symbol(symbol,e_st_function);
+                    
+                    expression_node_ptr genericfunc_node =
+                    parse_generic_function_call(generic_function,symbol);
+                    
+                    if (genericfunc_node)
+                        return genericfunc_node;
+                    else
+                    {
+                        set_error(
+                                  make_error(parser_error::e_syntax,
+                                             current_token(),
+                                             "ERR180 - Failed to generate node for generic function: '" + symbol + "'"));
+                        
+                        return error_node();
+                    }
+                }
+            }
+            
+            {
+                // Are we dealing with a vararg string returning function?
+                igeneric_function<T>* string_function = symtab_store_.get_string_function(symbol);
+                
+                if (string_function)
+                {
+                    lodge_symbol(symbol,e_st_function);
+                    
+                    expression_node_ptr stringfunc_node =
+                    parse_string_function_call(string_function,symbol);
+                    
+                    if (stringfunc_node)
+                        return stringfunc_node;
+                    else
+                    {
+                        set_error(
+                                  make_error(parser_error::e_syntax,
+                                             current_token(),
+                                             "ERR181 - Failed to generate node for string function: '" + symbol + "'"));
+                        
+                        return error_node();
+                    }
+                }
+            }
+            
+            // Are we dealing with a vector?
+            if (symtab_store_.is_vector(symbol))
+            {
+                lodge_symbol(symbol,e_st_vector);
+                return parse_vector();
+            }
+            
+            if (details::is_reserved_symbol(symbol))
+            {
+                if (settings_.function_enabled(symbol) || !details::is_base_function(symbol))
+                {
+                    set_error(
+                              make_error(parser_error::e_syntax,
+                                         current_token(),
+                                         "ERR182 - Invalid use of reserved symbol '" + symbol + "'"));
+                    
+                    return error_node();
+                }
+            }
+            
+            // Should we handle unknown symbols?
+            if (resolve_unknown_symbol_ && unknown_symbol_resolver_)
+            {
+                if (!(settings_.rsrvd_sym_usr_disabled() && details::is_reserved_symbol(symbol)))
+                {
+                    T default_value = T(0);
+                    std::string error_message;
+                    typename unknown_symbol_resolver::usr_symbol_type usr_symbol_type;
+                    
+                    if (unknown_symbol_resolver_->process(symbol,usr_symbol_type,default_value,error_message))
+                    {
+                        bool create_result = false;
+                        
+                        symbol_table_t& symtab = symtab_store_.get_symbol_table();
+                        
+                        switch (usr_symbol_type)
+                        {
+                            case unknown_symbol_resolver::e_usr_variable_type : create_result = symtab.create_variable(symbol,default_value);
+                                break;
+                                
+                            case unknown_symbol_resolver::e_usr_constant_type : create_result = symtab.add_constant(symbol,default_value);
+                                break;
+                                
+                            default                                           : create_result = false;
+                        }
+                        
+                        if (create_result)
+                        {
+                            expression_node_ptr var = symtab_store_.get_variable(symbol);
+                            
+                            if (var)
+                            {
+                                if (symtab_store_.is_constant_node(symbol))
+                                {
+                                    var = expression_generator_(var->value());
+                                }
+                                
+                                lodge_symbol(symbol,e_st_variable);
+                                
+                                if (!post_variable_process(symbol))
+                                    return error_node();
+                                
+                                next_token();
+                                
+                                return var;
+                            }
+                        }
+                        
+                        set_error(
+                                  make_error(parser_error::e_symtab,
+                                             current_token(),
+                                             "ERR183 - Failed to create variable: '" + symbol + "'"));
+                        
+                        return error_node();
+                    }
+                }
             }
-
-            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)");
+            
+            set_error(
+                      make_error(parser_error::e_syntax,
+                                 current_token(),
+                                 "ERR184 - Undefined symbol: '" + symbol + "'"));
+            
+            return error_node();
+        }
+        
+        inline expression_node_ptr parse_symbol()
+        {
+            static const std::string symbol_if       = "if"      ;
+            static const std::string symbol_while    = "while"   ;
+            static const std::string symbol_repeat   = "repeat"  ;
+            static const std::string symbol_for      = "for"     ;
+            static const std::string symbol_switch   = "switch"  ;
+            static const std::string symbol_null     = "null"    ;
+            static const std::string symbol_break    = "break"   ;
+            static const std::string symbol_continue = "continue";
+            static const std::string symbol_var      = "var"     ;
+            static const std::string symbol_swap     = "swap"    ;
+            static const std::string symbol_return   = "return"  ;
+            
+            if (valid_vararg_operation(current_token().value))
+            {
+                return parse_vararg_function();
+            }
+            else if (valid_base_operation(current_token().value))
+            {
+                return parse_base_operation();
             }
-         };
-
-         struct synthesize_vovoc_expression0
-         {
-            typedef typename vovoc_t::type0 node_type;
-            typedef typename vovoc_t::sf3_type sf3_type;
-
-            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
-                                                      const details::operator_type& operation,
-                                                      expression_node_ptr (&branch)[2])
-            {
-               // (v0 o0 v1) o1 (c)
-               const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]);
-               const Type& v0 = vov->v0();
-               const Type& v1 = vov->v1();
-               const Type   c = static_cast<details::literal_node<Type>*>(branch[1])->value();
-               const details::operator_type o0 = vov->operation();
-               const details::operator_type o1 = operation;
-
-               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
-
-               details::free_node(*(expr_gen.node_allocator_),branch[0]);
-               details::free_node(*(expr_gen.node_allocator_),branch[1]);
-
-               expression_node_ptr result = error_node();
-
-               if (expr_gen.strength_reduction_enabled())
-               {
-                  // (v0 / v1) / c --> (vovoc) v0 / (v1 * c)
-                  if ((details::e_div == o0) && (details::e_div == o1))
-                  {
-                     const bool synthesis_result =
-                        synthesize_sf3ext_expression::
-                           template compile<vtype,vtype,ctype>(expr_gen,"t/(t*t)",v0,v1,c,result);
-
-                     exprtk_debug(("(v0 / v1) / c --> (vovoc) v0 / (v1 * c)\n"));
-
-                     return (synthesis_result) ? result : error_node();
-                  }
-               }
-
-               if (synthesize_sf3ext_expression::template compile<vtype,vtype,ctype>(expr_gen,id(expr_gen,o0,o1),v0,v1,c,result))
-                  return result;
-               else if (!expr_gen.valid_operator(o0,f0))
-                  return error_node();
-               else if (!expr_gen.valid_operator(o1,f1))
-                  return error_node();
-               else
-                  return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,c,f0,f1);
+            else if (
+                     details::imatch(current_token().value,symbol_if) &&
+                     settings_.control_struct_enabled(current_token().value)
+                     )
+            {
+                return parse_conditional_statement();
             }
-
-            static inline std::string id(expression_generator<Type>& expr_gen,
-                                         const details::operator_type o0, const details::operator_type o1)
+            else if (
+                     details::imatch(current_token().value,symbol_while) &&
+                     settings_.control_struct_enabled(current_token().value)
+                     )
             {
-               return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t");
+                return parse_while_loop();
             }
-         };
-
-         struct synthesize_vovoc_expression1
-         {
-            typedef typename vovoc_t::type1 node_type;
-            typedef typename vovoc_t::sf3_type sf3_type;
-
-            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
-                                                      const details::operator_type& operation,
-                                                      expression_node_ptr (&branch)[2])
-            {
-               // (v0) o0 (v1 o1 c)
-               const details::voc_base_node<Type>* voc = static_cast<const details::voc_base_node<Type>*>(branch[1]);
-               const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
-               const Type& v1 = voc->v();
-               const Type   c = voc->c();
-               const details::operator_type o0 = operation;
-               const details::operator_type o1 = voc->operation();
-
-               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
-
-               details::free_node(*(expr_gen.node_allocator_),branch[1]);
-
-               expression_node_ptr result = error_node();
-
-               if (expr_gen.strength_reduction_enabled())
-               {
-                  // v0 / (v1 / c) --> (vocov) (v0 * c) / v1
-                  if ((details::e_div == o0) && (details::e_div == o1))
-                  {
-                     const bool synthesis_result =
-                        synthesize_sf3ext_expression::
-                           template compile<vtype,ctype,vtype>(expr_gen,"(t*t)/t",v0,c,v1,result);
-
-                     exprtk_debug(("v0 / (v1 / c) --> (vocov) (v0 * c) / v1\n"));
-
-                     return (synthesis_result) ? result : error_node();
-                  }
-               }
-
-               if (synthesize_sf3ext_expression::template compile<vtype,vtype,ctype>(expr_gen,id(expr_gen,o0,o1),v0,v1,c,result))
-                  return result;
-               else if (!expr_gen.valid_operator(o0,f0))
-                  return error_node();
-               else if (!expr_gen.valid_operator(o1,f1))
-                  return error_node();
-               else
-                  return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,c,f0,f1);
+            else if (
+                     details::imatch(current_token().value,symbol_repeat) &&
+                     settings_.control_struct_enabled(current_token().value)
+                     )
+            {
+                return parse_repeat_until_loop();
             }
-
-            static inline std::string id(expression_generator<Type>& expr_gen,
-                                         const details::operator_type o0, const details::operator_type o1)
+            else if (
+                     details::imatch(current_token().value,symbol_for) &&
+                     settings_.control_struct_enabled(current_token().value)
+                     )
             {
-               return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)");
+                return parse_for_loop();
             }
-         };
-
-         struct synthesize_vocov_expression0
-         {
-            typedef typename vocov_t::type0 node_type;
-            typedef typename vocov_t::sf3_type sf3_type;
-
-            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
-                                                      const details::operator_type& operation,
-                                                      expression_node_ptr (&branch)[2])
-            {
-               // (v0 o0 c) o1 (v1)
-               const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]);
-               const Type& v0 = voc->v();
-               const Type   c = voc->c();
-               const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
-               const details::operator_type o0 = voc->operation();
-               const details::operator_type o1 = operation;
-
-               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
-
-               details::free_node(*(expr_gen.node_allocator_),branch[0]);
-
-               expression_node_ptr result = error_node();
-
-               if (expr_gen.strength_reduction_enabled())
-               {
-                  // (v0 / c) / v1 --> (vovoc) v0 / (v1 * c)
-                  if ((details::e_div == o0) && (details::e_div == o1))
-                  {
-                     const bool synthesis_result =
-                        synthesize_sf3ext_expression::
-                           template compile<vtype,vtype,ctype>(expr_gen,"t/(t*t)",v0,v1,c,result);
-
-                     exprtk_debug(("(v0 / c) / v1 --> (vovoc) v0 / (v1 * c)\n"));
-
-                     return (synthesis_result) ? result : error_node();
-                  }
-               }
-
-               if (synthesize_sf3ext_expression::template compile<vtype,ctype,vtype>(expr_gen,id(expr_gen,o0,o1),v0,c,v1,result))
-                  return result;
-               else if (!expr_gen.valid_operator(o0,f0))
-                  return error_node();
-               else if (!expr_gen.valid_operator(o1,f1))
-                  return error_node();
-               else
-                  return node_type::allocate(*(expr_gen.node_allocator_),v0,c,v1,f0,f1);
+            else if (
+                     details::imatch(current_token().value,symbol_switch) &&
+                     settings_.control_struct_enabled(current_token().value)
+                     )
+            {
+                return parse_switch_statement();
             }
-
-            static inline std::string id(expression_generator<Type>& expr_gen,
-                                         const details::operator_type o0, const details::operator_type o1)
+            else if (details::is_valid_sf_symbol(current_token().value))
             {
-               return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t");
+                return parse_special_function();
             }
-         };
-
-         struct synthesize_vocov_expression1
-         {
-            typedef typename vocov_t::type1 node_type;
-            typedef typename vocov_t::sf3_type sf3_type;
-
-            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
-                                                      const details::operator_type& operation,
-                                                      expression_node_ptr (&branch)[2])
-            {
-               // (v0) o0 (c o1 v1)
-               const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]);
-               const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
-               const Type   c = cov->c();
-               const Type& v1 = cov->v();
-               const details::operator_type o0 = operation;
-               const details::operator_type o1 = cov->operation();
-
-               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
-
-               details::free_node(*(expr_gen.node_allocator_),branch[1]);
-
-               expression_node_ptr result = error_node();
-
-               if (expr_gen.strength_reduction_enabled())
-               {
-                  // v0 / (c / v1) --> (vovoc) (v0 * v1) / c
-                  if ((details::e_div == o0) && (details::e_div == o1))
-                  {
-                     const bool synthesis_result =
-                        synthesize_sf3ext_expression::
-                           template compile<vtype,vtype,ctype>(expr_gen,"(t*t)/t",v0,v1,c,result);
-
-                     exprtk_debug(("v0 / (c / v1) --> (vovoc) (v0 * v1) / c\n"));
-
-                     return (synthesis_result) ? result : error_node();
-                  }
-               }
-
-               if (synthesize_sf3ext_expression::template compile<vtype,ctype,vtype>(expr_gen,id(expr_gen,o0,o1),v0,c,v1,result))
-                  return result;
-               else if (!expr_gen.valid_operator(o0,f0))
-                  return error_node();
-               else if (!expr_gen.valid_operator(o1,f1))
-                  return error_node();
-               else
-                  return node_type::allocate(*(expr_gen.node_allocator_),v0,c,v1,f0,f1);
+            else if (details::imatch(current_token().value,symbol_null))
+            {
+                return parse_null_statement();
             }
-
-            static inline std::string id(expression_generator<Type>& expr_gen,
-                                         const details::operator_type o0, const details::operator_type o1)
+#ifndef exprtk_disable_break_continue
+            else if (details::imatch(current_token().value,symbol_break))
             {
-               return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)");
+                return parse_break_statement();
             }
-         };
-
-         struct synthesize_covov_expression0
-         {
-            typedef typename covov_t::type0 node_type;
-            typedef typename covov_t::sf3_type sf3_type;
-
-            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
-                                                      const details::operator_type& operation,
-                                                      expression_node_ptr (&branch)[2])
-            {
-               // (c o0 v0) o1 (v1)
-               const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]);
-               const Type   c = cov->c();
-               const Type& v0 = cov->v();
-               const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
-               const details::operator_type o0 = cov->operation();
-               const details::operator_type o1 = operation;
-
-               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
-
-               details::free_node(*(expr_gen.node_allocator_),branch[0]);
-
-               expression_node_ptr result = error_node();
-
-               if (expr_gen.strength_reduction_enabled())
-               {
-                  // (c / v0) / v1 --> (covov) c / (v0 * v1)
-                  if ((details::e_div == o0) && (details::e_div == o1))
-                  {
-                     const bool synthesis_result =
-                        synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen,"t/(t*t)",c,v0,v1,result);
-
-                     exprtk_debug(("(c / v0) / v1 --> (covov) c / (v0 * v1)\n"));
-
-                     return (synthesis_result) ? result : error_node();
-                  }
-               }
-
-               if (synthesize_sf3ext_expression::template compile<ctype,vtype,vtype>(expr_gen,id(expr_gen,o0,o1),c,v0,v1,result))
-                  return result;
-               else if (!expr_gen.valid_operator(o0,f0))
-                  return error_node();
-               else if (!expr_gen.valid_operator(o1,f1))
-                  return error_node();
-               else
-                  return node_type::allocate(*(expr_gen.node_allocator_),c,v0,v1,f0,f1);
+            else if (details::imatch(current_token().value,symbol_continue))
+            {
+                return parse_continue_statement();
             }
-
-            static inline std::string id(expression_generator<Type>& expr_gen,
-                                         const details::operator_type o0, const details::operator_type o1)
+#endif
+            else if (details::imatch(current_token().value,symbol_var))
             {
-               return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t");
+                return parse_define_var_statement();
             }
-         };
-
-         struct synthesize_covov_expression1
-         {
-            typedef typename covov_t::type1 node_type;
-            typedef typename covov_t::sf3_type sf3_type;
-
-            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
-                                                      const details::operator_type& operation,
-                                                      expression_node_ptr (&branch)[2])
-            {
-               // (c) o0 (v0 o1 v1)
-               const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]);
-               const Type   c = static_cast<details::literal_node<Type>*>(branch[0])->value();
-               const Type& v0 = vov->v0();
-               const Type& v1 = vov->v1();
-               const details::operator_type o0 = operation;
-               const details::operator_type o1 = vov->operation();
-
-               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
-
-               details::free_node(*(expr_gen.node_allocator_),branch[0]);
-               details::free_node(*(expr_gen.node_allocator_),branch[1]);
-
-               expression_node_ptr result = error_node();
-
-               if (expr_gen.strength_reduction_enabled())
-               {
-                  // c / (v0 / v1) --> (covov) (c * v1) / v0
-                  if ((details::e_div == o0) && (details::e_div == o1))
-                  {
-                     const bool synthesis_result =
-                        synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",c,v1,v0,result);
-
-                     exprtk_debug(("c / (v0 / v1) --> (covov) (c * v1) / v0\n"));
-
-                     return (synthesis_result) ? result : error_node();
-                  }
-               }
-
-               if (synthesize_sf3ext_expression::template compile<ctype,vtype,vtype>(expr_gen,id(expr_gen,o0,o1),c,v0,v1,result))
-                  return result;
-               else if (!expr_gen.valid_operator(o0,f0))
-                  return error_node();
-               else if (!expr_gen.valid_operator(o1,f1))
-                  return error_node();
-               else
-                  return node_type::allocate(*(expr_gen.node_allocator_),c,v0,v1,f0,f1);
+            else if (details::imatch(current_token().value,symbol_swap))
+            {
+                return parse_swap_statement();
             }
-
-            static inline std::string id(expression_generator<Type>& expr_gen, const details::operator_type o0, const details::operator_type o1)
+            else if (details::imatch(current_token().value,symbol_return))
             {
-               return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)");
+                return parse_return_statement();
             }
-         };
-
-         struct synthesize_covoc_expression0
-         {
-            typedef typename covoc_t::type0 node_type;
-            typedef typename covoc_t::sf3_type sf3_type;
-
-            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
-                                                      const details::operator_type& operation,
-                                                      expression_node_ptr (&branch)[2])
-            {
-               // (c0 o0 v) o1 (c1)
-               const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]);
-               const Type  c0 = cov->c();
-               const Type&  v = cov->v();
-               const Type  c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
-               const details::operator_type o0 = cov->operation();
-               const details::operator_type o1 = operation;
-
-               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
-
-               details::free_node(*(expr_gen.node_allocator_),branch[0]);
-               details::free_node(*(expr_gen.node_allocator_),branch[1]);
-
-               expression_node_ptr result = error_node();
-
-               if (expr_gen.strength_reduction_enabled())
-               {
-                  // (c0 + v) + c1 --> (cov) (c0 + c1) + v
-                  if ((details::e_add == o0) && (details::e_add == o1))
-                  {
-                     exprtk_debug(("(c0 + v) + c1 --> (cov) (c0 + c1) + v\n"));
-
-                     return expr_gen.node_allocator_->
-                               template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1,v);
-                  }
-                  // (c0 + v) - c1 --> (cov) (c0 - c1) + v
-                  else if ((details::e_add == o0) && (details::e_sub == o1))
-                  {
-                     exprtk_debug(("(c0 + v) - c1 --> (cov) (c0 - c1) + v\n"));
-
-                     return expr_gen.node_allocator_->
-                               template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1,v);
-                  }
-                  // (c0 - v) + c1 --> (cov) (c0 + c1) - v
-                  else if ((details::e_sub == o0) && (details::e_add == o1))
-                  {
-                     exprtk_debug(("(c0 - v) + c1 --> (cov) (c0 + c1) - v\n"));
-
-                     return expr_gen.node_allocator_->
-                               template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1,v);
-                  }
-                  // (c0 - v) - c1 --> (cov) (c0 - c1) - v
-                  else if ((details::e_sub == o0) && (details::e_sub == o1))
-                  {
-                     exprtk_debug(("(c0 - v) - c1 --> (cov) (c0 - c1) - v\n"));
-
-                     return expr_gen.node_allocator_->
-                               template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1,v);
-                  }
-                  // (c0 * v) * c1 --> (cov) (c0 * c1) * v
-                  else if ((details::e_mul == o0) && (details::e_mul == o1))
-                  {
-                     exprtk_debug(("(c0 * v) * c1 --> (cov) (c0 * c1) * v\n"));
-
-                     return expr_gen.node_allocator_->
-                               template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1,v);
-                  }
-                  // (c0 * v) / c1 --> (cov) (c0 / c1) * v
-                  else if ((details::e_mul == o0) && (details::e_div == o1))
-                  {
-                     exprtk_debug(("(c0 * v) / c1 --> (cov) (c0 / c1) * v\n"));
-
-                     return expr_gen.node_allocator_->
-                               template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1,v);
-                  }
-                  // (c0 / v) * c1 --> (cov) (c0 * c1) / v
-                  else if ((details::e_div == o0) && (details::e_mul == o1))
-                  {
-                     exprtk_debug(("(c0 / v) * c1 --> (cov) (c0 * c1) / v\n"));
-
-                     return expr_gen.node_allocator_->
-                               template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1,v);
-                  }
-                  // (c0 / v) / c1 --> (cov) (c0 / c1) / v
-                  else if ((details::e_div == o0) && (details::e_div == o1))
-                  {
-                     exprtk_debug(("(c0 / v) / c1 --> (cov) (c0 / c1) / v\n"));
-
-                     return expr_gen.node_allocator_->
-                               template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1,v);
-                  }
-               }
-
-               if (synthesize_sf3ext_expression::template compile<ctype,vtype,ctype>(expr_gen,id(expr_gen,o0,o1),c0,v,c1,result))
-                  return result;
-               else if (!expr_gen.valid_operator(o0,f0))
-                  return error_node();
-               else if (!expr_gen.valid_operator(o1,f1))
-                  return error_node();
-               else
-                  return node_type::allocate(*(expr_gen.node_allocator_),c0,v,c1,f0,f1);
+            else if (symtab_store_.valid() || !sem_.empty())
+            {
+                return parse_symtab_symbol();
             }
-
-            static inline std::string id(expression_generator<Type>& expr_gen,
-                                         const details::operator_type o0, const details::operator_type o1)
+            else
             {
-               return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t");
+                set_error(
+                          make_error(parser_error::e_symtab,
+                                     current_token(),
+                                     "ERR185 - Variable or function detected, yet symbol-table is invalid, Symbol: " + current_token().value));
+                
+                return error_node();
+            }
+        }
+        
+        inline expression_node_ptr parse_branch(precedence_level precedence = e_level00)
+        {
+            expression_node_ptr branch = error_node();
+            
+            if (token_t::e_number == current_token().type)
+            {
+                T numeric_value = T(0);
+                
+                if (details::string_to_real(current_token().value,numeric_value))
+                {
+                    expression_node_ptr literal_exp = expression_generator_(numeric_value);
+                    next_token();
+                    branch = literal_exp;
+                }
+                else
+                {
+                    set_error(
+                              make_error(parser_error::e_numeric,
+                                         current_token(),
+                                         "ERR186 - Failed to convert '" + current_token().value + "' to a number"));
+                    
+                    return error_node();
+                }
+            }
+            else if (token_t::e_symbol == current_token().type)
+            {
+                branch = parse_symbol();
+            }
+#ifndef exprtk_disable_string_capabilities
+            else if (token_t::e_string == current_token().type)
+            {
+                branch = parse_const_string();
             }
-         };
-
-         struct synthesize_covoc_expression1
-         {
-            typedef typename covoc_t::type1 node_type;
-            typedef typename covoc_t::sf3_type sf3_type;
-
-            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
-                                                      const details::operator_type& operation,
-                                                      expression_node_ptr (&branch)[2])
-            {
-               // (c0) o0 (v o1 c1)
-               const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]);
-               const Type  c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
-               const Type&  v = voc->v();
-               const Type  c1 = voc->c();
-               const details::operator_type o0 = operation;
-               const details::operator_type o1 = voc->operation();
-
-               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
-
-               details::free_node(*(expr_gen.node_allocator_),branch[0]);
-               details::free_node(*(expr_gen.node_allocator_),branch[1]);
-
-               expression_node_ptr result = error_node();
-
-               if (expr_gen.strength_reduction_enabled())
-               {
-                  // (c0) + (v + c1) --> (cov) (c0 + c1) + v
-                  if ((details::e_add == o0) && (details::e_add == o1))
-                  {
-                     exprtk_debug(("(c0) + (v + c1) --> (cov) (c0 + c1) + v\n"));
-
-                     return expr_gen.node_allocator_->
-                               template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1,v);
-                  }
-                  // (c0) + (v - c1) --> (cov) (c0 - c1) + v
-                  else if ((details::e_add == o0) && (details::e_sub == o1))
-                  {
-                     exprtk_debug(("(c0) + (v - c1) --> (cov) (c0 - c1) + v\n"));
-
-                     return expr_gen.node_allocator_->
-                               template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1,v);
-                  }
-                  // (c0) - (v + c1) --> (cov) (c0 - c1) - v
-                  else if ((details::e_sub == o0) && (details::e_add == o1))
-                  {
-                     exprtk_debug(("(c0) - (v + c1) --> (cov) (c0 - c1) - v\n"));
-
-                     return expr_gen.node_allocator_->
-                               template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1,v);
-                  }
-                  // (c0) - (v - c1) --> (cov) (c0 + c1) - v
-                  else if ((details::e_sub == o0) && (details::e_sub == o1))
-                  {
-                     exprtk_debug(("(c0) - (v - c1) --> (cov) (c0 + c1) - v\n"));
-
-                     return expr_gen.node_allocator_->
-                               template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1,v);
-                  }
-                  // (c0) * (v * c1) --> (voc) v * (c0 * c1)
-                  else if ((details::e_mul == o0) && (details::e_mul == o1))
-                  {
-                     exprtk_debug(("(c0) * (v * c1) --> (voc) v * (c0 * c1)\n"));
-
-                     return expr_gen.node_allocator_->
-                               template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1,v);
-                  }
-                  // (c0) * (v / c1) --> (cov) (c0 / c1) * v
-                  else if ((details::e_mul == o0) && (details::e_div == o1))
-                  {
-                     exprtk_debug(("(c0) * (v / c1) --> (cov) (c0 / c1) * v\n"));
-
-                     return expr_gen.node_allocator_->
-                               template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1,v);
-                  }
-                  // (c0) / (v * c1) --> (cov) (c0 / c1) / v
-                  else if ((details::e_div == o0) && (details::e_mul == o1))
-                  {
-                     exprtk_debug(("(c0) / (v * c1) --> (cov) (c0 / c1) / v\n"));
-
-                     return expr_gen.node_allocator_->
-                               template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1,v);
-                  }
-                  // (c0) / (v / c1) --> (cov) (c0 * c1) / v
-                  else if ((details::e_div == o0) && (details::e_div == o1))
-                  {
-                     exprtk_debug(("(c0) / (v / c1) --> (cov) (c0 * c1) / v\n"));
-
-                     return expr_gen.node_allocator_->
-                               template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1,v);
-                  }
-               }
-
-               if (synthesize_sf3ext_expression::template compile<ctype,vtype,ctype>(expr_gen,id(expr_gen,o0,o1),c0,v,c1,result))
-                  return result;
-               else if (!expr_gen.valid_operator(o0,f0))
-                  return error_node();
-               else if (!expr_gen.valid_operator(o1,f1))
-                  return error_node();
-               else
-                  return node_type::allocate(*(expr_gen.node_allocator_),c0,v,c1,f0,f1);
+#endif
+            else if (token_t::e_lbracket == current_token().type)
+            {
+                next_token();
+                
+                if (0 == (branch = parse_expression()))
+                    return error_node();
+                else if (!token_is(token_t::e_rbracket))
+                {
+                    set_error(
+                              make_error(parser_error::e_syntax,
+                                         current_token(),
+                                         "ERR187 - Expected ')' instead of: '" + current_token().value + "'"));
+                    
+                    free_node(node_allocator_,branch);
+                    
+                    return error_node();
+                }
+                else if (!post_bracket_process(token_t::e_lbracket,branch))
+                {
+                    free_node(node_allocator_,branch);
+                    
+                    return error_node();
+                }
+            }
+            else if (token_t::e_lsqrbracket == current_token().type)
+            {
+                next_token();
+                
+                if (0 == (branch = parse_expression()))
+                    return error_node();
+                else if (!token_is(token_t::e_rsqrbracket))
+                {
+                    set_error(
+                              make_error(parser_error::e_syntax,
+                                         current_token(),
+                                         "ERR188 - Expected ']' instead of: '" + current_token().value + "'"));
+                    
+                    free_node(node_allocator_,branch);
+                    
+                    return error_node();
+                }
+                else if (!post_bracket_process(token_t::e_lsqrbracket,branch))
+                {
+                    free_node(node_allocator_,branch);
+                    
+                    return error_node();
+                }
+            }
+            else if (token_t::e_lcrlbracket == current_token().type)
+            {
+                next_token();
+                
+                if (0 == (branch = parse_expression()))
+                    return error_node();
+                else if (!token_is(token_t::e_rcrlbracket))
+                {
+                    set_error(
+                              make_error(parser_error::e_syntax,
+                                         current_token(),
+                                         "ERR189 - Expected '}' instead of: '" + current_token().value + "'"));
+                    
+                    free_node(node_allocator_,branch);
+                    
+                    return error_node();
+                }
+                else if (!post_bracket_process(token_t::e_lcrlbracket,branch))
+                {
+                    free_node(node_allocator_,branch);
+                    
+                    return error_node();
+                }
+            }
+            else if (token_t::e_sub == current_token().type)
+            {
+                next_token();
+                branch = parse_expression(e_level11);
+                
+                if (
+                    branch &&
+                    !(
+                      details::is_neg_unary_node    (branch) &&
+                      simplify_unary_negation_branch(branch)
+                      )
+                    )
+                {
+                    branch = expression_generator_(details::e_neg,branch);
+                }
             }
-
-            static inline std::string id(expression_generator<Type>& expr_gen,
-                                         const details::operator_type o0, const details::operator_type o1)
+            else if (token_t::e_add == current_token().type)
             {
-               return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)");
+                next_token();
+                branch = parse_expression(e_level13);
             }
-         };
-
-         struct synthesize_cocov_expression0
-         {
-            typedef typename cocov_t::type0 node_type;
-            static inline expression_node_ptr process(expression_generator<Type>&, const details::operator_type&, expression_node_ptr (&)[2])
+            else if (token_t::e_eof == current_token().type)
             {
-               // (c0 o0 c1) o1 (v) - Not possible.
-               return error_node();
-            }
-         };
-
-         struct synthesize_cocov_expression1
-         {
-            typedef typename cocov_t::type1 node_type;
-            typedef typename cocov_t::sf3_type sf3_type;
-
-            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
-                                                      const details::operator_type& operation,
-                                                      expression_node_ptr (&branch)[2])
-            {
-               // (c0) o0 (c1 o1 v)
-               const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]);
-               const Type  c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
-               const Type  c1 = cov->c();
-               const Type&  v = cov->v();
-               const details::operator_type o0 = operation;
-               const details::operator_type o1 = cov->operation();
-
-               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
-
-               details::free_node(*(expr_gen.node_allocator_),branch[0]);
-               details::free_node(*(expr_gen.node_allocator_),branch[1]);
-
-               expression_node_ptr result = error_node();
-
-               if (expr_gen.strength_reduction_enabled())
-               {
-                  // (c0) + (c1 + v) --> (cov) (c0 + c1) + v
-                  if ((details::e_add == o0) && (details::e_add == o1))
-                  {
-                     exprtk_debug(("(c0) + (c1 + v) --> (cov) (c0 + c1) + v\n"));
-
-                     return expr_gen.node_allocator_->
-                               template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1,v);
-                  }
-                  // (c0) + (c1 - v) --> (cov) (c0 + c1) - v
-                  else if ((details::e_add == o0) && (details::e_sub == o1))
-                  {
-                     exprtk_debug(("(c0) + (c1 - v) --> (cov) (c0 + c1) - v\n"));
-
-                     return expr_gen.node_allocator_->
-                               template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1,v);
-                  }
-                  // (c0) - (c1 + v) --> (cov) (c0 - c1) - v
-                  else if ((details::e_sub == o0) && (details::e_add == o1))
-                  {
-                     exprtk_debug(("(c0) - (c1 + v) --> (cov) (c0 - c1) - v\n"));
-
-                     return expr_gen.node_allocator_->
-                               template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1,v);
-                  }
-                  // (c0) - (c1 - v) --> (cov) (c0 - c1) + v
-                  else if ((details::e_sub == o0) && (details::e_sub == o1))
-                  {
-                     exprtk_debug(("(c0) - (c1 - v) --> (cov) (c0 - c1) + v\n"));
-
-                     return expr_gen.node_allocator_->
-                               template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1,v);
-                  }
-                  // (c0) * (c1 * v) --> (cov) (c0 * c1) * v
-                  else if ((details::e_mul == o0) && (details::e_mul == o1))
-                  {
-                     exprtk_debug(("(c0) * (c1 * v) --> (cov) (c0 * c1) * v\n"));
-
-                     return expr_gen.node_allocator_->
-                               template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1,v);
-                  }
-                  // (c0) * (c1 / v) --> (cov) (c0 * c1) / v
-                  else if ((details::e_mul == o0) && (details::e_div == o1))
-                  {
-                     exprtk_debug(("(c0) * (c1 / v) --> (cov) (c0 * c1) / v\n"));
-
-                     return expr_gen.node_allocator_->
-                               template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1,v);
-                  }
-                  // (c0) / (c1 * v) --> (cov) (c0 / c1) / v
-                  else if ((details::e_div == o0) && (details::e_mul == o1))
-                  {
-                     exprtk_debug(("(c0) / (c1 * v) --> (cov) (c0 / c1) / v\n"));
-
-                     return expr_gen.node_allocator_->
-                               template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1,v);
-                  }
-                  // (c0) / (c1 / v) --> (cov) (c0 / c1) * v
-                  else if ((details::e_div == o0) && (details::e_div == o1))
-                  {
-                     exprtk_debug(("(c0) / (c1 / v) --> (cov) (c0 / c1) * v\n"));
-
-                     return expr_gen.node_allocator_->
-                               template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1,v);
-                  }
-               }
-
-               if (synthesize_sf3ext_expression::template compile<ctype,ctype,vtype>(expr_gen,id(expr_gen,o0,o1),c0,c1,v,result))
-                  return result;
-               else if (!expr_gen.valid_operator(o0,f0))
-                  return error_node();
-               else if (!expr_gen.valid_operator(o1,f1))
-                  return error_node();
-               else
-                  return node_type::allocate(*(expr_gen.node_allocator_),c0,c1,v,f0,f1);
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR190 - Premature end of expression[1]"));
+                
+                return error_node();
             }
-
-            static inline std::string id(expression_generator<Type>& expr_gen, const details::operator_type o0, const details::operator_type o1)
+            else
             {
-               return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)");
+                set_error(
+                          make_error(parser_error::e_syntax,
+                                     current_token(),
+                                     "ERR191 - Premature end of expression[2]"));
+                
+                return error_node();
             }
-         };
-
-         struct synthesize_vococ_expression0
-         {
-            typedef typename vococ_t::type0 node_type;
-            typedef typename vococ_t::sf3_type sf3_type;
-
-            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
-                                                      const details::operator_type& operation,
-                                                      expression_node_ptr (&branch)[2])
-            {
-               // (v o0 c0) o1 (c1)
-               const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]);
-               const Type&  v = voc->v();
-               const Type& c0 = voc->c();
-               const Type& c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
-               const details::operator_type o0 = voc->operation();
-               const details::operator_type o1 = operation;
-
-               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
-
-               details::free_node(*(expr_gen.node_allocator_),branch[0]);
-               details::free_node(*(expr_gen.node_allocator_),branch[1]);
-
-               expression_node_ptr result = error_node();
-
-               if (expr_gen.strength_reduction_enabled())
-               {
-                  // (v + c0) + c1 --> (voc) v + (c0 + c1)
-                  if ((details::e_add == o0) && (details::e_add == o1))
-                  {
-                     exprtk_debug(("(v + c0) + c1 --> (voc) v + (c0 + c1)\n"));
-
-                     return expr_gen.node_allocator_->
-                               template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v,c0 + c1);
-                  }
-                  // (v + c0) - c1 --> (voc) v + (c0 - c1)
-                  else if ((details::e_add == o0) && (details::e_sub == o1))
-                  {
-                     exprtk_debug(("(v + c0) - c1 --> (voc) v + (c0 - c1)\n"));
-
-                     return expr_gen.node_allocator_->
-                               template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v,c0 - c1);
-                  }
-                  // (v - c0) + c1 --> (voc) v - (c0 + c1)
-                  else if ((details::e_sub == o0) && (details::e_add == o1))
-                  {
-                     exprtk_debug(("(v - c0) + c1 --> (voc) v - (c0 + c1)\n"));
-
-                     return expr_gen.node_allocator_->
-                               template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v,c1 - c0);
-                  }
-                  // (v - c0) - c1 --> (voc) v - (c0 + c1)
-                  else if ((details::e_sub == o0) && (details::e_sub == o1))
-                  {
-                     exprtk_debug(("(v - c0) - c1 --> (voc) v - (c0 + c1)\n"));
-
-                     return expr_gen.node_allocator_->
-                               template allocate_rc<typename details::voc_node<Type,details::sub_op<Type> > >(v,c0 + c1);
-                  }
-                  // (v * c0) * c1 --> (voc) v * (c0 * c1)
-                  else if ((details::e_mul == o0) && (details::e_mul == o1))
-                  {
-                     exprtk_debug(("(v * c0) * c1 --> (voc) v * (c0 * c1)\n"));
-
-                     return expr_gen.node_allocator_->
-                               template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v,c0 * c1);
-                  }
-                  // (v * c0) / c1 --> (voc) v * (c0 / c1)
-                  else if ((details::e_mul == o0) && (details::e_div == o1))
-                  {
-                     exprtk_debug(("(v * c0) / c1 --> (voc) v * (c0 / c1)\n"));
-
-                     return expr_gen.node_allocator_->
-                               template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v,c0 / c1);
-                  }
-                  // (v / c0) * c1 --> (voc) v * (c1 / c0)
-                  else if ((details::e_div == o0) && (details::e_mul == o1))
-                  {
-                     exprtk_debug(("(v / c0) * c1 --> (voc) v * (c1 / c0)\n"));
-
-                     return expr_gen.node_allocator_->
-                               template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v,c1 / c0);
-                  }
-                  // (v / c0) / c1 --> (voc) v / (c0 * c1)
-                  else if ((details::e_div == o0) && (details::e_div == o1))
-                  {
-                     exprtk_debug(("(v / c0) / c1 --> (voc) v / (c0 * c1)\n"));
-
-                     return expr_gen.node_allocator_->
-                               template allocate_rc<typename details::voc_node<Type,details::div_op<Type> > >(v,c0 * c1);
-                  }
-               }
-
-               if (synthesize_sf3ext_expression::template compile<vtype,ctype,ctype>(expr_gen,id(expr_gen,o0,o1),v,c0,c1,result))
-                  return result;
-               else if (!expr_gen.valid_operator(o0,f0))
-                  return error_node();
-               else if (!expr_gen.valid_operator(o1,f1))
-                  return error_node();
-               else
-                  return node_type::allocate(*(expr_gen.node_allocator_),v,c0,c1,f0,f1);
+            
+            if (
+                branch                    &&
+                (e_level00 == precedence) &&
+                token_is(token_t::e_ternary,prsrhlpr_t::e_hold)
+                )
+            {
+                branch = parse_ternary_conditional_statement(branch);
+            }
+            
+            parse_pending_string_rangesize(branch);
+            
+            return branch;
+        }
+        
+        template <typename Type>
+        class expression_generator
+        {
+        public:
+            
+            typedef details::expression_node<Type>* expression_node_ptr;
+            typedef expression_node_ptr (*synthesize_functor_t)(expression_generator<T>&, const details::operator_type& operation, expression_node_ptr (&branch)[2]);
+            typedef std::map<std::string,synthesize_functor_t> synthesize_map_t;
+            typedef typename exprtk::parser<Type> parser_t;
+            typedef const Type& vtype;
+            typedef const Type  ctype;
+            
+            inline void init_synthesize_map()
+            {
+#ifndef exprtk_disable_enhanced_features
+                synthesize_map_["(v)o(v)"] = synthesize_vov_expression::process;
+                synthesize_map_["(c)o(v)"] = synthesize_cov_expression::process;
+                synthesize_map_["(v)o(c)"] = synthesize_voc_expression::process;
+                
+#define register_synthezier(S)                      \
+synthesize_map_[S ::node_type::id()] = S ::process; \
+
+                register_synthezier(synthesize_vovov_expression0)
+                register_synthezier(synthesize_vovov_expression1)
+                register_synthezier(synthesize_vovoc_expression0)
+                register_synthezier(synthesize_vovoc_expression1)
+                register_synthezier(synthesize_vocov_expression0)
+                register_synthezier(synthesize_vocov_expression1)
+                register_synthezier(synthesize_covov_expression0)
+                register_synthezier(synthesize_covov_expression1)
+                register_synthezier(synthesize_covoc_expression0)
+                register_synthezier(synthesize_covoc_expression1)
+                register_synthezier(synthesize_cocov_expression1)
+                register_synthezier(synthesize_vococ_expression0)
+                
+                register_synthezier(synthesize_vovovov_expression0)
+                register_synthezier(synthesize_vovovoc_expression0)
+                register_synthezier(synthesize_vovocov_expression0)
+                register_synthezier(synthesize_vocovov_expression0)
+                register_synthezier(synthesize_covovov_expression0)
+                register_synthezier(synthesize_covocov_expression0)
+                register_synthezier(synthesize_vocovoc_expression0)
+                register_synthezier(synthesize_covovoc_expression0)
+                register_synthezier(synthesize_vococov_expression0)
+                
+                register_synthezier(synthesize_vovovov_expression1)
+                register_synthezier(synthesize_vovovoc_expression1)
+                register_synthezier(synthesize_vovocov_expression1)
+                register_synthezier(synthesize_vocovov_expression1)
+                register_synthezier(synthesize_covovov_expression1)
+                register_synthezier(synthesize_covocov_expression1)
+                register_synthezier(synthesize_vocovoc_expression1)
+                register_synthezier(synthesize_covovoc_expression1)
+                register_synthezier(synthesize_vococov_expression1)
+                
+                register_synthezier(synthesize_vovovov_expression2)
+                register_synthezier(synthesize_vovovoc_expression2)
+                register_synthezier(synthesize_vovocov_expression2)
+                register_synthezier(synthesize_vocovov_expression2)
+                register_synthezier(synthesize_covovov_expression2)
+                register_synthezier(synthesize_covocov_expression2)
+                register_synthezier(synthesize_vocovoc_expression2)
+                register_synthezier(synthesize_covovoc_expression2)
+                
+                register_synthezier(synthesize_vovovov_expression3)
+                register_synthezier(synthesize_vovovoc_expression3)
+                register_synthezier(synthesize_vovocov_expression3)
+                register_synthezier(synthesize_vocovov_expression3)
+                register_synthezier(synthesize_covovov_expression3)
+                register_synthezier(synthesize_covocov_expression3)
+                register_synthezier(synthesize_vocovoc_expression3)
+                register_synthezier(synthesize_covovoc_expression3)
+                register_synthezier(synthesize_vococov_expression3)
+                
+                register_synthezier(synthesize_vovovov_expression4)
+                register_synthezier(synthesize_vovovoc_expression4)
+                register_synthezier(synthesize_vovocov_expression4)
+                register_synthezier(synthesize_vocovov_expression4)
+                register_synthezier(synthesize_covovov_expression4)
+                register_synthezier(synthesize_covocov_expression4)
+                register_synthezier(synthesize_vocovoc_expression4)
+                register_synthezier(synthesize_covovoc_expression4)
+#endif
             }
-
-            static inline std::string id(expression_generator<Type>& expr_gen,
-                                         const details::operator_type o0, const details::operator_type o1)
+            
+            inline void set_parser(parser_t& p)
             {
-               return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t");
+                parser_ = &p;
             }
-         };
-
-         struct synthesize_vococ_expression1
-         {
-            typedef typename vococ_t::type0 node_type;
-
-            static inline expression_node_ptr process(expression_generator<Type>&, const details::operator_type&, expression_node_ptr (&)[2])
+            
+            inline void set_uom(unary_op_map_t& unary_op_map)
             {
-               // (v) o0 (c0 o1 c1) - Not possible.
-               exprtk_debug(("(v) o0 (c0 o1 c1) - Not possible.\n"));
-               return error_node();
-            }
-         };
-
-         struct synthesize_vovovov_expression0
-         {
-            typedef typename vovovov_t::type0 node_type;
-            typedef typename vovovov_t::sf4_type sf4_type;
-            typedef typename node_type::T0 T0;
-            typedef typename node_type::T1 T1;
-            typedef typename node_type::T2 T2;
-            typedef typename node_type::T3 T3;
-
-            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
-                                                      const details::operator_type& operation,
-                                                      expression_node_ptr (&branch)[2])
-            {
-               // (v0 o0 v1) o1 (v2 o2 v3)
-               const details::vov_base_node<Type>* vov0 = static_cast<details::vov_base_node<Type>*>(branch[0]);
-               const details::vov_base_node<Type>* vov1 = static_cast<details::vov_base_node<Type>*>(branch[1]);
-               const Type& v0 = vov0->v0();
-               const Type& v1 = vov0->v1();
-               const Type& v2 = vov1->v0();
-               const Type& v3 = vov1->v1();
-               const details::operator_type o0 = vov0->operation();
-               const details::operator_type o1 = operation;
-               const details::operator_type o2 = vov1->operation();
-
-               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
-
-               details::free_node(*(expr_gen.node_allocator_),branch[0]);
-               details::free_node(*(expr_gen.node_allocator_),branch[1]);
-
-               expression_node_ptr result = error_node();
-
-               if (expr_gen.strength_reduction_enabled())
-               {
-                  // (v0 / v1) * (v2 / v3) --> (vovovov) (v0 * v2) / (v1 * v3)
-                  if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
-                  {
-                     const bool synthesis_result =
-                        synthesize_sf4ext_expression::
-                           template compile<vtype,vtype,vtype,vtype>(expr_gen,"(t*t)/(t*t)",v0,v2,v1,v3,result);
-
-                     exprtk_debug(("(v0 / v1) * (v2 / v3) --> (vovovov) (v0 * v2) / (v1 * v3)\n"));
-
-                     return (synthesis_result) ? result : error_node();
-                  }
-                  // (v0 / v1) / (v2 / v3) --> (vovovov) (v0 * v3) / (v1 * v2)
-                  else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
-                  {
-                     const bool synthesis_result =
-                        synthesize_sf4ext_expression::
-                           template compile<vtype,vtype,vtype,vtype>(expr_gen,"(t*t)/(t*t)",v0,v3,v1,v2,result);
-
-                     exprtk_debug(("(v0 / v1) / (v2 / v3) --> (vovovov) (v0 * v3) / (v1 * v2)\n"));
-
-                     return (synthesis_result) ? result : error_node();
-                  }
-               }
-
-               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,v3,result))
-                  return result;
-               else if (!expr_gen.valid_operator(o0,f0))
-                  return error_node();
-               else if (!expr_gen.valid_operator(o1,f1))
-                  return error_node();
-               else if (!expr_gen.valid_operator(o2,f2))
-                  return error_node();
-               else
-                  return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,v3,f0,f1,f2);
+                unary_op_map_ = &unary_op_map;
             }
-
-            static inline std::string id(expression_generator<Type>& expr_gen,
-                                         const details::operator_type o0,
-                                         const details::operator_type o1,
-                                         const details::operator_type o2)
+            
+            inline void set_bom(binary_op_map_t& binary_op_map)
             {
-               return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t)");
-            }
-         };
-
-         struct synthesize_vovovoc_expression0
-         {
-            typedef typename vovovoc_t::type0 node_type;
-            typedef typename vovovoc_t::sf4_type sf4_type;
-            typedef typename node_type::T0 T0;
-            typedef typename node_type::T1 T1;
-            typedef typename node_type::T2 T2;
-            typedef typename node_type::T3 T3;
-
-            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
-                                                      const details::operator_type& operation,
-                                                      expression_node_ptr (&branch)[2])
-            {
-               // (v0 o0 v1) o1 (v2 o2 c)
-               const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]);
-               const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]);
-               const Type& v0 = vov->v0();
-               const Type& v1 = vov->v1();
-               const Type& v2 = voc->v ();
-               const Type   c = voc->c ();
-               const details::operator_type o0 = vov->operation();
-               const details::operator_type o1 = operation;
-               const details::operator_type o2 = voc->operation();
-
-               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
-
-               details::free_node(*(expr_gen.node_allocator_),branch[0]);
-               details::free_node(*(expr_gen.node_allocator_),branch[1]);
-
-               expression_node_ptr result = error_node();
-
-               if (expr_gen.strength_reduction_enabled())
-               {
-                  // (v0 / v1) * (v2 / c) --> (vovovoc) (v0 * v2) / (v1 * c)
-                  if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
-                  {
-                     const bool synthesis_result =
-                        synthesize_sf4ext_expression::
-                           template compile<vtype,vtype,vtype,ctype>(expr_gen,"(t*t)/(t*t)",v0,v2,v1,c,result);
-
-                     exprtk_debug(("(v0 / v1) * (v2 / c) --> (vovovoc) (v0 * v2) / (v1 * c)\n"));
-
-                     return (synthesis_result) ? result : error_node();
-                  }
-                  // (v0 / v1) / (v2 / c) --> (vocovov) (v0 * c) / (v1 * v2)
-                  if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
-                  {
-                     const bool synthesis_result =
-                        synthesize_sf4ext_expression::
-                           template compile<vtype,ctype,vtype,vtype>(expr_gen,"(t*t)/(t*t)",v0,c,v1,v2,result);
-
-                     exprtk_debug(("(v0 / v1) / (v2 / c) --> (vocovov) (v0 * c) / (v1 * v2)\n"));
-
-                     return (synthesis_result) ? result : error_node();
-                  }
-               }
-
-               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,c,result))
-                  return result;
-               else if (!expr_gen.valid_operator(o0,f0))
-                  return error_node();
-               else if (!expr_gen.valid_operator(o1,f1))
-                  return error_node();
-               else if (!expr_gen.valid_operator(o2,f2))
-                  return error_node();
-               else
-                  return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,c,f0,f1,f2);
+                binary_op_map_ = &binary_op_map;
             }
-
-            static inline std::string id(expression_generator<Type>& expr_gen,
-                                         const details::operator_type o0,
-                                         const details::operator_type o1,
-                                         const details::operator_type o2)
+            
+            inline void set_ibom(inv_binary_op_map_t& inv_binary_op_map)
             {
-               return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t)");
-            }
-         };
-
-         struct synthesize_vovocov_expression0
-         {
-            typedef typename vovocov_t::type0 node_type;
-            typedef typename vovocov_t::sf4_type sf4_type;
-            typedef typename node_type::T0 T0;
-            typedef typename node_type::T1 T1;
-            typedef typename node_type::T2 T2;
-            typedef typename node_type::T3 T3;
-
-            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
-                                                      const details::operator_type& operation,
-                                                      expression_node_ptr (&branch)[2])
-            {
-               // (v0 o0 v1) o1 (c o2 v2)
-               const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]);
-               const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]);
-               const Type& v0 = vov->v0();
-               const Type& v1 = vov->v1();
-               const Type& v2 = cov->v ();
-               const Type   c = cov->c ();
-               const details::operator_type o0 = vov->operation();
-               const details::operator_type o1 = operation;
-               const details::operator_type o2 = cov->operation();
-
-               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
-
-               details::free_node(*(expr_gen.node_allocator_),branch[0]);
-               details::free_node(*(expr_gen.node_allocator_),branch[1]);
-
-               expression_node_ptr result = error_node();
-
-               if (expr_gen.strength_reduction_enabled())
-               {
-                  // (v0 / v1) * (c / v2) --> (vocovov) (v0 * c) / (v1 * v2)
-                  if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
-                  {
-                     const bool synthesis_result =
-                        synthesize_sf4ext_expression::
-                           template compile<vtype,ctype,vtype,vtype>(expr_gen,"(t*t)/(t*t)",v0,c,v1,v2,result);
-
-                     exprtk_debug(("(v0 / v1) * (c / v2) --> (vocovov) (v0 * c) / (v1 * v2)\n"));
-
-                     return (synthesis_result) ? result : error_node();
-                  }
-                  // (v0 / v1) / (c / v2) --> (vovovoc) (v0 * v2) / (v1 * c)
-                  if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
-                  {
-                     const bool synthesis_result =
-                        synthesize_sf4ext_expression::
-                           template compile<vtype,vtype,vtype,ctype>(expr_gen,"(t*t)/(t*t)",v0,v2,v1,c,result);
-
-                     exprtk_debug(("(v0 / v1) / (c / v2) --> (vovovoc) (v0 * v2) / (v1 * c)\n"));
-
-                     return (synthesis_result) ? result : error_node();
-                  }
-               }
-
-               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,c,v2,result))
-                  return result;
-               else if (!expr_gen.valid_operator(o0,f0))
-                  return error_node();
-               else if (!expr_gen.valid_operator(o1,f1))
-                  return error_node();
-               else if (!expr_gen.valid_operator(o2,f2))
-                  return error_node();
-               else
-                  return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,c,v2,f0,f1,f2);
+                inv_binary_op_map_ = &inv_binary_op_map;
             }
-
-            static inline std::string id(expression_generator<Type>& expr_gen,
-                                         const details::operator_type o0,
-                                         const details::operator_type o1,
-                                         const details::operator_type o2)
+            
+            inline void set_sf3m(sf3_map_t& sf3_map)
             {
-               return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t)");
-            }
-         };
-
-         struct synthesize_vocovov_expression0
-         {
-            typedef typename vocovov_t::type0 node_type;
-            typedef typename vocovov_t::sf4_type sf4_type;
-            typedef typename node_type::T0 T0;
-            typedef typename node_type::T1 T1;
-            typedef typename node_type::T2 T2;
-            typedef typename node_type::T3 T3;
-
-            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
-                                                      const details::operator_type& operation,
-                                                      expression_node_ptr (&branch)[2])
-            {
-               // (v0 o0 c) o1 (v1 o2 v2)
-               const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]);
-               const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]);
-               const Type   c = voc->c ();
-               const Type& v0 = voc->v ();
-               const Type& v1 = vov->v0();
-               const Type& v2 = vov->v1();
-               const details::operator_type o0 = voc->operation();
-               const details::operator_type o1 = operation;
-               const details::operator_type o2 = vov->operation();
-
-               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
-
-               details::free_node(*(expr_gen.node_allocator_),branch[0]);
-               details::free_node(*(expr_gen.node_allocator_),branch[1]);
-
-               expression_node_ptr result = error_node();
-
-               if (expr_gen.strength_reduction_enabled())
-               {
-                  // (v0 / c) * (v1 / v2) --> (vovocov) (v0 * v1) / (c * v2)
-                  if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
-                  {
-                     const bool synthesis_result =
-                        synthesize_sf4ext_expression::
-                           template compile<vtype,vtype,ctype,vtype>(expr_gen,"(t*t)/(t*t)",v0,v1,c,v2,result);
-
-                     exprtk_debug(("(v0 / c) * (v1 / v2) --> (vovocov) (v0 * v1) / (c * v2)\n"));
-
-                     return (synthesis_result) ? result : error_node();
-                  }
-                  // (v0 / c) / (v1 / v2) --> (vovocov) (v0 * v2) / (c * v1)
-                  if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
-                  {
-                     const bool synthesis_result =
-                        synthesize_sf4ext_expression::
-                           template compile<vtype,vtype,ctype,vtype>(expr_gen,"(t*t)/(t*t)",v0,v2,c,v1,result);
-
-                     exprtk_debug(("(v0 / c) / (v1 / v2) --> (vovocov) (v0 * v2) / (c * v1)\n"));
-
-                     return (synthesis_result) ? result : error_node();
-                  }
-               }
-
-               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c,v1,v2,result))
-                  return result;
-               else if (!expr_gen.valid_operator(o0,f0))
-                  return error_node();
-               else if (!expr_gen.valid_operator(o1,f1))
-                  return error_node();
-               else if (!expr_gen.valid_operator(o2,f2))
-                  return error_node();
-               else
-                  return node_type::allocate(*(expr_gen.node_allocator_),v0,c,v1,v2,f0,f1,f2);
+                sf3_map_ = &sf3_map;
             }
-
-            static inline std::string id(expression_generator<Type>& expr_gen,
-                                         const details::operator_type o0,
-                                         const details::operator_type o1,
-                                         const details::operator_type o2)
+            
+            inline void set_sf4m(sf4_map_t& sf4_map)
             {
-               return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t)");
-            }
-         };
-
-         struct synthesize_covovov_expression0
-         {
-            typedef typename covovov_t::type0 node_type;
-            typedef typename covovov_t::sf4_type sf4_type;
-            typedef typename node_type::T0 T0;
-            typedef typename node_type::T1 T1;
-            typedef typename node_type::T2 T2;
-            typedef typename node_type::T3 T3;
-
-            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
-                                                      const details::operator_type& operation,
-                                                      expression_node_ptr (&branch)[2])
-            {
-               // (c o0 v0) o1 (v1 o2 v2)
-               const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]);
-               const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]);
-               const Type   c = cov->c ();
-               const Type& v0 = cov->v ();
-               const Type& v1 = vov->v0();
-               const Type& v2 = vov->v1();
-               const details::operator_type o0 = cov->operation();
-               const details::operator_type o1 = operation;
-               const details::operator_type o2 = vov->operation();
-
-               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
-
-               details::free_node(*(expr_gen.node_allocator_),branch[0]);
-               details::free_node(*(expr_gen.node_allocator_),branch[1]);
-
-               expression_node_ptr result = error_node();
-
-               if (expr_gen.strength_reduction_enabled())
-               {
-                  // (c / v0) * (v1 / v2) --> (covovov) (c * v1) / (v0 * v2)
-                  if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
-                  {
-                     const bool synthesis_result =
-                        synthesize_sf4ext_expression::
-                           template compile<ctype,vtype,vtype,vtype>(expr_gen,"(t*t)/(t*t)",c,v1,v0,v2,result);
-
-                     exprtk_debug(("(c / v0) * (v1 / v2) --> (covovov) (c * v1) / (v0 * v2)\n"));
-
-                     return (synthesis_result) ? result : error_node();
-                  }
-                  // (c / v0) / (v1 / v2) --> (covovov) (c * v2) / (v0 * v1)
-                  if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
-                  {
-                     const bool synthesis_result =
-                        synthesize_sf4ext_expression::
-                           template compile<ctype,vtype,vtype,vtype>(expr_gen,"(t*t)/(t*t)",c,v2,v0,v1,result);
-
-                     exprtk_debug(("(c / v0) / (v1 / v2) --> (covovov) (c * v2) / (v0 * v1)\n"));
-
-                     return (synthesis_result) ? result : error_node();
-                  }
-               }
-
-               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c,v0,v1,v2,result))
-                  return result;
-               else if (!expr_gen.valid_operator(o0,f0))
-                  return error_node();
-               else if (!expr_gen.valid_operator(o1,f1))
-                  return error_node();
-               else if (!expr_gen.valid_operator(o2,f2))
-                  return error_node();
-               else
-                  return node_type::allocate(*(expr_gen.node_allocator_),c,v0,v1,v2,f0,f1,f2);
+                sf4_map_ = &sf4_map;
             }
-
-            static inline std::string id(expression_generator<Type>& expr_gen,
-                                         const details::operator_type o0,
-                                         const details::operator_type o1,
-                                         const details::operator_type o2)
+            
+            inline void set_allocator(details::node_allocator& na)
             {
-               return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t)");
-            }
-         };
-
-         struct synthesize_covocov_expression0
-         {
-            typedef typename covocov_t::type0 node_type;
-            typedef typename covocov_t::sf4_type sf4_type;
-            typedef typename node_type::T0 T0;
-            typedef typename node_type::T1 T1;
-            typedef typename node_type::T2 T2;
-            typedef typename node_type::T3 T3;
-
-            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
-                                                      const details::operator_type& operation,
-                                                      expression_node_ptr (&branch)[2])
-            {
-               // (c0 o0 v0) o1 (c1 o2 v1)
-               const details::cov_base_node<Type>* cov0 = static_cast<details::cov_base_node<Type>*>(branch[0]);
-               const details::cov_base_node<Type>* cov1 = static_cast<details::cov_base_node<Type>*>(branch[1]);
-               const Type  c0 = cov0->c();
-               const Type& v0 = cov0->v();
-               const Type  c1 = cov1->c();
-               const Type& v1 = cov1->v();
-               const details::operator_type o0 = cov0->operation();
-               const details::operator_type o1 = operation;
-               const details::operator_type o2 = cov1->operation();
-
-               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
-
-               details::free_node(*(expr_gen.node_allocator_),branch[0]);
-               details::free_node(*(expr_gen.node_allocator_),branch[1]);
-
-               expression_node_ptr result = error_node();
-
-               if (expr_gen.strength_reduction_enabled())
-               {
-                  // (c0 + v0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1
-                  if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2))
-                  {
-                     const bool synthesis_result =
-                        synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen,"(t+t)+t",(c0 + c1),v0,v1,result);
-
-                     exprtk_debug(("(c0 + v0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1\n"));
-
-                     return (synthesis_result) ? result : error_node();
-                  }
-                  // (c0 + v0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1
-                  else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2))
-                  {
-                     const bool synthesis_result =
-                        synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen,"(t+t)-t",(c0 - c1),v0,v1,result);
-
-                     exprtk_debug(("(c0 + v0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1\n"));
-
-                     return (synthesis_result) ? result : error_node();
-                  }
-                  // (c0 - v0) - (c1 - v1) --> (covov) (c0 - c1) - v0 + v1
-                  else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2))
-                  {
-                     const bool synthesis_result =
-                        synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen,"(t-t)+t",(c0 - c1),v0,v1,result);
-
-                     exprtk_debug(("(c0 - v0) - (c1 - v1) --> (covov) (c0 - c1) - v0 + v1\n"));
-
-                     return (synthesis_result) ? result : error_node();
-                  }
-                  // (c0 * v0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1
-                  else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
-                  {
-                     const bool synthesis_result =
-                        synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen,"(t*t)*t",(c0 * c1),v0,v1,result);
-
-                     exprtk_debug(("(c0 * v0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1\n"));
-
-                     return (synthesis_result) ? result : error_node();
-                  }
-                  // (c0 * v0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 / v1)
-                  else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
-                  {
-                     const bool synthesis_result =
-                        synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",(c0 / c1),v0,v1,result);
-
-                     exprtk_debug(("(c0 * v0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 / v1)\n"));
-
-                     return (synthesis_result) ? result : error_node();
-                  }
-                  // (c0 / v0) * (c1 / v1) --> (covov) (c0 * c1) / (v0 * v1)
-                  else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
-                  {
-                     const bool synthesis_result =
-                        synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen,"t/(t*t)",(c0 * c1),v0,v1,result);
-
-                     exprtk_debug(("(c0 / v0) * (c1 / v1) --> (covov) (c0 * c1) / (v0 * v1)\n"));
-
-                     return (synthesis_result) ? result : error_node();
-                  }
-                  // (c0 / v0) / (c1 / v1) --> (covov) ((c0 / c1) * v1) / v0
-                  else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
-                  {
-                     const bool synthesis_result =
-                        synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",(c0 / c1),v1,v0,result);
-
-                     exprtk_debug(("(c0 / v0) / (c1 / v1) --> (covov) ((c0 / c1) * v1) / v0\n"));
-
-                     return (synthesis_result) ? result : error_node();
-                  }
-                  // (c0 * v0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)
-                  else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
-                  {
-                     const bool synthesis_result =
-                        synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen,"t*(t*t)",(c0 / c1),v0,v1,result);
-
-                     exprtk_debug(("(c0 * v0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)\n"));
-
-                     return (synthesis_result) ? result : error_node();
-                  }
-                  // (c0 / v0) / (c1 * v1) --> (covov) (c0 / c1) / (v0 * v1)
-                  else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))
-                  {
-                     const bool synthesis_result =
-                        synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen,"t/(t*t)",(c0 / c1),v0,v1,result);
-
-                     exprtk_debug(("(c0 / v0) / (c1 * v1) --> (covov) (c0 / c1) / (v0 * v1)\n"));
-
-                     return (synthesis_result) ? result : error_node();
-                  }
-                  // (c * v0) +/- (c * v1) --> (covov) c * (v0 +/- v1)
-                  else if (
-                            (std::equal_to<T>()(c0,c1)) &&
-                            (details::e_mul == o0)      &&
-                            (details::e_mul == o2)      &&
-                            (
-                              (details::e_add == o1) ||
-                              (details::e_sub == o1)
-                            )
-                          )
-                  {
-                     std::string specfunc;
-
-                     switch (o1)
-                     {
-                        case details::e_add : specfunc = "t*(t+t)"; break;
-                        case details::e_sub : specfunc = "t*(t-t)"; break;
-                        default             : return error_node();
-                     }
-
-                     const bool synthesis_result =
-                        synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen,specfunc,c0,v0,v1,result);
-
-                     exprtk_debug(("(c * v0) +/- (c * v1) --> (covov) c * (v0 +/- v1)\n"));
-
-                     return (synthesis_result) ? result : error_node();
-                  }
-               }
-
-               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,c1,v1,result))
-                  return result;
-               else if (!expr_gen.valid_operator(o0,f0))
-                  return error_node();
-               else if (!expr_gen.valid_operator(o1,f1))
-                  return error_node();
-               else if (!expr_gen.valid_operator(o2,f2))
-                  return error_node();
-               else
-                  return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,c1,v1,f0,f1,f2);
+                node_allocator_ = &na;
             }
-
-            static inline std::string id(expression_generator<Type>& expr_gen,
-                                         const details::operator_type o0,
-                                         const details::operator_type o1,
-                                         const details::operator_type o2)
+            
+            inline void set_strength_reduction_state(const bool enabled)
             {
-               return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t)");
-            }
-         };
-
-         struct synthesize_vocovoc_expression0
-         {
-            typedef typename vocovoc_t::type0 node_type;
-            typedef typename vocovoc_t::sf4_type sf4_type;
-            typedef typename node_type::T0 T0;
-            typedef typename node_type::T1 T1;
-            typedef typename node_type::T2 T2;
-            typedef typename node_type::T3 T3;
-
-            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
-                                                      const details::operator_type& operation,
-                                                      expression_node_ptr (&branch)[2])
-            {
-               // (v0 o0 c0) o1 (v1 o2 c1)
-               const details::voc_base_node<Type>* voc0 = static_cast<details::voc_base_node<Type>*>(branch[0]);
-               const details::voc_base_node<Type>* voc1 = static_cast<details::voc_base_node<Type>*>(branch[1]);
-               const Type  c0 = voc0->c();
-               const Type& v0 = voc0->v();
-               const Type  c1 = voc1->c();
-               const Type& v1 = voc1->v();
-               const details::operator_type o0 = voc0->operation();
-               const details::operator_type o1 = operation;
-               const details::operator_type o2 = voc1->operation();
-
-               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
-
-               details::free_node(*(expr_gen.node_allocator_),branch[0]);
-               details::free_node(*(expr_gen.node_allocator_),branch[1]);
-
-               expression_node_ptr result = error_node();
-
-               if (expr_gen.strength_reduction_enabled())
-               {
-                  // (v0 + c0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1
-                  if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2))
-                  {
-                     const bool synthesis_result =
-                        synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen,"(t+t)+t",(c0 + c1),v0,v1,result);
-
-                     exprtk_debug(("(v0 + c0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1\n"));
-
-                     return (synthesis_result) ? result : error_node();
-                  }
-                  // (v0 + c0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1
-                  else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2))
-                  {
-                     const bool synthesis_result =
-                        synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen,"(t+t)-t",(c0 - c1),v0,v1,result);
-
-                     exprtk_debug(("(v0 + c0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1\n"));
-
-                     return (synthesis_result) ? result : error_node();
-                  }
-                  // (v0 - c0) - (v1 - c1) --> (covov) (c1 - c0) + v0 - v1
-                  else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2))
-                  {
-                     const bool synthesis_result =
-                        synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen,"(t+t)-t",(c1 - c0),v0,v1,result);
-
-                     exprtk_debug(("(v0 - c0) - (v1 - c1) --> (covov) (c1 - c0) + v0 - v1\n"));
-
-                     return (synthesis_result) ? result : error_node();
-                  }
-                  // (v0 * c0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1
-                  else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
-                  {
-                     const bool synthesis_result =
-                        synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen,"(t*t)*t",(c0 * c1),v0,v1,result);
-
-                     exprtk_debug(("(v0 * c0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1\n"));
-
-                     return (synthesis_result) ? result : error_node();
-                  }
-                  // (v0 * c0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)
-                  else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
-                  {
-                     const bool synthesis_result =
-                        synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",(c0 / c1),v0,v1,result);
-
-                     exprtk_debug(("(v0 * c0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)\n"));
-
-                     return (synthesis_result) ? result : error_node();
-                  }
-                  // (v0 / c0) * (v1 / c1) --> (covov) (1 / (c0 * c1)) * v0 * v1
-                  else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
-                  {
-                     const bool synthesis_result =
-                        synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen,"(t*t)*t",Type(1) / (c0 * c1),v0,v1,result);
-
-                     exprtk_debug(("(v0 / c0) * (v1 / c1) --> (covov) (1 / (c0 * c1)) * v0 * v1\n"));
-
-                     return (synthesis_result) ? result : error_node();
-                  }
-                  // (v0 / c0) / (v1 / c1) --> (covov) ((c1 / c0) * v0) / v1
-                  else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
-                  {
-                     const bool synthesis_result =
-                        synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",(c1 / c0),v0,v1,result);
-
-                     exprtk_debug(("(v0 / c0) / (v1 / c1) --> (covov) ((c1 / c0) * v0) / v1\n"));
-
-                     return (synthesis_result) ? result : error_node();
-                  }
-                  // (v0 * c0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)
-                  else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
-                  {
-                     const bool synthesis_result =
-                        synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen,"t*(t/t)",(c0 * c1),v0,v1,result);
-
-                     exprtk_debug(("(v0 * c0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)\n"));
-
-                     return (synthesis_result) ? result : error_node();
-                  }
-                  // (v0 / c0) / (v1 * c1) --> (covov) (1 / (c0 * c1)) * v0 / v1
-                  else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))
-                  {
-                     const bool synthesis_result =
-                        synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen,"t*(t/t)",Type(1) / (c0 * c1),v0,v1,result);
-
-                     exprtk_debug(("(v0 / c0) / (v1 * c1) --> (covov) (1 / (c0 * c1)) * v0 / v1\n"));
-
-                     return (synthesis_result) ? result : error_node();
-                  }
-                  // (v0 / c0) * (v1 + c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 + c1)
-                  else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_add == o2))
-                  {
-                     const bool synthesis_result =
-                        synthesize_sf4ext_expression::
-                           template compile<vtype,ctype,vtype,ctype>(expr_gen,"(t*t)*(t+t)",v0,T(1) / c0,v1,c1,result);
-
-                     exprtk_debug(("(v0 / c0) * (v1 + c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 + c1)\n"));
-
-                     return (synthesis_result) ? result : error_node();
-                  }
-                  // (v0 / c0) * (v1 - c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 - c1)
-                  else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_sub == o2))
-                  {
-                     const bool synthesis_result =
-                        synthesize_sf4ext_expression::
-                           template compile<vtype,ctype,vtype,ctype>(expr_gen,"(t*t)*(t-t)",v0,T(1) / c0,v1,c1,result);
-
-                     exprtk_debug(("(v0 / c0) * (v1 - c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 - c1)\n"));
-
-                     return (synthesis_result) ? result : error_node();
-                  }
-                  // (v0 * c) +/- (v1 * c) --> (covov) c * (v0 +/- v1)
-                  else if (
-                            (std::equal_to<T>()(c0,c1)) &&
-                            (details::e_mul == o0)      &&
-                            (details::e_mul == o2)      &&
-                            (
-                              (details::e_add == o1) ||
-                              (details::e_sub == o1)
-                            )
-                          )
-                  {
-                     std::string specfunc;
-
-                     switch (o1)
-                     {
-                        case details::e_add : specfunc = "t*(t+t)"; break;
-                        case details::e_sub : specfunc = "t*(t-t)"; break;
-                        default             : return error_node();
-                     }
-
-                     const bool synthesis_result =
-                        synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen,specfunc,c0,v0,v1,result);
-
-                     exprtk_debug(("(v0 * c) +/- (v1 * c) --> (covov) c * (v0 +/- v1)\n"));
-
-                     return (synthesis_result) ? result : error_node();
-                  }
-                  // (v0 / c) +/- (v1 / c) --> (vovoc) (v0 +/- v1) / c
-                  else if (
-                            (std::equal_to<T>()(c0,c1)) &&
-                            (details::e_div == o0)      &&
-                            (details::e_div == o2)      &&
-                            (
-                              (details::e_add == o1) ||
-                              (details::e_sub == o1)
-                            )
-                          )
-                  {
-                     std::string specfunc;
-
-                     switch (o1)
-                     {
-                        case details::e_add : specfunc = "(t+t)/t"; break;
-                        case details::e_sub : specfunc = "(t-t)/t"; break;
-                        default             : return error_node();
-                     }
-
-                     const bool synthesis_result =
-                        synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen,specfunc,c0,v0,v1,result);
-
-                     exprtk_debug(("(v0 / c) +/- (v1 / c) --> (vovoc) (v0 +/- v1) / c\n"));
-
-                     return (synthesis_result) ? result : error_node();
-                  }
-               }
-
-               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c0,v1,c1,result))
-                  return result;
-               else if (!expr_gen.valid_operator(o0,f0))
-                  return error_node();
-               else if (!expr_gen.valid_operator(o1,f1))
-                  return error_node();
-               else if (!expr_gen.valid_operator(o2,f2))
-                  return error_node();
-               else
-                  return node_type::allocate(*(expr_gen.node_allocator_),v0,c0,v1,c1,f0,f1,f2);
+                strength_reduction_enabled_ = enabled;
             }
-
-            static inline std::string id(expression_generator<Type>& expr_gen,
-                                         const details::operator_type o0,
-                                         const details::operator_type o1,
-                                         const details::operator_type o2)
+            
+            inline bool strength_reduction_enabled() const
             {
-               return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t)");
-            }
-         };
-
-         struct synthesize_covovoc_expression0
-         {
-            typedef typename covovoc_t::type0 node_type;
-            typedef typename covovoc_t::sf4_type sf4_type;
-            typedef typename node_type::T0 T0;
-            typedef typename node_type::T1 T1;
-            typedef typename node_type::T2 T2;
-            typedef typename node_type::T3 T3;
-
-            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
-                                                      const details::operator_type& operation,
-                                                      expression_node_ptr (&branch)[2])
-            {
-               // (c0 o0 v0) o1 (v1 o2 c1)
-               const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]);
-               const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]);
-               const Type  c0 = cov->c();
-               const Type& v0 = cov->v();
-               const Type  c1 = voc->c();
-               const Type& v1 = voc->v();
-               const details::operator_type o0 = cov->operation();
-               const details::operator_type o1 = operation;
-               const details::operator_type o2 = voc->operation();
-
-               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
-
-               details::free_node(*(expr_gen.node_allocator_),branch[0]);
-               details::free_node(*(expr_gen.node_allocator_),branch[1]);
-
-               expression_node_ptr result = error_node();
-
-               if (expr_gen.strength_reduction_enabled())
-               {
-                  // (c0 + v0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1
-                  if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2))
-                  {
-                     const bool synthesis_result =
-                        synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen,"(t+t)+t",(c0 + c1),v0,v1,result);
-
-                     exprtk_debug(("(c0 + v0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1\n"));
-
-                     return (synthesis_result) ? result : error_node();
-                  }
-                  // (c0 + v0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1
-                  else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2))
-                  {
-                     const bool synthesis_result =
-                        synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen,"(t+t)-t",(c0 - c1),v0,v1,result);
-
-                     exprtk_debug(("(c0 + v0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1\n"));
-
-                     return (synthesis_result) ? result : error_node();
-                  }
-                  // (c0 - v0) - (v1 - c1) --> (covov) (c0 + c1) - v0 - v1
-                  else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2))
-                  {
-                     const bool synthesis_result =
-                        synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen,"t-(t+t)",(c0 + c1),v0,v1,result);
-
-                     exprtk_debug(("(c0 - v0) - (v1 - c1) --> (covov) (c0 + c1) - v0 - v1\n"));
-
-                     return (synthesis_result) ? result : error_node();
-                  }
-                  // (c0 * v0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1
-                  else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
-                  {
-                     const bool synthesis_result =
-                        synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen,"(t*t)*t",(c0 * c1),v0,v1,result);
-
-                     exprtk_debug(("(c0 * v0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1\n"));
-
-                     return (synthesis_result) ? result : error_node();
-                  }
-                  // (c0 * v0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)
-                  else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
-                  {
-                     const bool synthesis_result =
-                        synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",(c0 / c1),v0,v1,result);
-
-                     exprtk_debug(("(c0 * v0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)\n"));
-
-                     return (synthesis_result) ? result : error_node();
-                  }
-                  // (c0 / v0) * (v1 / c1) --> (covov) (c0 / c1) * (v1 / v0)
-                  else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
-                  {
-                     const bool synthesis_result =
-                        synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen,"t*(t/t)",(c0 / c1),v1,v0,result);
-
-                     exprtk_debug(("(c0 / v0) * (v1 / c1) --> (covov) (c0 / c1) * (v1 / v0)\n"));
-
-                     return (synthesis_result) ? result : error_node();
-                  }
-                  // (c0 / v0) / (v1 / c1) --> (covov) (c0 * c1) / (v0 * v1)
-                  else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
-                  {
-                     const bool synthesis_result =
-                        synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen,"t/(t*t)",(c0 * c1),v0,v1,result);
-
-                     exprtk_debug(("(c0 / v0) / (v1 / c1) --> (covov) (c0 * c1) / (v0 * v1)\n"));
-
-                     return (synthesis_result) ? result : error_node();
-                  }
-                  // (c0 * v0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)
-                  else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
-                  {
-                     const bool synthesis_result =
-                        synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",(c0 * c1),v0,v1,result);
-
-                     exprtk_debug(("(c0 * v0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)\n"));
-
-                     return (synthesis_result) ? result : error_node();
-                  }
-                  // (c0 / v0) / (v1 * c1) --> (covov) (c0 / c1) / (v0 * v1)
-                  else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))
-                  {
-                     const bool synthesis_result =
-                        synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen,"t/(t*t)",(c0 / c1),v0,v1,result);
-
-                     exprtk_debug(("(c0 / v0) / (v1 * c1) --> (covov) (c0 / c1) / (v0 * v1)\n"));
-
-                     return (synthesis_result) ? result : error_node();
-                  }
-                  // (c * v0) +/- (v1 * c) --> (covov) c * (v0 +/- v1)
-                  else if (
-                            (std::equal_to<T>()(c0,c1)) &&
-                            (details::e_mul == o0)      &&
-                            (details::e_mul == o2)      &&
-                            (
-                              (details::e_add == o1) ||
-                              (details::e_sub == o1)
-                            )
-                          )
-                  {
-                     std::string specfunc;
-
-                     switch (o1)
-                     {
-                        case details::e_add : specfunc = "t*(t+t)"; break;
-                        case details::e_sub : specfunc = "t*(t-t)"; break;
-                        default             : return error_node();
-                     }
-
-                     const bool synthesis_result =
-                        synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen,specfunc,c0,v0,v1,result);
-
-                     exprtk_debug(("(c * v0) +/- (v1 * c) --> (covov) c * (v0 +/- v1)\n"));
-
-                     return (synthesis_result) ? result : error_node();
-                  }
-               }
-
-               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,v1,c1,result))
-                  return result;
-               else if (!expr_gen.valid_operator(o0,f0))
-                  return error_node();
-               else if (!expr_gen.valid_operator(o1,f1))
-                  return error_node();
-               else if (!expr_gen.valid_operator(o2,f2))
-                  return error_node();
-               else
-                  return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,v1,c1,f0,f1,f2);
+                return strength_reduction_enabled_;
             }
-
-            static inline std::string id(expression_generator<Type>& expr_gen,
-                                         const details::operator_type o0,
-                                         const details::operator_type o1,
-                                         const details::operator_type o2)
+            
+            inline bool valid_operator(const details::operator_type& operation, binary_functor_t& bop)
             {
-               return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t)");
-            }
-         };
-
-         struct synthesize_vococov_expression0
-         {
-            typedef typename vococov_t::type0 node_type;
-            typedef typename vococov_t::sf4_type sf4_type;
-            typedef typename node_type::T0 T0;
-            typedef typename node_type::T1 T1;
-            typedef typename node_type::T2 T2;
-            typedef typename node_type::T3 T3;
-
-            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
-                                                      const details::operator_type& operation,
-                                                      expression_node_ptr (&branch)[2])
-            {
-               // (v0 o0 c0) o1 (c1 o2 v1)
-               const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]);
-               const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]);
-               const Type  c0 = voc->c();
-               const Type& v0 = voc->v();
-               const Type  c1 = cov->c();
-               const Type& v1 = cov->v();
-               const details::operator_type o0 = voc->operation();
-               const details::operator_type o1 = operation;
-               const details::operator_type o2 = cov->operation();
-
-               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
-
-               details::free_node(*(expr_gen.node_allocator_),branch[0]);
-               details::free_node(*(expr_gen.node_allocator_),branch[1]);
-
-               expression_node_ptr result = error_node();
-
-               if (expr_gen.strength_reduction_enabled())
-               {
-                  // (v0 + c0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1
-                  if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2))
-                  {
-                     const bool synthesis_result =
-                        synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen,"(t+t)+t",(c0 + c1),v0,v1,result);
-
-                     exprtk_debug(("(v0 + c0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1\n"));
-
-                     return (synthesis_result) ? result : error_node();
-                  }
-                  // (v0 + c0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1
-                  else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2))
-                  {
-                     const bool synthesis_result =
-                        synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen,"(t+t)-t",(c0 - c1),v0,v1,result);
-
-                     exprtk_debug(("(v0 + c0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1\n"));
-
-                     return (synthesis_result) ? result : error_node();
-                  }
-                  // (v0 - c0) - (c1 - v1) --> (vovoc) v0 + v1 - (c1 + c0)
-                  else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2))
-                  {
-                     const bool synthesis_result =
-                        synthesize_sf3ext_expression::
-                           template compile<vtype,vtype,ctype>(expr_gen,"(t+t)-t",v0,v1,(c1 + c0),result);
-
-                     exprtk_debug(("(v0 - c0) - (c1 - v1) --> (vovoc) v0 + v1 - (c1 + c0)\n"));
-
-                     return (synthesis_result) ? result : error_node();
-                  }
-                  // (v0 * c0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1
-                  else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
-                  {
-                     const bool synthesis_result =
-                        synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen,"(t*t)*t",(c0 * c1),v0,v1,result);
-
-                     exprtk_debug(("(v0 * c0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1\n"));
-
-                     return (synthesis_result) ? result : error_node();
-                  }
-                  // (v0 * c0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 * v1)
-                  else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
-                  {
-                     const bool synthesis_result =
-                        synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",(c0 / c1),v0,v1,result);
-
-                     exprtk_debug(("(v0 * c0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 * v1)\n"));
-
-                     return (synthesis_result) ? result : error_node();
-                  }
-                  // (v0 / c0) * (c1 / v1) --> (covov) (c1 / c0) * (v0 / v1)
-                  else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
-                  {
-                     const bool synthesis_result =
-                        synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",(c1 / c0),v0,v1,result);
-
-                     exprtk_debug(("(v0 / c0) * (c1 / v1) --> (covov) (c1 / c0) * (v0 / v1)\n"));
-
-                     return (synthesis_result) ? result : error_node();
-                  }
-                  // (v0 * c0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)
-                  else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
-                  {
-                     const bool synthesis_result =
-                        synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen,"(t*t)*t",(c0 / c1),v0,v1,result);
-
-                     exprtk_debug(("(v0 * c0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)\n"));
-
-                     return (synthesis_result) ? result : error_node();
-                  }
-                  // (v0 / c0) / (c1 * v1) --> (covov) (1 / (c0 * c1)) * (v0 / v1)
-                  else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))
-                  {
-                     const bool synthesis_result =
-                        synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",Type(1) / (c0 * c1),v0,v1,result);
-
-                     exprtk_debug(("(v0 / c0) / (c1 * v1) --> (covov) (1 / (c0 * c1)) * (v0 / v1)\n"));
-
-                     return (synthesis_result) ? result : error_node();
-                  }
-                  // (v0 / c0) / (c1 / v1) --> (vovoc) (v0 * v1) * (1 / (c0 * c1))
-                  else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
-                  {
-                     const bool synthesis_result =
-                        synthesize_sf3ext_expression::
-                           template compile<vtype,vtype,ctype>(expr_gen,"(t*t)*t",v0,v1,Type(1) / (c0 * c1),result);
-
-                     exprtk_debug(("(v0 / c0) / (c1 / v1) --> (vovoc) (v0 * v1) * (1 / (c0 * c1))\n"));
-
-                     return (synthesis_result) ? result : error_node();
-                  }
-                  // (v0 * c) +/- (c * v1) --> (covov) c * (v0 +/- v1)
-                  else if (
-                            (std::equal_to<T>()(c0,c1)) &&
-                            (details::e_mul == o0)      &&
-                            (details::e_mul == o2)      &&
-                            (
-                              (details::e_add == o1) || (details::e_sub == o1)
-                            )
-                          )
-                  {
-                     std::string specfunc;
-                     switch (o1)
-                     {
-                        case details::e_add : specfunc = "t*(t+t)"; break;
-                        case details::e_sub : specfunc = "t*(t-t)"; break;
-                        default             : return error_node();
-                     }
-
-                     const bool synthesis_result =
-                        synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen,specfunc,c0,v0,v1,result);
-
-                     exprtk_debug(("(v0 * c) +/- (c * v1) --> (covov) c * (v0 +/- v1)\n"));
-
-                     return (synthesis_result) ? result : error_node();
-                  }
-               }
-
-               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c0,c1,v1,result))
-                  return result;
-               else if (!expr_gen.valid_operator(o0,f0))
-                  return error_node();
-               else if (!expr_gen.valid_operator(o1,f1))
-                  return error_node();
-               else if (!expr_gen.valid_operator(o2,f2))
-                  return error_node();
-               else
-                  return node_type::allocate(*(expr_gen.node_allocator_),v0,c0,c1,v1,f0,f1,f2);
+                typename binary_op_map_t::iterator bop_itr = binary_op_map_->find(operation);
+                
+                if ((*binary_op_map_).end() == bop_itr)
+                    return false;
+                
+                bop = bop_itr->second;
+                
+                return true;
             }
-
-            static inline std::string id(expression_generator<Type>& expr_gen,
-                                         const details::operator_type o0,
-                                         const details::operator_type o1,
-                                         const details::operator_type o2)
+            
+            inline bool valid_operator(const details::operator_type& operation, unary_functor_t& uop)
             {
-               return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t)");
+                typename unary_op_map_t::iterator uop_itr = unary_op_map_->find(operation);
+                
+                if ((*unary_op_map_).end() == uop_itr)
+                    return false;
+                
+                uop = uop_itr->second;
+                
+                return true;
             }
-         };
-
-         struct synthesize_vovovov_expression1
-         {
-            typedef typename vovovov_t::type1 node_type;
-            typedef typename vovovov_t::sf4_type sf4_type;
-            typedef typename node_type::T0 T0;
-            typedef typename node_type::T1 T1;
-            typedef typename node_type::T2 T2;
-            typedef typename node_type::T3 T3;
-
-            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
-                                                      const details::operator_type& operation,
-                                                      expression_node_ptr (&branch)[2])
+            
+            inline details::operator_type get_operator(const binary_functor_t& bop)
             {
-               // v0 o0 (v1 o1 (v2 o2 v3))
-               typedef typename synthesize_vovov_expression1::node_type vovov_t;
-
-               const vovov_t* vovov = static_cast<const vovov_t*>(branch[1]);
-               const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
-               const Type& v1 = vovov->t0();
-               const Type& v2 = vovov->t1();
-               const Type& v3 = vovov->t2();
-               const details::operator_type o0 = operation;
-               const details::operator_type o1 = expr_gen.get_operator(vovov->f0());
-               const details::operator_type o2 = expr_gen.get_operator(vovov->f1());
-
-               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f1 = vovov->f0();
-               binary_functor_t f2 = vovov->f1();
-
-               details::free_node(*(expr_gen.node_allocator_),branch[1]);
-
-               expression_node_ptr result = error_node();
-
-               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,v3,result))
-                  return result;
-               else if (!expr_gen.valid_operator(o0,f0))
-                  return error_node();
-
-               exprtk_debug(("v0 o0 (v1 o1 (v2 o2 v3))\n"));
-
-               return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,v3,f0,f1,f2);
+                return (*inv_binary_op_map_).find(bop)->second;
             }
-
-            static inline std::string id(expression_generator<Type>& expr_gen,
-                                         const details::operator_type o0,
-                                         const details::operator_type o1,
-                                         const details::operator_type o2)
+            
+            inline expression_node_ptr operator()(const Type& v) const
             {
-               return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t))");
+                return node_allocator_->allocate<literal_node_t>(v);
             }
-         };
-
-         struct synthesize_vovovoc_expression1
-         {
-            typedef typename vovovoc_t::type1 node_type;
-            typedef typename vovovoc_t::sf4_type sf4_type;
-            typedef typename node_type::T0 T0;
-            typedef typename node_type::T1 T1;
-            typedef typename node_type::T2 T2;
-            typedef typename node_type::T3 T3;
-
-            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
-                                                      const details::operator_type& operation,
-                                                      expression_node_ptr (&branch)[2])
+            
+#ifndef exprtk_disable_string_capabilities
+            inline expression_node_ptr operator()(const std::string& s) const
             {
-               // v0 o0 (v1 o1 (v2 o2 c))
-               typedef typename synthesize_vovoc_expression1::node_type vovoc_t;
-
-               const vovoc_t* vovoc = static_cast<const vovoc_t*>(branch[1]);
-               const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
-               const Type& v1 = vovoc->t0();
-               const Type& v2 = vovoc->t1();
-               const Type   c = vovoc->t2();
-               const details::operator_type o0 = operation;
-               const details::operator_type o1 = expr_gen.get_operator(vovoc->f0());
-               const details::operator_type o2 = expr_gen.get_operator(vovoc->f1());
-
-               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f1 = vovoc->f0();
-               binary_functor_t f2 = vovoc->f1();
-
-               details::free_node(*(expr_gen.node_allocator_),branch[1]);
-
-               expression_node_ptr result = error_node();
-
-               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,c,result))
-                  return result;
-               else if (!expr_gen.valid_operator(o0,f0))
-                  return error_node();
-
-               exprtk_debug(("v0 o0 (v1 o1 (v2 o2 c))\n"));
-
-               return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,c,f0,f1,f2);
+                return node_allocator_->allocate<string_literal_node_t>(s);
             }
-
-            static inline std::string id(expression_generator<Type>& expr_gen,
-                                         const details::operator_type o0,
-                                         const details::operator_type o1,
-                                         const details::operator_type o2)
+            
+            inline expression_node_ptr operator()(std::string& s, range_t& rp) const
             {
-               return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t))");
+                return node_allocator_->allocate_rr<string_range_node_t>(s,rp);
             }
-         };
-
-         struct synthesize_vovocov_expression1
-         {
-            typedef typename vovocov_t::type1 node_type;
-            typedef typename vovocov_t::sf4_type sf4_type;
-            typedef typename node_type::T0 T0;
-            typedef typename node_type::T1 T1;
-            typedef typename node_type::T2 T2;
-            typedef typename node_type::T3 T3;
-
-            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
-                                                      const details::operator_type& operation,
-                                                      expression_node_ptr (&branch)[2])
+            
+            inline expression_node_ptr operator()(const std::string& s, range_t& rp) const
             {
-               // v0 o0 (v1 o1 (c o2 v2))
-               typedef typename synthesize_vocov_expression1::node_type vocov_t;
-
-               const vocov_t* vocov = static_cast<const vocov_t*>(branch[1]);
-               const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
-               const Type& v1 = vocov->t0();
-               const Type   c = vocov->t1();
-               const Type& v2 = vocov->t2();
-               const details::operator_type o0 = operation;
-               const details::operator_type o1 = expr_gen.get_operator(vocov->f0());
-               const details::operator_type o2 = expr_gen.get_operator(vocov->f1());
-
-               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f1 = vocov->f0();
-               binary_functor_t f2 = vocov->f1();
-
-               details::free_node(*(expr_gen.node_allocator_),branch[1]);
-
-               expression_node_ptr result = error_node();
-
-               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,c,v2,result))
-                  return result;
-               if (!expr_gen.valid_operator(o0,f0))
-                  return error_node();
-
-               exprtk_debug(("v0 o0 (v1 o1 (c o2 v2))\n"));
-
-               return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,c,v2,f0,f1,f2);
+                return node_allocator_->allocate_tt<const_string_range_node_t>(s,rp);
             }
-
-            static inline std::string id(expression_generator<Type>& expr_gen,
-                                         const details::operator_type o0,
-                                         const details::operator_type o1,
-                                         const details::operator_type o2)
+            
+            inline expression_node_ptr operator()(expression_node_ptr branch, range_t& rp) const
             {
-               return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t))");
+                if (is_generally_string_node(branch))
+                    return node_allocator_->allocate_tt<generic_string_range_node_t>(branch,rp);
+                else
+                    return error_node();
             }
-         };
-
-         struct synthesize_vocovov_expression1
-         {
-            typedef typename vocovov_t::type1 node_type;
-            typedef typename vocovov_t::sf4_type sf4_type;
-            typedef typename node_type::T0 T0;
-            typedef typename node_type::T1 T1;
-            typedef typename node_type::T2 T2;
-            typedef typename node_type::T3 T3;
-
-            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
-                                                      const details::operator_type& operation,
-                                                      expression_node_ptr (&branch)[2])
+#endif
+            
+            inline bool unary_optimisable(const details::operator_type& operation) const
+            {
+                return (details::e_abs   == operation) || (details::e_acos  == operation) ||
+                (details::e_acosh == operation) || (details::e_asin  == operation) ||
+                (details::e_asinh == operation) || (details::e_atan  == operation) ||
+                (details::e_atanh == operation) || (details::e_ceil  == operation) ||
+                (details::e_cos   == operation) || (details::e_cosh  == operation) ||
+                (details::e_exp   == operation) || (details::e_expm1 == operation) ||
+                (details::e_floor == operation) || (details::e_log   == operation) ||
+                (details::e_log10 == operation) || (details::e_log2  == operation) ||
+                (details::e_log1p == operation) || (details::e_neg   == operation) ||
+                (details::e_pos   == operation) || (details::e_round == operation) ||
+                (details::e_sin   == operation) || (details::e_sinc  == operation) ||
+                (details::e_sinh  == operation) || (details::e_sqrt  == operation) ||
+                (details::e_tan   == operation) || (details::e_tanh  == operation) ||
+                (details::e_cot   == operation) || (details::e_sec   == operation) ||
+                (details::e_csc   == operation) || (details::e_r2d   == operation) ||
+                (details::e_d2r   == operation) || (details::e_d2g   == operation) ||
+                (details::e_g2d   == operation) || (details::e_notl  == operation) ||
+                (details::e_sgn   == operation) || (details::e_erf   == operation) ||
+                (details::e_erfc  == operation) || (details::e_ncdf  == operation) ||
+                (details::e_frac  == operation) || (details::e_trunc == operation);
+            }
+            
+            inline bool sf3_optimisable(const std::string& sf3id, trinary_functor_t& tfunc)
+            {
+                typename sf3_map_t::iterator itr = sf3_map_->find(sf3id);
+                
+                if (sf3_map_->end() == itr)
+                    return false;
+                else
+                    tfunc = itr->second.first;
+                
+                return true;
+            }
+            
+            inline bool sf4_optimisable(const std::string& sf4id, quaternary_functor_t& qfunc)
+            {
+                typename sf4_map_t::iterator itr = sf4_map_->find(sf4id);
+                
+                if (sf4_map_->end() == itr)
+                    return false;
+                else
+                    qfunc = itr->second.first;
+                
+                return true;
+            }
+            
+            inline bool sf3_optimisable(const std::string& sf3id, details::operator_type& operation)
+            {
+                typename sf3_map_t::iterator itr = sf3_map_->find(sf3id);
+                
+                if (sf3_map_->end() == itr)
+                    return false;
+                else
+                    operation = itr->second.second;
+                
+                return true;
+            }
+            
+            inline bool sf4_optimisable(const std::string& sf4id, details::operator_type& operation)
+            {
+                typename sf4_map_t::iterator itr = sf4_map_->find(sf4id);
+                
+                if (sf4_map_->end() == itr)
+                    return false;
+                else
+                    operation = itr->second.second;
+                
+                return true;
+            }
+            
+            inline expression_node_ptr operator()(const details::operator_type& operation, expression_node_ptr (&branch)[1])
+            {
+                if (0 == branch[0])
+                    return error_node();
+                else if (details::is_null_node(branch[0]))
+                    return branch[0];
+                else if (details::is_break_node(branch[0]))
+                    return error_node();
+                else if (details::is_continue_node(branch[0]))
+                    return error_node();
+                else if (details::is_constant_node(branch[0]))
+                    return synthesize_expression<unary_node_t,1>(operation,branch);
+                else if (unary_optimisable(operation) && details::is_variable_node(branch[0]))
+                    return synthesize_uv_expression(operation,branch);
+                else if (unary_optimisable(operation) && details::is_ivector_node(branch[0]))
+                    return synthesize_uvec_expression(operation,branch);
+                else
+                    return synthesize_unary_expression(operation,branch);
+            }
+            
+            inline bool is_assignment_operation(const details::operator_type& operation) const
+            {
+                return (
+                        (details::e_addass == operation) ||
+                        (details::e_subass == operation) ||
+                        (details::e_mulass == operation) ||
+                        (details::e_divass == operation) ||
+                        (details::e_modass == operation)
+                        ) &&
+                parser_->settings_.assignment_enabled(operation);
+            }
+            
+#ifndef exprtk_disable_string_capabilities
+            inline bool valid_string_operation(const details::operator_type& operation) const
+            {
+                return (details::e_add    == 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_in     == operation) ||
+                (details::e_like   == operation) ||
+                (details::e_ilike  == operation) ||
+                (details::e_assign == operation) ||
+                (details::e_addass == operation) ||
+                (details::e_swap   == operation) ;
+            }
+#else
+            inline bool valid_string_operation(const details::operator_type&) const
             {
-               // v0 o0 (c o1 (v1 o2 v2))
-               typedef typename synthesize_covov_expression1::node_type covov_t;
-
-               const covov_t* covov = static_cast<const covov_t*>(branch[1]);
-               const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
-               const Type   c = covov->t0();
-               const Type& v1 = covov->t1();
-               const Type& v2 = covov->t2();
-               const details::operator_type o0 = operation;
-               const details::operator_type o1 = expr_gen.get_operator(covov->f0());
-               const details::operator_type o2 = expr_gen.get_operator(covov->f1());
-
-               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f1 = covov->f0();
-               binary_functor_t f2 = covov->f1();
-
-               details::free_node(*(expr_gen.node_allocator_),branch[1]);
-
-               expression_node_ptr result = error_node();
-
-               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c,v1,v2,result))
-                  return result;
-               else if (!expr_gen.valid_operator(o0,f0))
-                  return error_node();
-
-               exprtk_debug(("v0 o0 (c o1 (v1 o2 v2))\n"));
-
-               return node_type::allocate(*(expr_gen.node_allocator_),v0,c,v1,v2,f0,f1,f2);
-            }
-
-            static inline std::string id(expression_generator<Type>& expr_gen,
-                                         const details::operator_type o0,
-                                         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))");
-            }
-         };
-
-         struct synthesize_covovov_expression1
-         {
-            typedef typename covovov_t::type1 node_type;
-            typedef typename covovov_t::sf4_type sf4_type;
-            typedef typename node_type::T0 T0;
-            typedef typename node_type::T1 T1;
-            typedef typename node_type::T2 T2;
-            typedef typename node_type::T3 T3;
-
-            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
-                                                      const details::operator_type& operation,
-                                                      expression_node_ptr (&branch)[2])
-            {
-               // c o0 (v0 o1 (v1 o2 v2))
-               typedef typename synthesize_vovov_expression1::node_type vovov_t;
-
-               const vovov_t* vovov = static_cast<const vovov_t*>(branch[1]);
-               const Type   c = static_cast<details::literal_node<Type>*>(branch[0])->value();
-               const Type& v0 = vovov->t0();
-               const Type& v1 = vovov->t1();
-               const Type& v2 = vovov->t2();
-               const details::operator_type o0 = operation;
-               const details::operator_type o1 = expr_gen.get_operator(vovov->f0());
-               const details::operator_type o2 = expr_gen.get_operator(vovov->f1());
-
-               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f1 = vovov->f0();
-               binary_functor_t f2 = vovov->f1();
-
-               details::free_node(*(expr_gen.node_allocator_),branch[0]);
-               details::free_node(*(expr_gen.node_allocator_),branch[1]);
-
-               expression_node_ptr result = error_node();
-
-               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c,v0,v1,v2,result))
-                  return result;
-               if (!expr_gen.valid_operator(o0,f0))
-                  return error_node();
-
-               exprtk_debug(("c o0 (v0 o1 (v1 o2 v2))\n"));
-
-               return node_type::allocate(*(expr_gen.node_allocator_),c,v0,v1,v2,f0,f1,f2);
-            }
-
-            static inline std::string id(expression_generator<Type>& expr_gen,
-                                         const details::operator_type o0,
-                                         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))");
-            }
-         };
-
-         struct synthesize_covocov_expression1
-         {
-            typedef typename covocov_t::type1 node_type;
-            typedef typename covocov_t::sf4_type sf4_type;
-            typedef typename node_type::T0 T0;
-            typedef typename node_type::T1 T1;
-            typedef typename node_type::T2 T2;
-            typedef typename node_type::T3 T3;
-
-            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
-                                                      const details::operator_type& operation,
-                                                      expression_node_ptr (&branch)[2])
-            {
-               // c0 o0 (v0 o1 (c1 o2 v1))
-               typedef typename synthesize_vocov_expression1::node_type vocov_t;
-
-               const vocov_t* vocov = static_cast<const vocov_t*>(branch[1]);
-               const Type  c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
-               const Type& v0 = vocov->t0();
-               const Type  c1 = vocov->t1();
-               const Type& v1 = vocov->t2();
-               const details::operator_type o0 = operation;
-               const details::operator_type o1 = expr_gen.get_operator(vocov->f0());
-               const details::operator_type o2 = expr_gen.get_operator(vocov->f1());
-
-               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f1 = vocov->f0();
-               binary_functor_t f2 = vocov->f1();
-
-               details::free_node(*(expr_gen.node_allocator_),branch[0]);
-               details::free_node(*(expr_gen.node_allocator_),branch[1]);
-
-               expression_node_ptr result = error_node();
-
-               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,c1,v1,result))
-                  return result;
-               else if (!expr_gen.valid_operator(o0,f0))
-                  return error_node();
-
-               exprtk_debug(("c0 o0 (v0 o1 (c1 o2 v1))\n"));
-
-               return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,c1,v1,f0,f1,f2);
-            }
-
-            static inline std::string id(expression_generator<Type>& expr_gen,
-                                         const details::operator_type o0,
-                                         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))");
-            }
-         };
-
-         struct synthesize_vocovoc_expression1
-         {
-            typedef typename vocovoc_t::type1 node_type;
-            typedef typename vocovoc_t::sf4_type sf4_type;
-            typedef typename node_type::T0 T0;
-            typedef typename node_type::T1 T1;
-            typedef typename node_type::T2 T2;
-            typedef typename node_type::T3 T3;
-
-            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
-                                                      const details::operator_type& operation,
-                                                      expression_node_ptr (&branch)[2])
-            {
-               // v0 o0 (c0 o1 (v1 o2 c2))
-               typedef typename synthesize_covoc_expression1::node_type covoc_t;
-
-               const covoc_t* covoc = static_cast<const covoc_t*>(branch[1]);
-               const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
-               const Type  c0 = covoc->t0();
-               const Type& v1 = covoc->t1();
-               const Type  c1 = covoc->t2();
-               const details::operator_type o0 = operation;
-               const details::operator_type o1 = expr_gen.get_operator(covoc->f0());
-               const details::operator_type o2 = expr_gen.get_operator(covoc->f1());
-
-               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f1 = covoc->f0();
-               binary_functor_t f2 = covoc->f1();
-
-               details::free_node(*(expr_gen.node_allocator_),branch[1]);
-
-               expression_node_ptr result = error_node();
-
-               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c0,v1,c1,result))
-                  return result;
-               else if (!expr_gen.valid_operator(o0,f0))
-                  return error_node();
-
-               exprtk_debug(("v0 o0 (c0 o1 (v1 o2 c2))\n"));
-
-               return node_type::allocate(*(expr_gen.node_allocator_),v0,c0,v1,c1,f0,f1,f2);
-            }
-
-            static inline std::string id(expression_generator<Type>& expr_gen,
-                                         const details::operator_type o0,
-                                         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))");
-            }
-         };
-
-         struct synthesize_covovoc_expression1
-         {
-            typedef typename covovoc_t::type1 node_type;
-            typedef typename covovoc_t::sf4_type sf4_type;
-            typedef typename node_type::T0 T0;
-            typedef typename node_type::T1 T1;
-            typedef typename node_type::T2 T2;
-            typedef typename node_type::T3 T3;
-            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
-                                                      const details::operator_type& operation,
-                                                      expression_node_ptr (&branch)[2])
-            {
-               // c0 o0 (v0 o1 (v1 o2 c1))
-               typedef typename synthesize_vovoc_expression1::node_type vovoc_t;
-
-               const vovoc_t* vovoc = static_cast<const vovoc_t*>(branch[1]);
-               const Type  c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
-               const Type& v0 = vovoc->t0();
-               const Type& v1 = vovoc->t1();
-               const Type  c1 = vovoc->t2();
-               const details::operator_type o0 = operation;
-               const details::operator_type o1 = expr_gen.get_operator(vovoc->f0());
-               const details::operator_type o2 = expr_gen.get_operator(vovoc->f1());
-
-               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f1 = vovoc->f0();
-               binary_functor_t f2 = vovoc->f1();
-
-               details::free_node(*(expr_gen.node_allocator_),branch[0]);
-               details::free_node(*(expr_gen.node_allocator_),branch[1]);
-
-               expression_node_ptr result = error_node();
-
-               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,v1,c1,result))
-                  return result;
-               else if (!expr_gen.valid_operator(o0,f0))
-                  return error_node();
-
-               exprtk_debug(("c0 o0 (v0 o1 (v1 o2 c1))\n"));
-
-               return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,v1,c1,f0,f1,f2);
-            }
-
-            static inline std::string id(expression_generator<Type>& expr_gen,
-                                         const details::operator_type o0,
-                                         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 false;
             }
-         };
-
-         struct synthesize_vococov_expression1
-         {
-            typedef typename vococov_t::type1 node_type;
-            typedef typename vococov_t::sf4_type sf4_type;
-            typedef typename node_type::T0 T0;
-            typedef typename node_type::T1 T1;
-            typedef typename node_type::T2 T2;
-            typedef typename node_type::T3 T3;
-
-            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
-                                                      const details::operator_type& operation,
-                                                      expression_node_ptr (&branch)[2])
-            {
-               // v0 o0 (c0 o1 (c1 o2 v1))
-               typedef typename synthesize_cocov_expression1::node_type cocov_t;
-
-               const cocov_t* cocov = static_cast<const cocov_t*>(branch[1]);
-               const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
-               const Type  c0 = cocov->t0();
-               const Type  c1 = cocov->t1();
-               const Type& v1 = cocov->t2();
-               const details::operator_type o0 = operation;
-               const details::operator_type o1 = expr_gen.get_operator(cocov->f0());
-               const details::operator_type o2 = expr_gen.get_operator(cocov->f1());
-
-               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f1 = cocov->f0();
-               binary_functor_t f2 = cocov->f1();
-
-               details::free_node(*(expr_gen.node_allocator_),branch[1]);
-
-               expression_node_ptr result = error_node();
-
-               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c0,c1,v1,result))
-                  return result;
-               else if (!expr_gen.valid_operator(o0,f0))
-                  return error_node();
-
-               exprtk_debug(("v0 o0 (c0 o1 (c1 o2 v1))\n"));
-
-               return node_type::allocate(*(expr_gen.node_allocator_),v0,c0,c1,v1,f0,f1,f2);
-            }
-
-            static inline std::string id(expression_generator<Type>& expr_gen,
-                                         const details::operator_type o0,
-                                         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))");
-            }
-         };
-
-         struct synthesize_vovovov_expression2
-         {
-            typedef typename vovovov_t::type2 node_type;
-            typedef typename vovovov_t::sf4_type sf4_type;
-            typedef typename node_type::T0 T0;
-            typedef typename node_type::T1 T1;
-            typedef typename node_type::T2 T2;
-            typedef typename node_type::T3 T3;
-
-            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
-                                                      const details::operator_type& operation,
-                                                      expression_node_ptr (&branch)[2])
-            {
-               // v0 o0 ((v1 o1 v2) o2 v3)
-               typedef typename synthesize_vovov_expression0::node_type vovov_t;
-
-               const vovov_t* vovov = static_cast<const vovov_t*>(branch[1]);
-               const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
-               const Type& v1 = vovov->t0();
-               const Type& v2 = vovov->t1();
-               const Type& v3 = vovov->t2();
-               const details::operator_type o0 = operation;
-               const details::operator_type o1 = expr_gen.get_operator(vovov->f0());
-               const details::operator_type o2 = expr_gen.get_operator(vovov->f1());
-
-               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f1 = vovov->f0();
-               binary_functor_t f2 = vovov->f1();
-
-               details::free_node(*(expr_gen.node_allocator_),branch[1]);
-
-               expression_node_ptr result = error_node();
-
-               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,v3,result))
-                  return result;
-               else if (!expr_gen.valid_operator(o0,f0))
-                  return error_node();
-
-               exprtk_debug(("v0 o0 ((v1 o1 v2) o2 v3)\n"));
-
-               return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,v3,f0,f1,f2);
-            }
-
-            static inline std::string id(expression_generator<Type>& expr_gen,
-                                         const details::operator_type o0,
-                                         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)");
-            }
-         };
-
-         struct synthesize_vovovoc_expression2
-         {
-            typedef typename vovovoc_t::type2 node_type;
-            typedef typename vovovoc_t::sf4_type sf4_type;
-            typedef typename node_type::T0 T0;
-            typedef typename node_type::T1 T1;
-            typedef typename node_type::T2 T2;
-            typedef typename node_type::T3 T3;
-
-            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
-                                                      const details::operator_type& operation,
-                                                      expression_node_ptr (&branch)[2])
-            {
-               // v0 o0 ((v1 o1 v2) o2 c)
-               typedef typename synthesize_vovoc_expression0::node_type vovoc_t;
-
-               const vovoc_t* vovoc = static_cast<const vovoc_t*>(branch[1]);
-               const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
-               const Type& v1 = vovoc->t0();
-               const Type& v2 = vovoc->t1();
-               const Type   c = vovoc->t2();
-               const details::operator_type o0 = operation;
-               const details::operator_type o1 = expr_gen.get_operator(vovoc->f0());
-               const details::operator_type o2 = expr_gen.get_operator(vovoc->f1());
-
-               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f1 = vovoc->f0();
-               binary_functor_t f2 = vovoc->f1();
-
-               details::free_node(*(expr_gen.node_allocator_),branch[1]);
-
-               expression_node_ptr result = error_node();
-
-               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,c,result))
-                  return result;
-               else if (!expr_gen.valid_operator(o0,f0))
-                  return error_node();
-
-               exprtk_debug(("v0 o0 ((v1 o1 v2) o2 c)\n"));
-
-               return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,c,f0,f1,f2);
-            }
-
-            static inline std::string id(expression_generator<Type>& expr_gen,
-                                         const details::operator_type o0,
-                                         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)");
-            }
-         };
-
-         struct synthesize_vovocov_expression2
-         {
-            typedef typename vovocov_t::type2 node_type;
-            typedef typename vovocov_t::sf4_type sf4_type;
-            typedef typename node_type::T0 T0;
-            typedef typename node_type::T1 T1;
-            typedef typename node_type::T2 T2;
-            typedef typename node_type::T3 T3;
-
-            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
-                                                      const details::operator_type& operation,
-                                                      expression_node_ptr (&branch)[2])
-            {
-               // v0 o0 ((v1 o1 c) o2 v2)
-               typedef typename synthesize_vocov_expression0::node_type vocov_t;
-
-               const vocov_t* vocov = static_cast<const vocov_t*>(branch[1]);
-               const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
-               const Type& v1 = vocov->t0();
-               const Type   c = vocov->t1();
-               const Type& v2 = vocov->t2();
-               const details::operator_type o0 = operation;
-               const details::operator_type o1 = expr_gen.get_operator(vocov->f0());
-               const details::operator_type o2 = expr_gen.get_operator(vocov->f1());
-
-               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f1 = vocov->f0();
-               binary_functor_t f2 = vocov->f1();
-
-               details::free_node(*(expr_gen.node_allocator_),branch[1]);
-
-               expression_node_ptr result = error_node();
-
-               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,c,v2,result))
-                  return result;
-               else if (!expr_gen.valid_operator(o0,f0))
-                  return error_node();
-
-               exprtk_debug(("v0 o0 ((v1 o1 c) o2 v2)\n"));
-
-               return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,c,v2,f0,f1,f2);
-            }
-
-            static inline std::string id(expression_generator<Type>& expr_gen,
-                                         const details::operator_type o0,
-                                         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)");
+#endif
+            
+            inline std::string to_str(const details::operator_type& operation) const
+            {
+                switch (operation)
+                {
+                    case details::e_add  : return "+";
+                    case details::e_sub  : return "-";
+                    case details::e_mul  : return "*";
+                    case details::e_div  : return "/";
+                    case details::e_mod  : return "%";
+                    case details::e_pow  : return "^";
+                    case details::e_lt   : return "<";
+                    case details::e_lte  : return "<=";
+                    case details::e_gt   : return ">";
+                    case details::e_gte  : return ">=";
+                    case details::e_eq   : return "==";
+                    case details::e_ne   : return "!=";
+                    case details::e_and  : return "and";
+                    case details::e_nand : return "nand";
+                    case details::e_or   : return "or";
+                    case details::e_nor  : return "nor";
+                    case details::e_xor  : return "xor";
+                    case details::e_xnor : return "xnor";
+                    default              : return "UNKNOWN";
+                }
+            }
+            
+            inline bool operation_optimisable(const details::operator_type& operation) const
+            {
+                return (details::e_add  == operation) ||
+                (details::e_sub  == operation) ||
+                (details::e_mul  == operation) ||
+                (details::e_div  == operation) ||
+                (details::e_mod  == operation) ||
+                (details::e_pow  == 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_and  == operation) ||
+                (details::e_nand == operation) ||
+                (details::e_or   == operation) ||
+                (details::e_nor  == operation) ||
+                (details::e_xor  == operation) ||
+                (details::e_xnor == operation) ;
+            }
+            
+            inline std::string branch_to_id(expression_node_ptr branch)
+            {
+                static const std::string null_str   ("(null)" );
+                static const std::string const_str  ("(c)"    );
+                static const std::string var_str    ("(v)"    );
+                static const std::string vov_str    ("(vov)"  );
+                static const std::string cov_str    ("(cov)"  );
+                static const std::string voc_str    ("(voc)"  );
+                static const std::string str_str    ("(s)"    );
+                static const std::string strrng_str ("(rngs)" );
+                static const std::string cs_str     ("(cs)"   );
+                static const std::string cstrrng_str("(crngs)");
+                
+                if (details::is_null_node(branch))
+                    return null_str;
+                else if (details::is_constant_node(branch))
+                    return const_str;
+                else if (details::is_variable_node(branch))
+                    return var_str;
+                else if (details::is_vov_node(branch))
+                    return vov_str;
+                else if (details::is_cov_node(branch))
+                    return cov_str;
+                else if (details::is_voc_node(branch))
+                    return voc_str;
+                else if (details::is_string_node(branch))
+                    return str_str;
+                else if (details::is_const_string_node(branch))
+                    return cs_str;
+                else if (details::is_string_range_node(branch))
+                    return strrng_str;
+                else if (details::is_const_string_range_node(branch))
+                    return cstrrng_str;
+                else if (details::is_t0ot1ot2_node(branch))
+                    return "(" + dynamic_cast<details::T0oT1oT2_base_node<T>*>(branch)->type_id() + ")";
+                else if (details::is_t0ot1ot2ot3_node(branch))
+                    return "(" + dynamic_cast<details::T0oT1oT2oT3_base_node<T>*>(branch)->type_id() + ")";
+                else
+                    return "ERROR";
+            }
+            
+            inline std::string branch_to_id(expression_node_ptr (&branch)[2])
+            {
+                return branch_to_id(branch[0]) + std::string("o") + branch_to_id(branch[1]);
+            }
+            
+            inline bool cov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
+            {
+                if (!operation_optimisable(operation))
+                    return false;
+                else
+                    return (details::is_constant_node(branch[0]) && details::is_variable_node(branch[1]));
+            }
+            
+            inline bool voc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
+            {
+                if (!operation_optimisable(operation))
+                    return false;
+                else
+                    return (details::is_variable_node(branch[0]) && details::is_constant_node(branch[1]));
+            }
+            
+            inline bool vov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
+            {
+                if (!operation_optimisable(operation))
+                    return false;
+                else
+                    return (details::is_variable_node(branch[0]) && details::is_variable_node(branch[1]));
+            }
+            
+            inline bool cob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
+            {
+                if (!operation_optimisable(operation))
+                    return false;
+                else
+                    return (details::is_constant_node(branch[0]) && !details::is_constant_node(branch[1]));
+            }
+            
+            inline bool boc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
+            {
+                if (!operation_optimisable(operation))
+                    return false;
+                else
+                    return (!details::is_constant_node(branch[0]) && details::is_constant_node(branch[1]));
+            }
+            
+            inline bool cocob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
+            {
+                if (
+                    (details::e_add == operation) ||
+                    (details::e_sub == operation) ||
+                    (details::e_mul == operation) ||
+                    (details::e_div == operation)
+                    )
+                {
+                    return (details::is_constant_node(branch[0]) && details::is_cob_node(branch[1])) ||
+                    (details::is_constant_node(branch[1]) && details::is_cob_node(branch[0]));
+                }
+                else
+                    return false;
             }
-         };
-
-         struct synthesize_vocovov_expression2
-         {
-            typedef typename vocovov_t::type2 node_type;
-            typedef typename vocovov_t::sf4_type sf4_type;
-            typedef typename node_type::T0 T0;
-            typedef typename node_type::T1 T1;
-            typedef typename node_type::T2 T2;
-            typedef typename node_type::T3 T3;
-
-            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
-                                                      const details::operator_type& operation,
-                                                      expression_node_ptr (&branch)[2])
+            
+            inline bool coboc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
             {
-               // v0 o0 ((c o1 v1) o2 v2)
-               typedef typename synthesize_covov_expression0::node_type covov_t;
-
-               const covov_t* covov = static_cast<const covov_t*>(branch[1]);
-               const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
-               const Type   c = covov->t0();
-               const Type& v1 = covov->t1();
-               const Type& v2 = covov->t2();
-               const details::operator_type o0 = operation;
-               const details::operator_type o1 = expr_gen.get_operator(covov->f0());
-               const details::operator_type o2 = expr_gen.get_operator(covov->f1());
-
-               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f1 = covov->f0();
-               binary_functor_t f2 = covov->f1();
-
-               details::free_node(*(expr_gen.node_allocator_),branch[1]);
-
-               expression_node_ptr result = error_node();
-
-               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c,v1,v2,result))
-                  return result;
-               else if (!expr_gen.valid_operator(o0,f0))
-                  return error_node();
-
-               exprtk_debug(("v0 o0 ((c o1 v1) o2 v2)\n"));
-
-               return node_type::allocate(*(expr_gen.node_allocator_),v0,c,v1,v2,f0,f1,f2);
+                if (
+                    (details::e_add == operation) ||
+                    (details::e_sub == operation) ||
+                    (details::e_mul == operation) ||
+                    (details::e_div == operation)
+                    )
+                {
+                    return (details::is_constant_node(branch[0]) && details::is_boc_node(branch[1])) ||
+                    (details::is_constant_node(branch[1]) && details::is_boc_node(branch[0]));
+                }
+                else
+                    return false;
+            }
+            
+            inline bool uvouv_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
+            {
+                if (!operation_optimisable(operation))
+                    return false;
+                else
+                    return (details::is_uv_node(branch[0]) && details::is_uv_node(branch[1]));
+            }
+            
+            inline bool vob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
+            {
+                if (!operation_optimisable(operation))
+                    return false;
+                else
+                    return (details::is_variable_node(branch[0]) && !details::is_variable_node(branch[1]));
+            }
+            
+            inline bool bov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
+            {
+                if (!operation_optimisable(operation))
+                    return false;
+                else
+                    return (!details::is_variable_node(branch[0]) && details::is_variable_node(branch[1]));
+            }
+            
+            inline bool binext_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
+            {
+                if (!operation_optimisable(operation))
+                    return false;
+                else
+                    return (!details::is_constant_node(branch[0]) || !details::is_constant_node(branch[1]));
+            }
+            
+            inline bool is_invalid_assignment_op(const details::operator_type& operation, expression_node_ptr (&branch)[2])
+            {
+                if (is_assignment_operation(operation))
+                {
+                    const bool b1_is_genstring = details::is_generally_string_node(branch[1]);
+                    
+                    if (details::is_string_node(branch[0]))
+                        return !b1_is_genstring;
+                    else
+                        return (
+                                !details::is_variable_node          (branch[0]) &&
+                                !details::is_vector_elem_node       (branch[0]) &&
+                                !details::is_rebasevector_elem_node (branch[0]) &&
+                                !details::is_rebasevector_celem_node(branch[0]) &&
+                                !details::is_vector_node            (branch[0])
+                                )
+                        || b1_is_genstring;
+                }
+                else
+                    return false;
+            }
+            
+            inline bool is_constpow_operation(const details::operator_type& operation, expression_node_ptr(&branch)[2])
+            {
+                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])
+                    )
+                    return false;
+                
+                const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
+                
+                return cardinal_pow_optimisable(operation, c);
+            }
+            
+            inline bool is_invalid_break_continue_op(expression_node_ptr (&branch)[2])
+            {
+                return (
+                        details::is_break_node   (branch[0]) ||
+                        details::is_break_node   (branch[1]) ||
+                        details::is_continue_node(branch[0]) ||
+                        details::is_continue_node(branch[1])
+                        );
+            }
+            
+            inline bool is_invalid_string_op(const details::operator_type& operation, expression_node_ptr (&branch)[2])
+            {
+                const bool b0_string = is_generally_string_node(branch[0]);
+                const bool b1_string = is_generally_string_node(branch[1]);
+                
+                bool result = false;
+                
+                if (b0_string != b1_string)
+                    result = true;
+                else if (!valid_string_operation(operation) && b0_string && b1_string)
+                    result = true;
+                
+                if (result)
+                {
+                    parser_->set_synthesis_error("Invalid string operation");
+                }
+                
+                return result;
+            }
+            
+            inline bool is_invalid_string_op(const details::operator_type& operation, expression_node_ptr (&branch)[3])
+            {
+                const bool b0_string = is_generally_string_node(branch[0]);
+                const bool b1_string = is_generally_string_node(branch[1]);
+                const bool b2_string = is_generally_string_node(branch[2]);
+                
+                bool result = false;
+                
+                if ((b0_string != b1_string) || (b1_string != b2_string))
+                    result = true;
+                else if ((details::e_inrange != operation) && b0_string && b1_string && b2_string)
+                    result = true;
+                
+                if (result)
+                {
+                    parser_->set_synthesis_error("Invalid string operation");
+                }
+                
+                return result;
+            }
+            
+            inline bool is_string_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2])
+            {
+                const bool b0_string = is_generally_string_node(branch[0]);
+                const bool b1_string = is_generally_string_node(branch[1]);
+                
+                return (b0_string && b1_string && valid_string_operation(operation));
+            }
+            
+            inline bool is_string_operation(const details::operator_type& operation, expression_node_ptr (&branch)[3])
+            {
+                const bool b0_string = is_generally_string_node(branch[0]);
+                const bool b1_string = is_generally_string_node(branch[1]);
+                const bool b2_string = is_generally_string_node(branch[2]);
+                
+                return (b0_string && b1_string && b2_string && (details::e_inrange == operation));
+            }
+            
+#ifndef exprtk_disable_sc_andor
+            inline bool is_shortcircuit_expression(const details::operator_type& operation)
+            {
+                return (
+                        (details::e_scand == operation) ||
+                        (details::e_scor  == operation)
+                        );
             }
-
-            static inline std::string id(expression_generator<Type>& expr_gen,
-                                         const details::operator_type o0,
-                                         const details::operator_type o1,
-                                         const details::operator_type o2)
+#else
+            inline bool is_shortcircuit_expression(const details::operator_type&)
             {
-               return (details::build_string() << "t" << expr_gen.to_str(o0) << "((t" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t)");
+                return false;
             }
-         };
-
-         struct synthesize_covovov_expression2
-         {
-            typedef typename covovov_t::type2 node_type;
-            typedef typename covovov_t::sf4_type sf4_type;
-            typedef typename node_type::T0 T0;
-            typedef typename node_type::T1 T1;
-            typedef typename node_type::T2 T2;
-            typedef typename node_type::T3 T3;
-
-            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
-                                                      const details::operator_type& operation,
-                                                      expression_node_ptr (&branch)[2])
-            {
-               // c o0 ((v1 o1 v2) o2 v3)
-               typedef typename synthesize_vovov_expression0::node_type vovov_t;
-
-               const vovov_t* vovov = static_cast<const vovov_t*>(branch[1]);
-               const Type   c = static_cast<details::literal_node<Type>*>(branch[0])->value();
-               const Type& v0 = vovov->t0();
-               const Type& v1 = vovov->t1();
-               const Type& v2 = vovov->t2();
-               const details::operator_type o0 = operation;
-               const details::operator_type o1 = expr_gen.get_operator(vovov->f0());
-               const details::operator_type o2 = expr_gen.get_operator(vovov->f1());
-
-               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f1 = vovov->f0();
-               binary_functor_t f2 = vovov->f1();
-
-               details::free_node(*(expr_gen.node_allocator_),branch[0]);
-               details::free_node(*(expr_gen.node_allocator_),branch[1]);
-
-               expression_node_ptr result = error_node();
-
-               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c,v0,v1,v2,result))
-                  return result;
-               else if (!expr_gen.valid_operator(o0,f0))
-                  return error_node();
-
-               exprtk_debug(("c o0 ((v1 o1 v2) o2 v3)\n"));
-
-               return node_type::allocate(*(expr_gen.node_allocator_),c,v0,v1,v2,f0,f1,f2);
+#endif
+            
+            inline bool is_null_present(expression_node_ptr (&branch)[2])
+            {
+                return (
+                        details::is_null_node(branch[0]) ||
+                        details::is_null_node(branch[1])
+                        );
+            }
+            
+            inline bool is_vector_eqineq_logic_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2])
+            {
+                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)
+                            );
+            }
+            
+            inline bool is_vector_arithmetic_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2])
+            {
+                if (!is_ivector_node(branch[0]) && !is_ivector_node(branch[1]))
+                    return false;
+                else
+                    return (
+                            (details::e_add == operation) ||
+                            (details::e_sub == operation) ||
+                            (details::e_mul == operation) ||
+                            (details::e_div == operation) ||
+                            (details::e_pow == operation)
+                            );
+            }
+            
+            inline expression_node_ptr operator()(const details::operator_type& operation, expression_node_ptr (&branch)[2])
+            {
+                if ((0 == branch[0]) || (0 == branch[1]))
+                    return error_node();
+                else if (is_invalid_string_op(operation,branch))
+                    return error_node();
+                else if (is_invalid_assignment_op(operation,branch))
+                    return error_node();
+                else if (is_invalid_break_continue_op(branch))
+                    return error_node();
+                else if (details::e_assign == operation)
+                    return synthesize_assignment_expression(operation,branch);
+                else if (details::e_swap == operation)
+                    return synthesize_swap_expression(branch);
+                else if (is_assignment_operation(operation))
+                    return synthesize_assignment_operation_expression(operation,branch);
+                else if (is_vector_eqineq_logic_operation(operation,branch))
+                    return synthesize_veceqineqlogic_operation_expression(operation,branch);
+                else if (is_vector_arithmetic_operation(operation,branch))
+                    return synthesize_vecarithmetic_operation_expression(operation,branch);
+                else if (is_shortcircuit_expression(operation))
+                    return synthesize_shortcircuit_expression(operation,branch);
+                else if (is_string_operation(operation,branch))
+                    return synthesize_string_expression(operation,branch);
+                else if (is_null_present(branch))
+                    return synthesize_null_expression(operation, branch);
+#ifndef exprtk_disable_cardinal_pow_optimisation
+                else if (is_constpow_operation(operation, branch))
+                    return cardinal_pow_optimisation(branch);
+#endif
+                
+                expression_node_ptr result = error_node();
+                
+#ifndef exprtk_disable_enhanced_features
+                if (synthesize_expression(operation,branch,result))
+                    return result;
+                else
+#endif
+                    
+                {
+                    /*
+                     Possible reductions:
+                     1. c o cob -> cob
+                     2. cob o c -> cob
+                     3. c o boc -> boc
+                     4. boc o c -> boc
+                     */
+                    result = error_node();
+                    
+                    if (cocob_optimisable(operation,branch))
+                        result = synthesize_cocob_expression::process(*this,operation,branch);
+                    else if (coboc_optimisable(operation,branch) && (0 == result))
+                        result = synthesize_coboc_expression::process(*this,operation,branch);
+                    
+                    if (result)
+                        return result;
+                }
+                
+                if (uvouv_optimisable(operation,branch))
+                    return synthesize_uvouv_expression(operation,branch);
+                else if (vob_optimisable(operation,branch))
+                    return synthesize_vob_expression::process(*this,operation,branch);
+                else if (bov_optimisable(operation,branch))
+                    return synthesize_bov_expression::process(*this,operation,branch);
+                else if (cob_optimisable(operation,branch))
+                    return synthesize_cob_expression::process(*this,operation,branch);
+                else if (boc_optimisable(operation,branch))
+                    return synthesize_boc_expression::process(*this,operation,branch);
+#ifndef exprtk_disable_enhanced_features
+                else if (cov_optimisable(operation,branch))
+                    return synthesize_cov_expression::process(*this,operation,branch);
+#endif
+                else if (binext_optimisable(operation,branch))
+                    return synthesize_binary_ext_expression::process(*this,operation,branch);
+                else
+                    return synthesize_expression<binary_node_t,2>(operation,branch);
+            }
+            
+            inline expression_node_ptr operator()(const details::operator_type& operation, expression_node_ptr (&branch)[3])
+            {
+                if (
+                    (0 == branch[0]) ||
+                    (0 == branch[1]) ||
+                    (0 == branch[2])
+                    )
+                {
+                    details::free_all_nodes(*node_allocator_,branch);
+                    
+                    return error_node();
+                }
+                else if (is_invalid_string_op(operation,branch))
+                    return error_node();
+                else if (is_string_operation(operation,branch))
+                    return synthesize_string_expression(operation,branch);
+                else
+                    return synthesize_expression<trinary_node_t,3>(operation,branch);
+            }
+            
+            inline expression_node_ptr operator()(const details::operator_type& operation, expression_node_ptr (&branch)[4])
+            {
+                return synthesize_expression<quaternary_node_t,4>(operation,branch);
+            }
+            
+            inline expression_node_ptr operator()(const details::operator_type& operation, expression_node_ptr b0)
+            {
+                expression_node_ptr branch[1] = { b0 };
+                return (*this)(operation,branch);
+            }
+            
+            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 branch[2] = { b0, b1 };
+                    return expression_generator<Type>::operator()(operation,branch);
+                }
+            }
+            
+            inline expression_node_ptr conditional(expression_node_ptr condition,
+                                                   expression_node_ptr consequent,
+                                                   expression_node_ptr alternative) const
+            {
+                if ((0 == condition) || (0 == consequent))
+                {
+                    free_node(*node_allocator_,condition  );
+                    free_node(*node_allocator_,consequent );
+                    free_node(*node_allocator_,alternative);
+                    
+                    return error_node();
+                }
+                // Can the condition be immediately evaluated? if so optimise.
+                else if (details::is_constant_node(condition))
+                {
+                    // True branch
+                    if (details::is_true(condition))
+                    {
+                        free_node(*node_allocator_,condition  );
+                        free_node(*node_allocator_,alternative);
+                        
+                        return consequent;
+                    }
+                    // False branch
+                    else
+                    {
+                        free_node(*node_allocator_,condition );
+                        free_node(*node_allocator_,consequent);
+                        
+                        if (alternative)
+                            return alternative;
+                        else
+                            return node_allocator_->allocate<details::null_node<T> >();
+                    }
+                }
+                else if ((0 != consequent) && (0 != alternative))
+                {
+                    return node_allocator_->
+                    allocate<conditional_node_t>(condition,consequent,alternative);
+                }
+                else
+                    return node_allocator_->
+                    allocate<cons_conditional_node_t>(condition,consequent);
+            }
+            
+#ifndef exprtk_disable_string_capabilities
+            inline expression_node_ptr conditional_string(expression_node_ptr condition,
+                                                          expression_node_ptr consequent,
+                                                          expression_node_ptr alternative) const
+            {
+                if ((0 == condition) || (0 == consequent))
+                {
+                    free_node(*node_allocator_,condition  );
+                    free_node(*node_allocator_,consequent );
+                    free_node(*node_allocator_,alternative);
+                    
+                    return error_node();
+                }
+                // Can the condition be immediately evaluated? if so optimise.
+                else if (details::is_constant_node(condition))
+                {
+                    // True branch
+                    if (details::is_true(condition))
+                    {
+                        free_node(*node_allocator_,condition  );
+                        free_node(*node_allocator_,alternative);
+                        
+                        return consequent;
+                    }
+                    // False branch
+                    else
+                    {
+                        free_node(*node_allocator_,condition );
+                        free_node(*node_allocator_,consequent);
+                        
+                        if (alternative)
+                            return alternative;
+                        else
+                            return node_allocator_->
+                            allocate_c<details::string_literal_node<Type> >("");
+                    }
+                }
+                else if ((0 != consequent) && (0 != alternative))
+                    return node_allocator_->
+                    allocate<conditional_string_node_t>(condition,consequent,alternative);
+                else
+                    return error_node();
             }
-
-            static inline std::string id(expression_generator<Type>& expr_gen,
-                                         const details::operator_type o0,
-                                         const details::operator_type o1,
-                                         const details::operator_type o2)
+#else
+            inline expression_node_ptr conditional_string(expression_node_ptr,
+                                                          expression_node_ptr,
+                                                          expression_node_ptr) const
             {
-               return (details::build_string() << "t" << expr_gen.to_str(o0) << "((t" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t)");
+                return error_node();
             }
-        };
-
-         struct synthesize_covocov_expression2
-         {
-            typedef typename covocov_t::type2 node_type;
-            typedef typename covocov_t::sf4_type sf4_type;
-            typedef typename node_type::T0 T0;
-            typedef typename node_type::T1 T1;
-            typedef typename node_type::T2 T2;
-            typedef typename node_type::T3 T3;
-
-            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
-                                                      const details::operator_type& operation,
-                                                      expression_node_ptr (&branch)[2])
-            {
-               // c0 o0 ((v0 o1 c1) o2 v1)
-               typedef typename synthesize_vocov_expression0::node_type vocov_t;
-
-               const vocov_t* vocov = static_cast<const vocov_t*>(branch[1]);
-               const Type  c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
-               const Type& v0 = vocov->t0();
-               const Type  c1 = vocov->t1();
-               const Type& v1 = vocov->t2();
-               const details::operator_type o0 = operation;
-               const details::operator_type o1 = expr_gen.get_operator(vocov->f0());
-               const details::operator_type o2 = expr_gen.get_operator(vocov->f1());
-
-               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f1 = vocov->f0();
-               binary_functor_t f2 = vocov->f1();
-
-               details::free_node(*(expr_gen.node_allocator_),branch[0]);
-               details::free_node(*(expr_gen.node_allocator_),branch[1]);
-
-               expression_node_ptr result = error_node();
-
-               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,c1,v1,result))
-                  return result;
-               else if (!expr_gen.valid_operator(o0,f0))
-                  return error_node();
-
-               exprtk_debug(("c0 o0 ((v0 o1 c1) o2 v1)\n"));
-
-               return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,c1,v1,f0,f1,f2);
+#endif
+            
+            inline expression_node_ptr while_loop(expression_node_ptr& condition,
+                                                  expression_node_ptr& branch,
+                                                  const bool brkcont = false) const
+            {
+                if (!brkcont && details::is_constant_node(condition))
+                {
+                    expression_node_ptr result = error_node();
+                    if (details::is_true(condition))
+                        // Infinite loops are not allowed.
+                        result = error_node();
+                    else
+                        result = node_allocator_->allocate<details::null_node<Type> >();
+                    
+                    free_node(*node_allocator_, condition);
+                    free_node(*node_allocator_, branch   );
+                    
+                    return result;
+                }
+                else if (details::is_null_node(condition))
+                {
+                    free_node(*node_allocator_,condition);
+                    
+                    return branch;
+                }
+                else if (!brkcont)
+                    return node_allocator_->allocate<while_loop_node_t>(condition,branch);
+#ifndef exprtk_disable_break_continue
+                else
+                    return node_allocator_->allocate<while_loop_bc_node_t>(condition,branch);
+#else
+                return error_node();
+#endif
             }
-
-            static inline std::string id(expression_generator<Type>& expr_gen,
-                                         const details::operator_type o0,
-                                         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)");
+            
+            inline expression_node_ptr repeat_until_loop(expression_node_ptr& condition,
+                                                         expression_node_ptr& branch,
+                                                         const bool brkcont = false) const
+            {
+                if (!brkcont && details::is_constant_node(condition))
+                {
+                    if (details::is_true(condition) && details::is_constant_node(branch))
+                    {
+                        free_node(*node_allocator_,condition);
+                        
+                        return branch;
+                    }
+                    
+                    free_node(*node_allocator_, condition);
+                    free_node(*node_allocator_, branch   );
+                    
+                    return error_node();
+                }
+                else if (details::is_null_node(condition))
+                {
+                    free_node(*node_allocator_,condition);
+                    
+                    return branch;
+                }
+                else if (!brkcont)
+                    return node_allocator_->allocate<repeat_until_loop_node_t>(condition,branch);
+#ifndef exprtk_disable_break_continue
+                else
+                    return node_allocator_->allocate<repeat_until_loop_bc_node_t>(condition,branch);
+#else
+                return error_node();
+#endif
             }
-         };
-
-         struct synthesize_vocovoc_expression2
-         {
-            typedef typename vocovoc_t::type2 node_type;
-            typedef typename vocovoc_t::sf4_type sf4_type;
-            typedef typename node_type::T0 T0;
-            typedef typename node_type::T1 T1;
-            typedef typename node_type::T2 T2;
-            typedef typename node_type::T3 T3;
-
-            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
-                                                      const details::operator_type& operation,
-                                                      expression_node_ptr (&branch)[2])
-            {
-               // v0 o0 ((c0 o1 v1) o2 c1)
-               typedef typename synthesize_covoc_expression0::node_type covoc_t;
-
-               const covoc_t* covoc = static_cast<const covoc_t*>(branch[1]);
-               const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
-               const Type  c0 = covoc->t0();
-               const Type& v1 = covoc->t1();
-               const Type  c1 = covoc->t2();
-               const details::operator_type o0 = operation;
-               const details::operator_type o1 = expr_gen.get_operator(covoc->f0());
-               const details::operator_type o2 = expr_gen.get_operator(covoc->f1());
-
-               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f1 = covoc->f0();
-               binary_functor_t f2 = covoc->f1();
-
-               details::free_node(*(expr_gen.node_allocator_),branch[1]);
-
-               expression_node_ptr result = error_node();
-
-               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c0,v1,c1,result))
-                  return result;
-               else if (!expr_gen.valid_operator(o0,f0))
-                  return error_node();
-
-               exprtk_debug(("v0 o0 ((c0 o1 v1) o2 c1)\n"));
-
-               return node_type::allocate(*(expr_gen.node_allocator_),v0,c0,v1,c1,f0,f1,f2);
+            
+            inline expression_node_ptr for_loop(expression_node_ptr& initialiser,
+                                                expression_node_ptr& condition,
+                                                expression_node_ptr& incrementor,
+                                                expression_node_ptr& loop_body,
+                                                bool brkcont = false) const
+            {
+                if (!brkcont && details::is_constant_node(condition))
+                {
+                    expression_node_ptr result = error_node();
+                    
+                    if (details::is_true(condition))
+                        // Infinite loops are not allowed.
+                        result = error_node();
+                    else
+                        result = node_allocator_->allocate<details::null_node<Type> >();
+                    
+                    free_node(*node_allocator_,initialiser);
+                    free_node(*node_allocator_,condition  );
+                    free_node(*node_allocator_,incrementor);
+                    free_node(*node_allocator_,loop_body  );
+                    
+                    return result;
+                }
+                else if (details::is_null_node(condition))
+                {
+                    free_node(*node_allocator_,initialiser);
+                    free_node(*node_allocator_,condition  );
+                    free_node(*node_allocator_,incrementor);
+                    
+                    return loop_body;
+                }
+                else if (!brkcont)
+                    return node_allocator_->allocate<for_loop_node_t>(initialiser,
+                                                                      condition,
+                                                                      incrementor,
+                                                                      loop_body);
+#ifndef exprtk_disable_break_continue
+                else
+                    return node_allocator_->allocate<for_loop_bc_node_t>(initialiser,
+                                                                         condition,
+                                                                         incrementor,
+                                                                         loop_body);
+#else
+                return error_node();
+#endif
             }
-
-            static inline std::string id(expression_generator<Type>& expr_gen,
-                                         const details::operator_type o0,
-                                         const details::operator_type o1,
-                                         const details::operator_type o2)
+            
+            template <typename Allocator,
+            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();
+                
+                for (std::size_t i = 0; i < (arg_list.size() / 2); ++i)
+                {
+                    expression_node_ptr condition  = arg_list[(2 * i)    ];
+                    expression_node_ptr consequent = arg_list[(2 * i) + 1];
+                    
+                    if ((0 == result) && details::is_true(condition))
+                    {
+                        result = consequent;
+                        break;
+                    }
+                }
+                
+                if (0 == result)
+                {
+                    result = arg_list.back();
+                }
+                
+                for (std::size_t i = 0; i < arg_list.size(); ++i)
+                {
+                    expression_node_ptr current_expr = arg_list[i];
+                    
+                    if (current_expr && (current_expr != result))
+                    {
+                        free_node(*node_allocator_,current_expr);
+                    }
+                }
+                
+                return result;
+            }
+            
+            template <typename Allocator,
+            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();
+                
+                for (std::size_t i = 0; i < (arg_list.size() / 2); ++i)
+                {
+                    expression_node_ptr condition  = arg_list[(2 * i)    ];
+                    expression_node_ptr consequent = arg_list[(2 * i) + 1];
+                    
+                    if (details::is_true(condition))
+                    {
+                        result = consequent;
+                    }
+                }
+                
+                if (0 == result)
+                {
+                    T zero = T(0);
+                    result = node_allocator_->allocate<literal_node_t>(zero);
+                }
+                
+                for (std::size_t i = 0; i < arg_list.size(); ++i)
+                {
+                    expression_node_ptr& current_expr = arg_list[i];
+                    
+                    if (current_expr && (current_expr != result))
+                    {
+                        free_node(*node_allocator_,current_expr);
+                    }
+                }
+                
+                return result;
+            }
+            
+            struct switch_nodes
+            {
+                typedef std::vector<expression_node_ptr> arg_list_t;
+                
+#define case_stmt(N)                                             \
+if (is_true(arg[(2 * N)])) { return arg[(2 * N) + 1]->value(); } \
+
+                struct switch_1
+                {
+                    static inline T process(const arg_list_t& arg)
+                    {
+                        case_stmt(0)
+                        return arg.back()->value();
+                    }
+                };
+                
+                struct switch_2
+                {
+                    static inline T process(const arg_list_t& arg)
+                    {
+                        case_stmt(0) case_stmt(1)
+                        return arg.back()->value();
+                    }
+                };
+                
+                struct switch_3
+                {
+                    static inline T process(const arg_list_t& arg)
+                    {
+                        case_stmt(0) case_stmt(1)
+                        case_stmt(2)
+                        return arg.back()->value();
+                    }
+                };
+                
+                struct switch_4
+                {
+                    static inline T process(const arg_list_t& arg)
+                    {
+                        case_stmt(0) case_stmt(1)
+                        case_stmt(2) case_stmt(3)
+                        return arg.back()->value();
+                    }
+                };
+                
+                struct switch_5
+                {
+                    static inline T process(const arg_list_t& arg)
+                    {
+                        case_stmt(0) case_stmt(1)
+                        case_stmt(2) case_stmt(3)
+                        case_stmt(4)
+                        return arg.back()->value();
+                    }
+                };
+                
+                struct switch_6
+                {
+                    static inline T process(const arg_list_t& arg)
+                    {
+                        case_stmt(0) case_stmt(1)
+                        case_stmt(2) case_stmt(3)
+                        case_stmt(4) case_stmt(5)
+                        return arg.back()->value();
+                    }
+                };
+                
+                struct switch_7
+                {
+                    static inline T process(const arg_list_t& arg)
+                    {
+                        case_stmt(0) case_stmt(1)
+                        case_stmt(2) case_stmt(3)
+                        case_stmt(4) case_stmt(5)
+                        case_stmt(6)
+                        return arg.back()->value();
+                    }
+                };
+                
+#undef case_stmt
+            };
+            
+            template <typename Allocator,
+            template <typename,typename> class Sequence>
+            inline expression_node_ptr switch_statement(Sequence<expression_node_ptr,Allocator>& arg_list)
+            {
+                if (arg_list.empty())
+                    return error_node();
+                else if (
+                         !all_nodes_valid(arg_list)   ||
+                         (arg_list.size() < 3)        ||
+                         ((arg_list.size() % 2) != 1)
+                         )
+                {
+                    details::free_all_nodes(*node_allocator_,arg_list);
+                    
+                    return error_node();
+                }
+                else if (is_constant_foldable(arg_list))
+                    return const_optimise_switch(arg_list);
+                
+                switch ((arg_list.size() - 1) / 2)
+                {
+#define case_stmt(N)                                                 \
+case N :                                                             \
+return node_allocator_->                                          \
+allocate<details::switch_n_node                         \
+<Type,typename switch_nodes::switch_##N> >(arg_list); \
+
+                        case_stmt(1)
+                        case_stmt(2)
+                        case_stmt(3)
+                        case_stmt(4)
+                        case_stmt(5)
+                        case_stmt(6)
+                        case_stmt(7)
+#undef case_stmt
+                        
+                    default : return node_allocator_->allocate<details::switch_node<Type> >(arg_list);
+                }
+            }
+            
+            template <typename Allocator,
+            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))
+                {
+                    details::free_all_nodes(*node_allocator_,arg_list);
+                    
+                    return error_node();
+                }
+                else if (is_constant_foldable(arg_list))
+                    return const_optimise_mswitch(arg_list);
+                else
+                    return node_allocator_->allocate<details::multi_switch_node<Type> >(arg_list);
+            }
+            
+#define unary_opr_switch_statements           \
+case_stmt(details::  e_abs,details::  abs_op) \
+case_stmt(details:: e_acos,details:: acos_op) \
+case_stmt(details::e_acosh,details::acosh_op) \
+case_stmt(details:: e_asin,details:: asin_op) \
+case_stmt(details::e_asinh,details::asinh_op) \
+case_stmt(details:: e_atan,details:: atan_op) \
+case_stmt(details::e_atanh,details::atanh_op) \
+case_stmt(details:: e_ceil,details:: ceil_op) \
+case_stmt(details::  e_cos,details::  cos_op) \
+case_stmt(details:: e_cosh,details:: cosh_op) \
+case_stmt(details::  e_exp,details::  exp_op) \
+case_stmt(details::e_expm1,details::expm1_op) \
+case_stmt(details::e_floor,details::floor_op) \
+case_stmt(details::  e_log,details::  log_op) \
+case_stmt(details::e_log10,details::log10_op) \
+case_stmt(details:: e_log2,details:: log2_op) \
+case_stmt(details::e_log1p,details::log1p_op) \
+case_stmt(details::  e_neg,details::  neg_op) \
+case_stmt(details::  e_pos,details::  pos_op) \
+case_stmt(details::e_round,details::round_op) \
+case_stmt(details::  e_sin,details::  sin_op) \
+case_stmt(details:: e_sinc,details:: sinc_op) \
+case_stmt(details:: e_sinh,details:: sinh_op) \
+case_stmt(details:: e_sqrt,details:: sqrt_op) \
+case_stmt(details::  e_tan,details::  tan_op) \
+case_stmt(details:: e_tanh,details:: tanh_op) \
+case_stmt(details::  e_cot,details::  cot_op) \
+case_stmt(details::  e_sec,details::  sec_op) \
+case_stmt(details::  e_csc,details::  csc_op) \
+case_stmt(details::  e_r2d,details::  r2d_op) \
+case_stmt(details::  e_d2r,details::  d2r_op) \
+case_stmt(details::  e_d2g,details::  d2g_op) \
+case_stmt(details::  e_g2d,details::  g2d_op) \
+case_stmt(details:: e_notl,details:: notl_op) \
+case_stmt(details::  e_sgn,details::  sgn_op) \
+case_stmt(details::  e_erf,details::  erf_op) \
+case_stmt(details:: e_erfc,details:: erfc_op) \
+case_stmt(details:: e_ncdf,details:: ncdf_op) \
+case_stmt(details:: e_frac,details:: frac_op) \
+case_stmt(details::e_trunc,details::trunc_op) \
+
+            inline expression_node_ptr synthesize_uv_expression(const details::operator_type& operation,
+                                                                expression_node_ptr (&branch)[1])
             {
-               return (details::build_string() << "t" << expr_gen.to_str(o0) << "((t" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t)");
-            }
-         };
-
-         struct synthesize_covovoc_expression2
-         {
-            typedef typename covovoc_t::type2 node_type;
-            typedef typename covovoc_t::sf4_type sf4_type;
-            typedef typename node_type::T0 T0;
-            typedef typename node_type::T1 T1;
-            typedef typename node_type::T2 T2;
-            typedef typename node_type::T3 T3;
-
-            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
-                                                      const details::operator_type& operation,
-                                                      expression_node_ptr (&branch)[2])
+                T& v = static_cast<details::variable_node<T>*>(branch[0])->ref();
+                
+                switch (operation)
+                {
+#define case_stmt(op0,op1)                                                          \
+case op0 : return node_allocator_->                                                 \
+allocate<typename details::unary_variable_node<Type,op1<Type> > >(v); \
+
+                        unary_opr_switch_statements
+#undef case_stmt
+                    default : return error_node();
+                }
+            }
+            
+            inline expression_node_ptr synthesize_uvec_expression(const details::operator_type& operation,
+                                                                  expression_node_ptr (&branch)[1])
+            {
+                switch (operation)
+                {
+#define case_stmt(op0,op1)                                                    \
+case op0 : return node_allocator_->                                           \
+allocate<typename details::unary_vector_node<Type,op1<Type> > > \
+(operation,branch[0]);                                       \
+
+                        unary_opr_switch_statements
+#undef case_stmt
+                    default : return error_node();
+                }
+            }
+            
+            inline expression_node_ptr synthesize_unary_expression(const details::operator_type& operation,
+                                                                   expression_node_ptr (&branch)[1])
+            {
+                switch (operation)
+                {
+#define case_stmt(op0,op1)                                                                \
+case op0 : return node_allocator_->                                                       \
+allocate<typename details::unary_branch_node<Type,op1<Type> > >(branch[0]); \
+
+                        unary_opr_switch_statements
+#undef case_stmt
+                    default : return error_node();
+                }
+            }
+            
+            inline expression_node_ptr const_optimise_sf3(const details::operator_type& operation,
+                                                          expression_node_ptr (&branch)[3])
+            {
+                expression_node_ptr temp_node = error_node();
+                
+                switch (operation)
+                {
+#define case_stmt(op)                                                        \
+case details::e_sf##op : temp_node = node_allocator_->                       \
+allocate<details::sf3_node<Type,details::sf##op##_op<Type> > > \
+(operation,branch);                                         \
+break;                                                            \
+
+                        case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03)
+                        case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07)
+                        case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11)
+                        case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15)
+                        case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19)
+                        case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23)
+                        case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27)
+                        case_stmt(28) case_stmt(29) case_stmt(30) case_stmt(31)
+                        case_stmt(32) case_stmt(33) case_stmt(34) case_stmt(35)
+                        case_stmt(36) case_stmt(37) case_stmt(38) case_stmt(39)
+                        case_stmt(40) case_stmt(41) case_stmt(42) case_stmt(43)
+                        case_stmt(44) case_stmt(45) case_stmt(46) case_stmt(47)
+#undef case_stmt
+                    default : return error_node();
+                }
+                
+                T v = temp_node->value();
+                
+                details::free_node(*node_allocator_,temp_node);
+                
+                return node_allocator_->allocate<literal_node_t>(v);
+            }
+            
+            inline expression_node_ptr varnode_optimise_sf3(const details::operator_type& operation, expression_node_ptr (&branch)[3])
+            {
+                typedef details::variable_node<Type>* variable_ptr;
+                
+                const Type& v0 = static_cast<variable_ptr>(branch[0])->ref();
+                const Type& v1 = static_cast<variable_ptr>(branch[1])->ref();
+                const Type& v2 = static_cast<variable_ptr>(branch[2])->ref();
+                
+                switch (operation)
+                {
+#define case_stmt(op)                                                                \
+case details::e_sf##op : return node_allocator_->                                    \
+allocate_rrr<details::sf3_var_node<Type,details::sf##op##_op<Type> > > \
+(v0,v1,v2);                                                         \
+
+                        case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03)
+                        case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07)
+                        case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11)
+                        case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15)
+                        case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19)
+                        case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23)
+                        case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27)
+                        case_stmt(28) case_stmt(29) case_stmt(30) case_stmt(31)
+                        case_stmt(32) case_stmt(33) case_stmt(34) case_stmt(35)
+                        case_stmt(36) case_stmt(37) case_stmt(38) case_stmt(39)
+                        case_stmt(40) case_stmt(41) case_stmt(42) case_stmt(43)
+                        case_stmt(44) case_stmt(45) case_stmt(46) case_stmt(47)
+#undef case_stmt
+                    default : return error_node();
+                }
+            }
+            
+            inline expression_node_ptr special_function(const details::operator_type& operation, expression_node_ptr (&branch)[3])
+            {
+                if (!all_nodes_valid(branch))
+                    return error_node();
+                else if (is_constant_foldable(branch))
+                    return const_optimise_sf3(operation,branch);
+                else if (all_nodes_variables(branch))
+                    return varnode_optimise_sf3(operation,branch);
+                else
+                {
+                    switch (operation)
+                    {
+#define case_stmt(op)                                                        \
+case details::e_sf##op : return node_allocator_->                            \
+allocate<details::sf3_node<Type,details::sf##op##_op<Type> > > \
+(operation,branch);                                         \
+
+                            case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03)
+                            case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07)
+                            case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11)
+                            case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15)
+                            case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19)
+                            case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23)
+                            case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27)
+                            case_stmt(28) case_stmt(29) case_stmt(30) case_stmt(31)
+                            case_stmt(32) case_stmt(33) case_stmt(34) case_stmt(35)
+                            case_stmt(36) case_stmt(37) case_stmt(38) case_stmt(39)
+                            case_stmt(40) case_stmt(41) case_stmt(42) case_stmt(43)
+                            case_stmt(44) case_stmt(45) case_stmt(46) case_stmt(47)
+#undef case_stmt
+                        default : return error_node();
+                    }
+                }
+            }
+            
+            inline expression_node_ptr const_optimise_sf4(const details::operator_type& operation, expression_node_ptr (&branch)[4])
+            {
+                expression_node_ptr temp_node = error_node();
+                
+                switch (operation)
+                {
+#define case_stmt(op)                                                                    \
+case details::e_sf##op : temp_node = node_allocator_->                                   \
+allocate<details::sf4_node<Type,details::sf##op##_op<Type> > > \
+(operation,branch);                                         \
+break;                                                                        \
+
+                        case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51)
+                        case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55)
+                        case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59)
+                        case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63)
+                        case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67)
+                        case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71)
+                        case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75)
+                        case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79)
+                        case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83)
+                        case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87)
+                        case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91)
+                        case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95)
+                        case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99)
+#undef case_stmt
+                    default : return error_node();
+                }
+                
+                T v = temp_node->value();
+                details::free_node(*node_allocator_,temp_node);
+                
+                return node_allocator_->allocate<literal_node_t>(v);
+            }
+            
+            inline expression_node_ptr varnode_optimise_sf4(const details::operator_type& operation, expression_node_ptr (&branch)[4])
+            {
+                typedef details::variable_node<Type>* variable_ptr;
+                
+                const Type& v0 = static_cast<variable_ptr>(branch[0])->ref();
+                const Type& v1 = static_cast<variable_ptr>(branch[1])->ref();
+                const Type& v2 = static_cast<variable_ptr>(branch[2])->ref();
+                const Type& v3 = static_cast<variable_ptr>(branch[3])->ref();
+                
+                switch (operation)
+                {
+#define case_stmt(op)                                                                 \
+case details::e_sf##op : return node_allocator_->                                     \
+allocate_rrrr<details::sf4_var_node<Type,details::sf##op##_op<Type> > > \
+(v0,v1,v2,v3);                                                       \
+
+                        case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51)
+                        case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55)
+                        case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59)
+                        case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63)
+                        case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67)
+                        case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71)
+                        case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75)
+                        case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79)
+                        case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83)
+                        case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87)
+                        case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91)
+                        case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95)
+                        case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99)
+#undef case_stmt
+                    default : return error_node();
+                }
+            }
+            
+            inline expression_node_ptr special_function(const details::operator_type& operation, expression_node_ptr (&branch)[4])
+            {
+                if (!all_nodes_valid(branch))
+                    return error_node();
+                else if (is_constant_foldable(branch))
+                    return const_optimise_sf4(operation,branch);
+                else if (all_nodes_variables(branch))
+                    return varnode_optimise_sf4(operation,branch);
+                switch (operation)
+                {
+#define case_stmt(op)                                                        \
+case details::e_sf##op : return node_allocator_->                            \
+allocate<details::sf4_node<Type,details::sf##op##_op<Type> > > \
+(operation,branch);                                         \
+
+                        case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51)
+                        case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55)
+                        case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59)
+                        case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63)
+                        case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67)
+                        case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71)
+                        case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75)
+                        case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79)
+                        case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83)
+                        case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87)
+                        case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91)
+                        case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95)
+                        case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99)
+#undef case_stmt
+                    default : return error_node();
+                }
+            }
+            
+            template <typename Allocator,
+            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();
+                
+                switch (operation)
+                {
+#define case_stmt(op0,op1)                                                 \
+case op0 : temp_node = node_allocator_->                                   \
+allocate<details::vararg_node<Type,op1<Type> > > \
+(arg_list);                                   \
+break;                                                          \
+
+                        case_stmt(details::e_sum,  details::vararg_add_op  )
+                        case_stmt(details::e_prod, details::vararg_mul_op  )
+                        case_stmt(details::e_avg,  details::vararg_avg_op  )
+                        case_stmt(details::e_min,  details::vararg_min_op  )
+                        case_stmt(details::e_max,  details::vararg_max_op  )
+                        case_stmt(details::e_mand, details::vararg_mand_op )
+                        case_stmt(details::e_mor,  details::vararg_mor_op  )
+                        case_stmt(details::e_multi,details::vararg_multi_op)
+#undef case_stmt
+                    default : return error_node();
+                }
+                
+                T v = temp_node->value();
+                details::free_node(*node_allocator_,temp_node);
+                
+                return node_allocator_->allocate<literal_node_t>(v);
+            }
+            
+            inline bool special_one_parameter_vararg(const details::operator_type& operation)
+            {
+                return (
+                        (details::e_sum  == operation) ||
+                        (details::e_prod == operation) ||
+                        (details::e_avg  == operation) ||
+                        (details::e_min  == operation) ||
+                        (details::e_max  == operation)
+                        );
+            }
+            
+            template <typename Allocator,
+            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)
+                {
+#define case_stmt(op0,op1)                                                   \
+case op0 : return node_allocator_->                                          \
+allocate<details::vararg_varnode<Type,op1<Type> > >(arg_list); \
+
+                        case_stmt(details::e_sum,  details::vararg_add_op  )
+                        case_stmt(details::e_prod, details::vararg_mul_op  )
+                        case_stmt(details::e_avg,  details::vararg_avg_op  )
+                        case_stmt(details::e_min,  details::vararg_min_op  )
+                        case_stmt(details::e_max,  details::vararg_max_op  )
+                        case_stmt(details::e_mand, details::vararg_mand_op )
+                        case_stmt(details::e_mor,  details::vararg_mor_op  )
+                        case_stmt(details::e_multi,details::vararg_multi_op)
+#undef case_stmt
+                    default : return error_node();
+                }
+            }
+            
+            template <typename Allocator,
+            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())
+                {
+                    switch (operation)
+                    {
+#define case_stmt(op0,op1)                                                      \
+case op0 : return node_allocator_->                                             \
+allocate<details::vectorize_node<Type,op1<Type> > >(arg_list[0]); \
+
+                            case_stmt(details::e_sum,  details::vec_add_op)
+                            case_stmt(details::e_prod, details::vec_mul_op)
+                            case_stmt(details::e_avg,  details::vec_avg_op)
+                            case_stmt(details::e_min,  details::vec_min_op)
+                            case_stmt(details::e_max,  details::vec_max_op)
+#undef case_stmt
+                        default : return error_node();
+                    }
+                }
+                else
+                    return error_node();
+            }
+            
+            template <typename Allocator,
+            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))
+                {
+                    details::free_all_nodes(*node_allocator_,arg_list);
+                    
+                    return error_node();
+                }
+                else if (is_constant_foldable(arg_list))
+                    return const_optimise_varargfunc(operation,arg_list);
+                else if ((arg_list.size() == 1) && details::is_ivector_node(arg_list[0]))
+                    return vectorize_func(operation,arg_list);
+                else if ((arg_list.size() == 1) && special_one_parameter_vararg(operation))
+                    return arg_list[0];
+                else if (all_nodes_variables(arg_list))
+                    return varnode_optimise_varargfunc(operation,arg_list);
+                
+                switch (operation)
+                {
+#define case_stmt(op0,op1)                                                \
+case op0 : return node_allocator_->                                       \
+allocate<details::vararg_node<Type,op1<Type> > >(arg_list); \
+
+                        case_stmt(details::e_sum,  details::vararg_add_op  )
+                        case_stmt(details::e_prod, details::vararg_mul_op  )
+                        case_stmt(details::e_avg,  details::vararg_avg_op  )
+                        case_stmt(details::e_min,  details::vararg_min_op  )
+                        case_stmt(details::e_max,  details::vararg_max_op  )
+                        case_stmt(details::e_mand, details::vararg_mand_op )
+                        case_stmt(details::e_mor,  details::vararg_mor_op  )
+                        case_stmt(details::e_multi,details::vararg_multi_op)
+#undef case_stmt
+                    default : return error_node();
+                }
+            }
+            
+            template <std::size_t N>
+            inline expression_node_ptr function(ifunction_t* f, expression_node_ptr (&b)[N])
+            {
+                typedef typename details::function_N_node<T,ifunction_t,N> function_N_node_t;
+                expression_node_ptr result = synthesize_expression<function_N_node_t,N>(f,b);
+                
+                if (0 == result)
+                    return error_node();
+                else
+                {
+                    // Can the function call be completely optimised?
+                    if (details::is_constant_node(result))
+                        return result;
+                    else if (!all_nodes_valid(b))
+                        return error_node();
+                    else if (N != f->param_count)
+                    {
+                        details::free_all_nodes(*node_allocator_,b);
+                        
+                        return error_node();
+                    }
+                    
+                    function_N_node_t* func_node_ptr = static_cast<function_N_node_t*>(result);
+                    
+                    if (func_node_ptr->init_branches(b))
+                        return result;
+                    else
+                    {
+                        details::free_all_nodes(*node_allocator_,b);
+                        
+                        return error_node();
+                    }
+                }
+            }
+            
+            inline expression_node_ptr function(ifunction_t* f)
+            {
+                typedef typename details::function_N_node<Type,ifunction_t,0> function_N_node_t;
+                return node_allocator_->allocate<function_N_node_t>(f);
+            }
+            
+            inline expression_node_ptr vararg_function_call(ivararg_function_t* vaf,
+                                                            std::vector<expression_node_ptr>& arg_list)
+            {
+                if (!all_nodes_valid(arg_list))
+                {
+                    details::free_all_nodes(*node_allocator_,arg_list);
+                    
+                    return error_node();
+                }
+                
+                typedef details::vararg_function_node<Type,ivararg_function_t> alloc_type;
+                
+                expression_node_ptr result = node_allocator_->allocate<alloc_type>(vaf,arg_list);
+                
+                if (
+                    !arg_list.empty()        &&
+                    !vaf->has_side_effects() &&
+                    is_constant_foldable(arg_list)
+                    )
+                {
+                    Type v = result->value();
+                    details::free_node(*node_allocator_,result);
+                    result = node_allocator_->allocate<literal_node_t>(v);
+                }
+                
+                parser_->state_.activate_side_effect("vararg_function_call()");
+                
+                return result;
+            }
+            
+            inline expression_node_ptr generic_function_call(igeneric_function_t* gf,
+                                                             std::vector<expression_node_ptr>& arg_list,
+                                                             const std::size_t& param_seq_index = std::numeric_limits<std::size_t>::max())
+            {
+                if (!all_nodes_valid(arg_list))
+                {
+                    details::free_all_nodes(*node_allocator_,arg_list);
+                    return error_node();
+                }
+                
+                typedef details::generic_function_node     <Type,igeneric_function_t> alloc_type1;
+                typedef details::multimode_genfunction_node<Type,igeneric_function_t> alloc_type2;
+                
+                const std::size_t no_psi = std::numeric_limits<std::size_t>::max();
+                
+                expression_node_ptr result = error_node();
+                
+                if (no_psi == param_seq_index)
+                    result = node_allocator_->allocate<alloc_type1>(arg_list,gf);
+                else
+                    result = node_allocator_->allocate<alloc_type2>(gf,param_seq_index,arg_list);
+                
+                alloc_type1* genfunc_node_ptr = static_cast<alloc_type1*>(result);
+                
+                if (
+                    !arg_list.empty()       &&
+                    !gf->has_side_effects() &&
+                    is_constant_foldable(arg_list)
+                    )
+                {
+                    genfunc_node_ptr->init_branches();
+                    Type v = result->value();
+                    details::free_node(*node_allocator_,result);
+                    return node_allocator_->allocate<literal_node_t>(v);
+                }
+                else if (genfunc_node_ptr->init_branches())
+                {
+                    parser_->state_.activate_side_effect("generic_function_call()");
+                    return result;
+                }
+                else
+                {
+                    details::free_node(*node_allocator_,result);
+                    details::free_all_nodes(*node_allocator_,arg_list);
+                    return error_node();
+                }
+            }
+            
+            inline expression_node_ptr string_function_call(igeneric_function_t* gf,
+                                                            std::vector<expression_node_ptr>& arg_list,
+                                                            const std::size_t& param_seq_index = std::numeric_limits<std::size_t>::max())
+            {
+                if (!all_nodes_valid(arg_list))
+                {
+                    details::free_all_nodes(*node_allocator_,arg_list);
+                    return error_node();
+                }
+                
+                typedef details::string_function_node      <Type,igeneric_function_t> alloc_type1;
+                typedef details::multimode_strfunction_node<Type,igeneric_function_t> alloc_type2;
+                
+                const std::size_t no_psi = std::numeric_limits<std::size_t>::max();
+                
+                expression_node_ptr result = error_node();
+                
+                if (no_psi == param_seq_index)
+                    result = node_allocator_->allocate<alloc_type1>(gf,arg_list);
+                else
+                    result = node_allocator_->allocate<alloc_type2>(gf,param_seq_index,arg_list);
+                
+                alloc_type1* strfunc_node_ptr = static_cast<alloc_type1*>(result);
+                
+                if (
+                    !arg_list.empty()       &&
+                    !gf->has_side_effects() &&
+                    is_constant_foldable(arg_list)
+                    )
+                {
+                    strfunc_node_ptr->init_branches();
+                    
+                    Type v = result->value();
+                    
+                    details::free_node(*node_allocator_,result);
+                    
+                    return node_allocator_->allocate<literal_node_t>(v);
+                }
+                else if (strfunc_node_ptr->init_branches())
+                {
+                    parser_->state_.activate_side_effect("string_function_call()");
+                    
+                    return result;
+                }
+                else
+                {
+                    details::free_node(*node_allocator_,result);
+                    details::free_all_nodes(*node_allocator_,arg_list);
+                    
+                    return error_node();
+                }
+            }
+            
+            inline expression_node_ptr return_call(std::vector<expression_node_ptr>& arg_list)
+            {
+                if (!all_nodes_valid(arg_list))
+                {
+                    details::free_all_nodes(*node_allocator_,arg_list);
+                    return error_node();
+                }
+                
+                typedef details::return_node<Type> alloc_type;
+                
+                expression_node_ptr result = node_allocator_->
+                allocate_rr<alloc_type>(arg_list,parser_->results_ctx());
+                
+                alloc_type* return_node_ptr = static_cast<alloc_type*>(result);
+                
+                if (return_node_ptr->init_branches())
+                {
+                    parser_->state_.activate_side_effect("return_call()");
+                    
+                    return result;
+                }
+                else
+                {
+                    details::free_node(*node_allocator_,result);
+                    details::free_all_nodes(*node_allocator_,arg_list);
+                    
+                    return error_node();
+                }
+            }
+            
+            inline expression_node_ptr return_envelope(expression_node_ptr body,
+                                                       results_context_t* rc,
+                                                       bool*& return_invoked)
+            {
+                typedef details::return_envelope_node<Type> alloc_type;
+                
+                expression_node_ptr result = node_allocator_->
+                allocate_cr<alloc_type>(body,(*rc));
+                
+                return_invoked = static_cast<alloc_type*>(result)->retinvk_ptr();
+                
+                return result;
+            }
+            
+            inline expression_node_ptr vector_element(const std::string& symbol,
+                                                      vector_holder_ptr vector_base,
+                                                      expression_node_ptr index)
+            {
+                expression_node_ptr result = error_node();
+                
+                if (details::is_constant_node(index))
+                {
+                    std::size_t i = static_cast<std::size_t>(details::numeric::to_int64(index->value()));
+                    
+                    details::free_node(*node_allocator_,index);
+                    
+                    if (vector_base->rebaseable())
+                    {
+                        return node_allocator_->allocate<rebasevector_celem_node_t>(i,vector_base);
+                    }
+                    
+                    scope_element& se = parser_->sem_.get_element(symbol,i);
+                    
+                    if (se.index == i)
+                    {
+                        result = se.var_node;
+                    }
+                    else
+                    {
+                        scope_element nse;
+                        nse.name      = symbol;
+                        nse.active    = true;
+                        nse.ref_count = 1;
+                        nse.type      = scope_element::e_vecelem;
+                        nse.index     = i;
+                        nse.depth     = parser_->state_.scope_depth;
+                        nse.data      = 0;
+                        nse.var_node  = node_allocator_->allocate<variable_node_t>((*(*vector_base)[i]));
+                        
+                        if (!parser_->sem_.add_element(nse))
+                        {
+                            parser_->set_synthesis_error("Failed to add new local vector element to SEM [1]");
+                            
+                            parser_->sem_.free_element(nse);
+                            
+                            result = error_node();
+                        }
+                        
+                        exprtk_debug(("vector_element() - INFO - Added new local vector element: %s\n",nse.name.c_str()));
+                        
+                        parser_->state_.activate_side_effect("vector_element()");
+                        
+                        result = nse.var_node;
+                    }
+                }
+                else if (vector_base->rebaseable())
+                    result = node_allocator_->allocate<rebasevector_elem_node_t>(index,vector_base);
+                else
+                    result = node_allocator_->allocate<vector_elem_node_t>(index,vector_base);
+                
+                return result;
+            }
+            
+        private:
+            
+            template <std::size_t N, typename NodePtr>
+            inline bool is_constant_foldable(NodePtr (&b)[N]) const
+            {
+                for (std::size_t i = 0; i < N; ++i)
+                {
+                    if (0 == b[i])
+                        return false;
+                    else if (!details::is_constant_node(b[i]))
+                        return false;
+                }
+                
+                return true;
+            }
+            
+            template <typename NodePtr,
+            typename Allocator,
+            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)
+                {
+                    if (0 == b[i])
+                        return false;
+                    else if (!details::is_constant_node(b[i]))
+                        return false;
+                }
+                
+                return true;
+            }
+            
+            void lodge_assignment(symbol_type cst, expression_node_ptr node)
+            {
+                parser_->state_.activate_side_effect("lodge_assignment()");
+                
+                if (!parser_->dec_.collect_assignments())
+                    return;
+                
+                std::string symbol_name;
+                
+                switch (cst)
+                {
+                    case e_st_variable : symbol_name = parser_->symtab_store_
+                        .get_variable_name(node);
+                        break;
+                        
+#ifndef exprtk_disable_string_capabilities
+                    case e_st_string   : symbol_name = parser_->symtab_store_
+                        .get_stringvar_name(node);
+                        break;
+#endif
+                        
+                    case e_st_vector   : {
+                        typedef details::vector_holder<T> vector_holder_t;
+                        
+                        vector_holder_t& vh = static_cast<vector_node_t*>(node)->vec_holder();
+                        
+                        symbol_name = parser_->symtab_store_.get_vector_name(&vh);
+                    }
+                        break;
+                        
+                    case e_st_vecelem  : {
+                        typedef details::vector_holder<T> vector_holder_t;
+                        
+                        vector_holder_t& vh = static_cast<vector_elem_node_t*>(node)->vec_holder();
+                        
+                        symbol_name = parser_->symtab_store_.get_vector_name(&vh);
+                        
+                        cst = e_st_vector;
+                    }
+                        break;
+                        
+                    default            : return;
+                }
+                
+                if (!symbol_name.empty())
+                {
+                    parser_->dec_.add_assignment(symbol_name,cst);
+                }
+            }
+            
+            inline expression_node_ptr synthesize_assignment_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
+            {
+                if (details::is_variable_node(branch[0]))
+                {
+                    lodge_assignment(e_st_variable,branch[0]);
+                    
+                    return synthesize_expression<assignment_node_t,2>(operation,branch);
+                }
+                else if (details::is_vector_elem_node(branch[0]))
+                {
+                    lodge_assignment(e_st_vecelem,branch[0]);
+                    
+                    return synthesize_expression<assignment_vec_elem_node_t, 2>(operation, branch);
+                }
+                else if (details::is_rebasevector_elem_node(branch[0]))
+                {
+                    lodge_assignment(e_st_vecelem,branch[0]);
+                    
+                    return synthesize_expression<assignment_rebasevec_elem_node_t, 2>(operation, branch);
+                }
+                else if (details::is_rebasevector_celem_node(branch[0]))
+                {
+                    lodge_assignment(e_st_vecelem,branch[0]);
+                    
+                    return synthesize_expression<assignment_rebasevec_celem_node_t, 2>(operation, branch);
+                }
+#ifndef exprtk_disable_string_capabilities
+                else if (details::is_string_node(branch[0]))
+                {
+                    lodge_assignment(e_st_string,branch[0]);
+                    
+                    return synthesize_expression<assignment_string_node_t,2>(operation,branch);
+                }
+                else if (details::is_string_range_node(branch[0]))
+                {
+                    lodge_assignment(e_st_string,branch[0]);
+                    
+                    return synthesize_expression<assignment_string_range_node_t,2>(operation,branch);
+                }
+#endif
+                else if (details::is_vector_node(branch[0]))
+                {
+                    lodge_assignment(e_st_vector,branch[0]);
+                    
+                    if (details::is_ivector_node(branch[1]))
+                        return synthesize_expression<assignment_vecvec_node_t,2>(operation,branch);
+                    else
+                        return synthesize_expression<assignment_vec_node_t,2>(operation,branch);
+                }
+                else
+                {
+                    parser_->set_synthesis_error("Invalid assignment operation.[1]");
+                    
+                    return error_node();
+                }
+            }
+            
+            inline expression_node_ptr synthesize_assignment_operation_expression(const details::operator_type& operation,
+                                                                                  expression_node_ptr (&branch)[2])
             {
-               // c0 o0 ((v0 o1 v1) o2 c1)
-               typedef typename synthesize_vovoc_expression0::node_type vovoc_t;
-
-               const vovoc_t* vovoc = static_cast<const vovoc_t*>(branch[1]);
-               const Type  c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
-               const Type& v0 = vovoc->t0();
-               const Type& v1 = vovoc->t1();
-               const Type  c1 = vovoc->t2();
-               const details::operator_type o0 = operation;
-               const details::operator_type o1 = expr_gen.get_operator(vovoc->f0());
-               const details::operator_type o2 = expr_gen.get_operator(vovoc->f1());
-
-               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f1 = vovoc->f0();
-               binary_functor_t f2 = vovoc->f1();
-
-               details::free_node(*(expr_gen.node_allocator_),branch[0]);
-               details::free_node(*(expr_gen.node_allocator_),branch[1]);
-
-               expression_node_ptr result = error_node();
-
-               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,v1,c1,result))
-                  return result;
-               else if (!expr_gen.valid_operator(o0,f0))
-                  return error_node();
-
-               exprtk_debug(("c0 o0 ((v0 o1 v1) o2 c1)\n"));
-
-               return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,v1,c1,f0,f1,f2);
+                if (details::is_variable_node(branch[0]))
+                {
+                    lodge_assignment(e_st_variable,branch[0]);
+                    
+                    switch (operation)
+                    {
+#define case_stmt(op0,op1)                                                                  \
+case op0 : return node_allocator_->                                                         \
+template allocate_rrr<typename details::assignment_op_node<Type,op1<Type> > > \
+(operation,branch[0],branch[1]);                                           \
+
+                            case_stmt(details::e_addass,details::add_op)
+                            case_stmt(details::e_subass,details::sub_op)
+                            case_stmt(details::e_mulass,details::mul_op)
+                            case_stmt(details::e_divass,details::div_op)
+                            case_stmt(details::e_modass,details::mod_op)
+#undef case_stmt
+                        default : return error_node();
+                    }
+                }
+                else if (details::is_vector_elem_node(branch[0]))
+                {
+                    switch (operation)
+                    {
+#define case_stmt(op0,op1)                                                                            \
+case op0 : return node_allocator_->                                                                   \
+template allocate_rrr<typename details::assignment_vec_elem_op_node<Type,op1<Type> > > \
+(operation,branch[0],branch[1]);                                                    \
+
+                            case_stmt(details::e_addass,details::add_op)
+                            case_stmt(details::e_subass,details::sub_op)
+                            case_stmt(details::e_mulass,details::mul_op)
+                            case_stmt(details::e_divass,details::div_op)
+                            case_stmt(details::e_modass,details::mod_op)
+#undef case_stmt
+                        default : return error_node();
+                    }
+                }
+                else if (details::is_rebasevector_elem_node(branch[0]))
+                {
+                    switch (operation)
+                    {
+#define case_stmt(op0,op1)                                                                                  \
+case op0 : return node_allocator_->                                                                         \
+template allocate_rrr<typename details::assignment_rebasevec_elem_op_node<Type,op1<Type> > > \
+(operation,branch[0],branch[1]);                                                          \
+
+                            case_stmt(details::e_addass,details::add_op)
+                            case_stmt(details::e_subass,details::sub_op)
+                            case_stmt(details::e_mulass,details::mul_op)
+                            case_stmt(details::e_divass,details::div_op)
+                            case_stmt(details::e_modass,details::mod_op)
+#undef case_stmt
+                        default : return error_node();
+                    }
+                }
+                else if (details::is_rebasevector_celem_node(branch[0]))
+                {
+                    switch (operation)
+                    {
+#define case_stmt(op0,op1)                                                                                   \
+case op0 : return node_allocator_->                                                                          \
+template allocate_rrr<typename details::assignment_rebasevec_celem_op_node<Type,op1<Type> > > \
+(operation,branch[0],branch[1]);                                                           \
+
+                            case_stmt(details::e_addass,details::add_op)
+                            case_stmt(details::e_subass,details::sub_op)
+                            case_stmt(details::e_mulass,details::mul_op)
+                            case_stmt(details::e_divass,details::div_op)
+                            case_stmt(details::e_modass,details::mod_op)
+#undef case_stmt
+                        default : return error_node();
+                    }
+                }
+                else if (details::is_vector_node(branch[0]))
+                {
+                    lodge_assignment(e_st_vector,branch[0]);
+                    
+                    if (details::is_ivector_node(branch[1]))
+                    {
+                        switch (operation)
+                        {
+#define case_stmt(op0,op1)                                                                         \
+case op0 : return node_allocator_->                                                                \
+template allocate_rrr<typename details::assignment_vecvec_op_node<Type,op1<Type> > > \
+(operation,branch[0],branch[1]);                                                  \
+
+                                case_stmt(details::e_addass,details::add_op)
+                                case_stmt(details::e_subass,details::sub_op)
+                                case_stmt(details::e_mulass,details::mul_op)
+                                case_stmt(details::e_divass,details::div_op)
+                                case_stmt(details::e_modass,details::mod_op)
+#undef case_stmt
+                            default : return error_node();
+                        }
+                    }
+                    else
+                    {
+                        switch (operation)
+                        {
+#define case_stmt(op0,op1)                                                                      \
+case op0 : return node_allocator_->                                                             \
+template allocate_rrr<typename details::assignment_vec_op_node<Type,op1<Type> > > \
+(operation,branch[0],branch[1]);                                               \
+
+                                case_stmt(details::e_addass,details::add_op)
+                                case_stmt(details::e_subass,details::sub_op)
+                                case_stmt(details::e_mulass,details::mul_op)
+                                case_stmt(details::e_divass,details::div_op)
+                                case_stmt(details::e_modass,details::mod_op)
+#undef case_stmt
+                            default : return error_node();
+                        }
+                    }
+                }
+#ifndef exprtk_disable_string_capabilities
+                else if (
+                         (details::e_addass == operation) &&
+                         details::is_string_node(branch[0])
+                         )
+                {
+                    typedef details::assignment_string_node<T,details::asn_addassignment> addass_t;
+                    
+                    lodge_assignment(e_st_string,branch[0]);
+                    
+                    return synthesize_expression<addass_t,2>(operation,branch);
+                }
+#endif
+                else
+                {
+                    parser_->set_synthesis_error("Invalid assignment operation[2]");
+                    
+                    return error_node();
+                }
+            }
+            
+            inline expression_node_ptr synthesize_veceqineqlogic_operation_expression(const details::operator_type& operation,
+                                                                                      expression_node_ptr (&branch)[2])
+            {
+                const bool is_b0_ivec = details::is_ivector_node(branch[0]);
+                const bool is_b1_ivec = details::is_ivector_node(branch[1]);
+                
+#define batch_eqineq_logic_case               \
+case_stmt(details::   e_lt,details::   lt_op) \
+case_stmt(details::  e_lte,details::  lte_op) \
+case_stmt(details::   e_gt,details::   gt_op) \
+case_stmt(details::  e_gte,details::  gte_op) \
+case_stmt(details::   e_eq,details::   eq_op) \
+case_stmt(details::   e_ne,details::   ne_op) \
+case_stmt(details::e_equal,details::equal_op) \
+case_stmt(details::  e_and,  details::and_op) \
+case_stmt(details:: e_nand, details::nand_op) \
+case_stmt(details::   e_or, details::  or_op) \
+case_stmt(details::  e_nor, details:: nor_op) \
+case_stmt(details::  e_xor, details:: xor_op) \
+case_stmt(details:: e_xnor, details::xnor_op) \
+
+                if (is_b0_ivec && is_b1_ivec)
+                {
+                    switch (operation)
+                    {
+#define case_stmt(op0,op1)                                                                     \
+case op0 : return node_allocator_->                                                            \
+template allocate_rrr<typename details::vec_binop_vecvec_node<Type,op1<Type> > > \
+(operation,branch[0],branch[1]);                                              \
+
+                            batch_eqineq_logic_case
+#undef case_stmt
+                        default : return error_node();
+                    }
+                }
+                else if (is_b0_ivec && !is_b1_ivec)
+                {
+                    switch (operation)
+                    {
+#define case_stmt(op0,op1)                                                                     \
+case op0 : return node_allocator_->                                                            \
+template allocate_rrr<typename details::vec_binop_vecval_node<Type,op1<Type> > > \
+(operation,branch[0],branch[1]);                                              \
+
+                            batch_eqineq_logic_case
+#undef case_stmt
+                        default : return error_node();
+                    }
+                }
+                else if (!is_b0_ivec && is_b1_ivec)
+                {
+                    switch (operation)
+                    {
+#define case_stmt(op0,op1)                                                                     \
+case op0 : return node_allocator_->                                                            \
+template allocate_rrr<typename details::vec_binop_valvec_node<Type,op1<Type> > > \
+(operation,branch[0],branch[1]);                                              \
+
+                            batch_eqineq_logic_case
+#undef case_stmt
+                        default : return error_node();
+                    }
+                }
+                else
+                    return error_node();
+                
+#undef batch_eqineq_logic_case
+            }
+            
+            inline expression_node_ptr synthesize_vecarithmetic_operation_expression(const details::operator_type& operation,
+                                                                                     expression_node_ptr (&branch)[2])
+            {
+                const bool is_b0_ivec = details::is_ivector_node(branch[0]);
+                const bool is_b1_ivec = details::is_ivector_node(branch[1]);
+                
+#define vector_ops                        \
+case_stmt(details::e_add,details::add_op) \
+case_stmt(details::e_sub,details::sub_op) \
+case_stmt(details::e_mul,details::mul_op) \
+case_stmt(details::e_div,details::div_op) \
+case_stmt(details::e_mod,details::mod_op) \
+
+                if (is_b0_ivec && is_b1_ivec)
+                {
+                    switch (operation)
+                    {
+#define case_stmt(op0,op1)                                                                     \
+case op0 : return node_allocator_->                                                            \
+template allocate_rrr<typename details::vec_binop_vecvec_node<Type,op1<Type> > > \
+(operation,branch[0],branch[1]);                                              \
+
+                            vector_ops
+                            case_stmt(details::e_pow,details:: pow_op)
+#undef case_stmt
+                        default : return error_node();
+                    }
+                }
+                else if (is_b0_ivec && !is_b1_ivec)
+                {
+                    switch (operation)
+                    {
+#define case_stmt(op0,op1)                                                                     \
+case op0 : return node_allocator_->                                                            \
+template allocate_rrr<typename details::vec_binop_vecval_node<Type,op1<Type> > > \
+(operation,branch[0],branch[1]);                                              \
+
+                            vector_ops
+                            case_stmt(details::e_pow,details:: pow_op)
+#undef case_stmt
+                        default : return error_node();
+                    }
+                }
+                else if (!is_b0_ivec && is_b1_ivec)
+                {
+                    switch (operation)
+                    {
+#define case_stmt(op0,op1)                                                                     \
+case op0 : return node_allocator_->                                                            \
+template allocate_rrr<typename details::vec_binop_valvec_node<Type,op1<Type> > > \
+(operation,branch[0],branch[1]);                                              \
+
+                            vector_ops
+#undef case_stmt
+                        default : return error_node();
+                    }
+                }
+                else
+                    return error_node();
+                
+#undef vector_ops
+            }
+            
+            inline expression_node_ptr synthesize_swap_expression(expression_node_ptr (&branch)[2])
+            {
+                const bool v0_is_ivar = details::is_ivariable_node(branch[0]);
+                const bool v1_is_ivar = details::is_ivariable_node(branch[1]);
+                
+                const bool v0_is_ivec = details::is_ivector_node(branch[0]);
+                const bool v1_is_ivec = details::is_ivector_node(branch[1]);
+                
+#ifndef exprtk_disable_string_capabilities
+                const bool v0_is_str = details::is_generally_string_node(branch[0]);
+                const bool v1_is_str = details::is_generally_string_node(branch[1]);
+#endif
+                
+                expression_node_ptr result = error_node();
+                
+                if (v0_is_ivar && v1_is_ivar)
+                {
+                    typedef details::variable_node<T>* variable_node_ptr;
+                    
+                    variable_node_ptr v0 = variable_node_ptr(0);
+                    variable_node_ptr v1 = variable_node_ptr(0);
+                    
+                    if (
+                        (0 != (v0 = dynamic_cast<variable_node_ptr>(branch[0]))) &&
+                        (0 != (v1 = dynamic_cast<variable_node_ptr>(branch[1])))
+                        )
+                    {
+                        result = node_allocator_->allocate<details::swap_node<T> >(v0,v1);
+                    }
+                    else
+                        result = node_allocator_->allocate<details::swap_generic_node<T> >(branch[0],branch[1]);
+                }
+                else if (v0_is_ivec && v1_is_ivec)
+                {
+                    result = node_allocator_->allocate<details::swap_vecvec_node<T> >(branch[0],branch[1]);
+                }
+#ifndef exprtk_disable_string_capabilities
+                else if (v0_is_str && v1_is_str)
+                {
+                    if (is_string_node(branch[0]) && is_string_node(branch[1]))
+                        result = node_allocator_->allocate<details::swap_string_node<T> >(branch[0],branch[1]);
+                    else
+                        result = node_allocator_->allocate<details::swap_genstrings_node<T> >(branch[0],branch[1]);
+                }
+#endif
+                else
+                {
+                    parser_->set_synthesis_error("Only variables, strings, vectors or vector elements can be swapped");
+                    
+                    return error_node();
+                }
+                
+                parser_->state_.activate_side_effect("synthesize_swap_expression()");
+                
+                return result;
+            }
+            
+#ifndef exprtk_disable_sc_andor
+            inline expression_node_ptr synthesize_shortcircuit_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
+            {
+                expression_node_ptr result = error_node();
+                
+                if (details::is_constant_node(branch[0]))
+                {
+                    if (
+                        (details::e_scand == operation) &&
+                        std::equal_to<T>()(T(0),branch[0]->value())
+                        )
+                        result = node_allocator_->allocate_c<literal_node_t>(T(0));
+                    else if (
+                             (details::e_scor == operation) &&
+                             std::not_equal_to<T>()(T(0),branch[0]->value())
+                             )
+                        result = node_allocator_->allocate_c<literal_node_t>(T(1));
+                }
+                
+                if (details::is_constant_node(branch[1]) && (0 == result))
+                {
+                    if (
+                        (details::e_scand == operation) &&
+                        std::equal_to<T>()(T(0),branch[1]->value())
+                        )
+                        result = node_allocator_->allocate_c<literal_node_t>(T(0));
+                    else if (
+                             (details::e_scor == operation) &&
+                             std::not_equal_to<T>()(T(0),branch[1]->value())
+                             )
+                        result = node_allocator_->allocate_c<literal_node_t>(T(1));
+                }
+                
+                if (result)
+                {
+                    free_node(*node_allocator_,branch[0]);
+                    free_node(*node_allocator_,branch[1]);
+                    
+                    return result;
+                }
+                else if (details::e_scand == operation)
+                    return synthesize_expression<scand_node_t,2>(operation,branch);
+                else if (details::e_scor == operation)
+                    return synthesize_expression<scor_node_t,2>(operation,branch);
+                else
+                    return error_node();
             }
-
-            static inline std::string id(expression_generator<Type>& expr_gen,
-                                         const details::operator_type o0,
-                                         const details::operator_type o1,
-                                         const details::operator_type o2)
+#else
+            inline expression_node_ptr synthesize_shortcircuit_expression(const details::operator_type&, expression_node_ptr (&)[2])
             {
-               return (details::build_string() << "t" << expr_gen.to_str(o0) << "((t" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t)");
+                return error_node();
             }
-         };
-
-         struct synthesize_vococov_expression2
-         {
-            typedef typename vococov_t::type2 node_type;
-            static inline expression_node_ptr process(expression_generator<Type>&, const details::operator_type&, expression_node_ptr (&)[2])
-            {
-               // v0 o0 ((c0 o1 c1) o2 v1) - Not possible
-               exprtk_debug(("v0 o0 ((c0 o1 c1) o2 v1) - Not possible\n"));
-               return error_node();
+#endif
+            
+#define basic_opr_switch_statements       \
+case_stmt(details::e_add,details::add_op) \
+case_stmt(details::e_sub,details::sub_op) \
+case_stmt(details::e_mul,details::mul_op) \
+case_stmt(details::e_div,details::div_op) \
+case_stmt(details::e_mod,details::mod_op) \
+case_stmt(details::e_pow,details::pow_op) \
+
+#define extended_opr_switch_statements      \
+case_stmt(details::  e_lt,details::  lt_op) \
+case_stmt(details:: e_lte,details:: lte_op) \
+case_stmt(details::  e_gt,details::  gt_op) \
+case_stmt(details:: e_gte,details:: gte_op) \
+case_stmt(details::  e_eq,details::  eq_op) \
+case_stmt(details::  e_ne,details::  ne_op) \
+case_stmt(details:: e_and,details:: and_op) \
+case_stmt(details::e_nand,details::nand_op) \
+case_stmt(details::  e_or,details::  or_op) \
+case_stmt(details:: e_nor,details:: nor_op) \
+case_stmt(details:: e_xor,details:: xor_op) \
+case_stmt(details::e_xnor,details::xnor_op) \
+
+#ifndef exprtk_disable_cardinal_pow_optimisation
+            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)
+                {
+#define case_stmt(cp)                                                     \
+case cp : return node_allocator_->                                        \
+allocate<IPowNode<T,details::numeric::fast_exp<T,cp> > >(v); \
+
+                        case_stmt( 1) case_stmt( 2) case_stmt( 3) case_stmt( 4)
+                        case_stmt( 5) case_stmt( 6) case_stmt( 7) case_stmt( 8)
+                        case_stmt( 9) case_stmt(10) case_stmt(11) case_stmt(12)
+                        case_stmt(13) case_stmt(14) case_stmt(15) case_stmt(16)
+                        case_stmt(17) case_stmt(18) case_stmt(19) case_stmt(20)
+                        case_stmt(21) case_stmt(22) case_stmt(23) case_stmt(24)
+                        case_stmt(25) case_stmt(26) case_stmt(27) case_stmt(28)
+                        case_stmt(29) case_stmt(30) case_stmt(31) case_stmt(32)
+                        case_stmt(33) case_stmt(34) case_stmt(35) case_stmt(36)
+                        case_stmt(37) case_stmt(38) case_stmt(39) case_stmt(40)
+                        case_stmt(41) case_stmt(42) case_stmt(43) case_stmt(44)
+                        case_stmt(45) case_stmt(46) case_stmt(47) case_stmt(48)
+                        case_stmt(49) case_stmt(50) case_stmt(51) case_stmt(52)
+                        case_stmt(53) case_stmt(54) case_stmt(55) case_stmt(56)
+                        case_stmt(57) case_stmt(58) case_stmt(59) case_stmt(60)
+#undef case_stmt
+                    default : return error_node();
+                }
+            }
+            
+            inline expression_node_ptr cardinal_pow_optimisation(const T& v, const T& c)
+            {
+                const bool not_recipricol = (c >= T(0));
+                const int p = details::numeric::to_int32(details::numeric::abs(c));
+                
+                if (0 == p)
+                    return node_allocator_->allocate_c<literal_node_t>(T(1));
+                else if (std::equal_to<T>()(T(2),c))
+                {
+                    return node_allocator_->
+                    template allocate_rr<typename details::vov_node<Type,details::mul_op<Type> > >(v,v);
+                }
+                else
+                {
+                    if (not_recipricol)
+                        return cardinal_pow_optimisation_impl<T,details::ipow_node>(v,p);
+                    else
+                        return cardinal_pow_optimisation_impl<T,details::ipowinv_node>(v,p);
+                }
+            }
+            
+            inline bool cardinal_pow_optimisable(const details::operator_type& operation, const T& c)
+            {
+                return (details::e_pow == operation) && (details::numeric::abs(c) <= T(60)) && details::numeric::is_integer(c);
+            }
+            
+            inline expression_node_ptr cardinal_pow_optimisation(expression_node_ptr (&branch)[2])
+            {
+                const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
+                const bool not_recipricol = (c >= T(0));
+                const int p = details::numeric::to_int32(details::numeric::abs(c));
+                
+                node_allocator_->free(branch[1]);
+                
+                if (0 == p)
+                {
+                    details::free_all_nodes(*node_allocator_, branch);
+                    return node_allocator_->allocate_c<literal_node_t>(T(1));
+                }
+                else if (not_recipricol)
+                    return cardinal_pow_optimisation_impl<expression_node_ptr,details::bipow_node>(branch[0],p);
+                else
+                    return cardinal_pow_optimisation_impl<expression_node_ptr,details::bipowninv_node>(branch[0],p);
             }
-
-            static inline std::string id(expression_generator<Type>&,
-                                         const details::operator_type, const details::operator_type, const details::operator_type)
+#else
+            inline expression_node_ptr cardinal_pow_optimisation(T&, const T&)
             {
-               return "INVALID";
+                return error_node();
             }
-         };
-
-         struct synthesize_vovovov_expression3
-         {
-            typedef typename vovovov_t::type3 node_type;
-            typedef typename vovovov_t::sf4_type sf4_type;
-            typedef typename node_type::T0 T0;
-            typedef typename node_type::T1 T1;
-            typedef typename node_type::T2 T2;
-            typedef typename node_type::T3 T3;
-
-            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
-                                                      const details::operator_type& operation,
-                                                      expression_node_ptr (&branch)[2])
+            
+            inline bool cardinal_pow_optimisable(const details::operator_type&, const T&)
             {
-               // ((v0 o0 v1) o1 v2) o2 v3
-               typedef typename synthesize_vovov_expression0::node_type vovov_t;
-
-               const vovov_t* vovov = static_cast<const vovov_t*>(branch[0]);
-               const Type& v0 = vovov->t0();
-               const Type& v1 = vovov->t1();
-               const Type& v2 = vovov->t2();
-               const Type& v3 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
-               const details::operator_type o0 = expr_gen.get_operator(vovov->f0());
-               const details::operator_type o1 = expr_gen.get_operator(vovov->f1());
-               const details::operator_type o2 = operation;
-
-               binary_functor_t f0 = vovov->f0();
-               binary_functor_t f1 = vovov->f1();
-               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
-
-               details::free_node(*(expr_gen.node_allocator_),branch[0]);
-
-               expression_node_ptr result = error_node();
-
-               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,v3,result))
-                  return result;
-               else if (!expr_gen.valid_operator(o2,f2))
-                  return error_node();
-
-               exprtk_debug(("((v0 o0 v1) o1 v2) o2 v3\n"));
-
-               return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,v3,f0,f1,f2);
+                return false;
             }
-
-            static inline std::string id(expression_generator<Type>& expr_gen,
-                                         const details::operator_type o0,
-                                         const details::operator_type o1,
-                                         const details::operator_type o2)
+            
+            inline expression_node_ptr cardinal_pow_optimisation(expression_node_ptr(&)[2])
             {
-               return (details::build_string() << "((t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
+                return error_node();
             }
-         };
-
-         struct synthesize_vovovoc_expression3
-         {
-            typedef typename vovovoc_t::type3 node_type;
-            typedef typename vovovoc_t::sf4_type sf4_type;
-            typedef typename node_type::T0 T0;
-            typedef typename node_type::T1 T1;
-            typedef typename node_type::T2 T2;
-            typedef typename node_type::T3 T3;
-
-            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
-                                                      const details::operator_type& operation,
-                                                      expression_node_ptr (&branch)[2])
-            {
-               // ((v0 o0 v1) o1 v2) o2 c
-               typedef typename synthesize_vovov_expression0::node_type vovov_t;
-
-               const vovov_t* vovov = static_cast<const vovov_t*>(branch[0]);
-               const Type& v0 = vovov->t0();
-               const Type& v1 = vovov->t1();
-               const Type& v2 = vovov->t2();
-               const Type   c = static_cast<details::literal_node<Type>*>(branch[1])->value();
-               const details::operator_type o0 = expr_gen.get_operator(vovov->f0());
-               const details::operator_type o1 = expr_gen.get_operator(vovov->f1());
-               const details::operator_type o2 = operation;
-
-               binary_functor_t f0 = vovov->f0();
-               binary_functor_t f1 = vovov->f1();
-               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
-
-               details::free_node(*(expr_gen.node_allocator_),branch[0]);
-               details::free_node(*(expr_gen.node_allocator_),branch[1]);
-
-               expression_node_ptr result = error_node();
-
-               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,c,result))
-                  return result;
-               else if (!expr_gen.valid_operator(o2,f2))
-                  return error_node();
-
-               exprtk_debug(("((v0 o0 v1) o1 v2) o2 c\n"));
-
-               return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,c,f0,f1,f2);
-            }
-
-            static inline std::string id(expression_generator<Type>& expr_gen,
-                                         const details::operator_type o0,
-                                         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");
-            }
-         };
-
-         struct synthesize_vovocov_expression3
-         {
-            typedef typename vovocov_t::type3 node_type;
-            typedef typename vovocov_t::sf4_type sf4_type;
-            typedef typename node_type::T0 T0;
-            typedef typename node_type::T1 T1;
-            typedef typename node_type::T2 T2;
-            typedef typename node_type::T3 T3;
-
-            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
-                                                      const details::operator_type& operation,
-                                                      expression_node_ptr (&branch)[2])
-            {
-               // ((v0 o0 v1) o1 c) o2 v2
-               typedef typename synthesize_vovoc_expression0::node_type vovoc_t;
-
-               const vovoc_t* vovoc = static_cast<const vovoc_t*>(branch[0]);
-               const Type& v0 = vovoc->t0();
-               const Type& v1 = vovoc->t1();
-               const Type   c = vovoc->t2();
-               const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
-               const details::operator_type o0 = expr_gen.get_operator(vovoc->f0());
-               const details::operator_type o1 = expr_gen.get_operator(vovoc->f1());
-               const details::operator_type o2 = operation;
-
-               binary_functor_t f0 = vovoc->f0();
-               binary_functor_t f1 = vovoc->f1();
-               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
-
-               details::free_node(*(expr_gen.node_allocator_),branch[0]);
-
-               expression_node_ptr result = error_node();
-
-               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,c,v2,result))
-                  return result;
-               else if (!expr_gen.valid_operator(o2,f2))
-                  return error_node();
-
-               exprtk_debug(("((v0 o0 v1) o1 c) o2 v2\n"));
-
-               return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,c,v2,f0,f1,f2);
-            }
-
-            static inline std::string id(expression_generator<Type>& expr_gen,
-                                         const details::operator_type o0,
-                                         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");
-            }
-         };
-
-         struct synthesize_vocovov_expression3
-         {
-            typedef typename vocovov_t::type3 node_type;
-            typedef typename vocovov_t::sf4_type sf4_type;
-            typedef typename node_type::T0 T0;
-            typedef typename node_type::T1 T1;
-            typedef typename node_type::T2 T2;
-            typedef typename node_type::T3 T3;
-
-            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
-                                                      const details::operator_type& operation,
-                                                      expression_node_ptr (&branch)[2])
-            {
-               // ((v0 o0 c) o1 v1) o2 v2
-               typedef typename synthesize_vocov_expression0::node_type vocov_t;
-
-               const vocov_t* vocov = static_cast<const vocov_t*>(branch[0]);
-               const Type& v0 = vocov->t0();
-               const Type   c = vocov->t1();
-               const Type& v1 = vocov->t2();
-               const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
-               const details::operator_type o0 = expr_gen.get_operator(vocov->f0());
-               const details::operator_type o1 = expr_gen.get_operator(vocov->f1());
-               const details::operator_type o2 = operation;
-
-               binary_functor_t f0 = vocov->f0();
-               binary_functor_t f1 = vocov->f1();
-               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
-
-               details::free_node(*(expr_gen.node_allocator_),branch[0]);
-
-               expression_node_ptr result = error_node();
-
-               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c,v1,v2,result))
-                  return result;
-               else if (!expr_gen.valid_operator(o2,f2))
-                  return error_node();
-
-               exprtk_debug(("((v0 o0 c) o1 v1) o2 v2\n"));
-
-               return node_type::allocate(*(expr_gen.node_allocator_),v0,c,v1,v2,f0,f1,f2);
-            }
-
-            static inline std::string id(expression_generator<Type>& expr_gen,
-                                         const details::operator_type o0,
-                                         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");
-            }
-         };
-
-         struct synthesize_covovov_expression3
-         {
-            typedef typename covovov_t::type3 node_type;
-            typedef typename covovov_t::sf4_type sf4_type;
-            typedef typename node_type::T0 T0;
-            typedef typename node_type::T1 T1;
-            typedef typename node_type::T2 T2;
-            typedef typename node_type::T3 T3;
-
-            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
-                                                      const details::operator_type& operation,
-                                                      expression_node_ptr (&branch)[2])
-            {
-               // ((c o0 v0) o1 v1) o2 v2
-               typedef typename synthesize_covov_expression0::node_type covov_t;
-
-               const covov_t* covov = static_cast<const covov_t*>(branch[0]);
-               const Type   c = covov->t0();
-               const Type& v0 = covov->t1();
-               const Type& v1 = covov->t2();
-               const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
-               const details::operator_type o0 = expr_gen.get_operator(covov->f0());
-               const details::operator_type o1 = expr_gen.get_operator(covov->f1());
-               const details::operator_type o2 = operation;
-
-               binary_functor_t f0 = covov->f0();
-               binary_functor_t f1 = covov->f1();
-               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
-
-               details::free_node(*(expr_gen.node_allocator_),branch[0]);
-
-               expression_node_ptr result = error_node();
-
-               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c,v0,v1,v2,result))
-                  return result;
-               else if (!expr_gen.valid_operator(o2,f2))
-                  return error_node();
-
-               exprtk_debug(("((c o0 v0) o1 v1) o2 v2\n"));
-
-               return node_type::allocate(*(expr_gen.node_allocator_),c,v0,v1,v2,f0,f1,f2);
-            }
-
-            static inline std::string id(expression_generator<Type>& expr_gen,
-                                         const details::operator_type o0,
-                                         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");
-            }
-         };
-
-         struct synthesize_covocov_expression3
-         {
-            typedef typename covocov_t::type3 node_type;
-            typedef typename covocov_t::sf4_type sf4_type;
-            typedef typename node_type::T0 T0;
-            typedef typename node_type::T1 T1;
-            typedef typename node_type::T2 T2;
-            typedef typename node_type::T3 T3;
-
-            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
-                                                      const details::operator_type& operation,
-                                                      expression_node_ptr (&branch)[2])
-            {
-               // ((c0 o0 v0) o1 c1) o2 v1
-               typedef typename synthesize_covoc_expression0::node_type covoc_t;
-
-               const covoc_t* covoc = static_cast<const covoc_t*>(branch[0]);
-               const Type  c0 = covoc->t0();
-               const Type& v0 = covoc->t1();
-               const Type  c1 = covoc->t2();
-               const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
-               const details::operator_type o0 = expr_gen.get_operator(covoc->f0());
-               const details::operator_type o1 = expr_gen.get_operator(covoc->f1());
-               const details::operator_type o2 = operation;
-
-               binary_functor_t f0 = covoc->f0();
-               binary_functor_t f1 = covoc->f1();
-               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
-
-               details::free_node(*(expr_gen.node_allocator_),branch[0]);
-
-               expression_node_ptr result = error_node();
-
-               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,c1,v1,result))
-                  return result;
-               else if (!expr_gen.valid_operator(o2,f2))
-                  return error_node();
-
-               exprtk_debug(("((c0 o0 v0) o1 c1) o2 v1\n"));
-
-               return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,c1,v1,f0,f1,f2);
-            }
-
-            static inline std::string id(expression_generator<Type>& expr_gen,
-                                         const details::operator_type o0,
-                                         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");
-            }
-         };
-
-         struct synthesize_vocovoc_expression3
-         {
-            typedef typename vocovoc_t::type3 node_type;
-            typedef typename vocovoc_t::sf4_type sf4_type;
-            typedef typename node_type::T0 T0;
-            typedef typename node_type::T1 T1;
-            typedef typename node_type::T2 T2;
-            typedef typename node_type::T3 T3;
-
-            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
-                                                      const details::operator_type& operation,
-                                                      expression_node_ptr (&branch)[2])
-            {
-               // ((v0 o0 c0) o1 v1) o2 c1
-               typedef typename synthesize_vocov_expression0::node_type vocov_t;
-
-               const vocov_t* vocov = static_cast<const vocov_t*>(branch[0]);
-               const Type& v0 = vocov->t0();
-               const Type  c0 = vocov->t1();
-               const Type& v1 = vocov->t2();
-               const Type  c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
-               const details::operator_type o0 = expr_gen.get_operator(vocov->f0());
-               const details::operator_type o1 = expr_gen.get_operator(vocov->f1());
-               const details::operator_type o2 = operation;
-
-               binary_functor_t f0 = vocov->f0();
-               binary_functor_t f1 = vocov->f1();
-               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
-
-               details::free_node(*(expr_gen.node_allocator_),branch[0]);
-               details::free_node(*(expr_gen.node_allocator_),branch[1]);
-
-               expression_node_ptr result = error_node();
-
-               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c0,v1,c1,result))
-                  return result;
-               else if (!expr_gen.valid_operator(o2,f2))
-                  return error_node();
-
-               exprtk_debug(("((v0 o0 c0) o1 v1) o2 c1\n"));
-
-               return node_type::allocate(*(expr_gen.node_allocator_),v0,c0,v1,c1,f0,f1,f2);
-            }
-
-            static inline std::string id(expression_generator<Type>& expr_gen,
-                                         const details::operator_type o0,
-                                         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");
-            }
-         };
-
-         struct synthesize_covovoc_expression3
-         {
-            typedef typename covovoc_t::type3 node_type;
-            typedef typename covovoc_t::sf4_type sf4_type;
-            typedef typename node_type::T0 T0;
-            typedef typename node_type::T1 T1;
-            typedef typename node_type::T2 T2;
-            typedef typename node_type::T3 T3;
-
-            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
-                                                      const details::operator_type& operation,
-                                                      expression_node_ptr (&branch)[2])
-            {
-               // ((c0 o0 v0) o1 v1) o2 c1
-               typedef typename synthesize_covov_expression0::node_type covov_t;
-
-               const covov_t* covov = static_cast<const covov_t*>(branch[0]);
-               const Type  c0 = covov->t0();
-               const Type& v0 = covov->t1();
-               const Type& v1 = covov->t2();
-               const Type  c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
-               const details::operator_type o0 = expr_gen.get_operator(covov->f0());
-               const details::operator_type o1 = expr_gen.get_operator(covov->f1());
-               const details::operator_type o2 = operation;
-
-               binary_functor_t f0 = covov->f0();
-               binary_functor_t f1 = covov->f1();
-               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
-
-               details::free_node(*(expr_gen.node_allocator_),branch[0]);
-               details::free_node(*(expr_gen.node_allocator_),branch[1]);
-
-               expression_node_ptr result = error_node();
-
-               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,v1,c1,result))
-                  return result;
-               else if (!expr_gen.valid_operator(o2,f2))
-                  return error_node();
-
-               exprtk_debug(("((c0 o0 v0) o1 v1) o2 c1\n"));
-
-               return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,v1,c1,f0,f1,f2);
-            }
-
-            static inline std::string id(expression_generator<Type>& expr_gen,
-                                         const details::operator_type o0,
-                                         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");
-            }
-         };
-
-         struct synthesize_vococov_expression3
-         {
-            typedef typename vococov_t::type3 node_type;
-            typedef typename vococov_t::sf4_type sf4_type;
-            typedef typename node_type::T0 T0;
-            typedef typename node_type::T1 T1;
-            typedef typename node_type::T2 T2;
-            typedef typename node_type::T3 T3;
-
-            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
-                                                      const details::operator_type& operation,
-                                                      expression_node_ptr (&branch)[2])
-            {
-               // ((v0 o0 c0) o1 c1) o2 v1
-               typedef typename synthesize_vococ_expression0::node_type vococ_t;
-
-               const vococ_t* vococ = static_cast<const vococ_t*>(branch[0]);
-               const Type& v0 = vococ->t0();
-               const Type  c0 = vococ->t1();
-               const Type  c1 = vococ->t2();
-               const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
-               const details::operator_type o0 = expr_gen.get_operator(vococ->f0());
-               const details::operator_type o1 = expr_gen.get_operator(vococ->f1());
-               const details::operator_type o2 = operation;
-
-               binary_functor_t f0 = vococ->f0();
-               binary_functor_t f1 = vococ->f1();
-               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
-
-               details::free_node(*(expr_gen.node_allocator_),branch[0]);
-
-               expression_node_ptr result = error_node();
-
-               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c0,c1,v1,result))
-                  return result;
-               else if (!expr_gen.valid_operator(o2,f2))
-                  return error_node();
-
-               exprtk_debug(("((v0 o0 c0) o1 c1) o2 v1\n"));
-
-               return node_type::allocate(*(expr_gen.node_allocator_),v0,c0,c1,v1,f0,f1,f2);
-            }
-
-            static inline std::string id(expression_generator<Type>& expr_gen,
-                                         const details::operator_type o0,
-                                         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");
-            }
-         };
-
-         struct synthesize_vovovov_expression4
-         {
-            typedef typename vovovov_t::type4 node_type;
-            typedef typename vovovov_t::sf4_type sf4_type;
-            typedef typename node_type::T0 T0;
-            typedef typename node_type::T1 T1;
-            typedef typename node_type::T2 T2;
-            typedef typename node_type::T3 T3;
-
-            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
-                                                      const details::operator_type& operation,
-                                                      expression_node_ptr (&branch)[2])
-            {
-               // (v0 o0 (v1 o1 v2)) o2 v3
-               typedef typename synthesize_vovov_expression1::node_type vovov_t;
-
-               const vovov_t* vovov = static_cast<const vovov_t*>(branch[0]);
-               const Type& v0 = vovov->t0();
-               const Type& v1 = vovov->t1();
-               const Type& v2 = vovov->t2();
-               const Type& v3 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
-               const details::operator_type o0 = expr_gen.get_operator(vovov->f0());
-               const details::operator_type o1 = expr_gen.get_operator(vovov->f1());
-               const details::operator_type o2 = operation;
-
-               binary_functor_t f0 = vovov->f0();
-               binary_functor_t f1 = vovov->f1();
-               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
-
-               details::free_node(*(expr_gen.node_allocator_),branch[0]);
-
-               expression_node_ptr result = error_node();
-
-               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,v3,result))
-                  return result;
-               else if (!expr_gen.valid_operator(o2,f2))
-                  return error_node();
-
-               exprtk_debug(("(v0 o0 (v1 o1 v2)) o2 v3\n"));
-
-               return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,v3,f0,f1,f2);
-            }
-
-            static inline std::string id(expression_generator<Type>& expr_gen,
-                                         const details::operator_type o0,
-                                         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");
-            }
-         };
-
-         struct synthesize_vovovoc_expression4
-         {
-            typedef typename vovovoc_t::type4 node_type;
-            typedef typename vovovoc_t::sf4_type sf4_type;
-            typedef typename node_type::T0 T0;
-            typedef typename node_type::T1 T1;
-            typedef typename node_type::T2 T2;
-            typedef typename node_type::T3 T3;
-
-            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
-                                                      const details::operator_type& operation,
-                                                      expression_node_ptr (&branch)[2])
-            {
-               // ((v0 o0 (v1 o1 v2)) o2 c)
-               typedef typename synthesize_vovov_expression1::node_type vovov_t;
-
-               const vovov_t* vovov = static_cast<const vovov_t*>(branch[0]);
-               const Type& v0 = vovov->t0();
-               const Type& v1 = vovov->t1();
-               const Type& v2 = vovov->t2();
-               const Type   c = static_cast<details::literal_node<Type>*>(branch[1])->value();
-               const details::operator_type o0 = expr_gen.get_operator(vovov->f0());
-               const details::operator_type o1 = expr_gen.get_operator(vovov->f1());
-               const details::operator_type o2 = operation;
-
-               binary_functor_t f0 = vovov->f0();
-               binary_functor_t f1 = vovov->f1();
-               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
-
-               details::free_node(*(expr_gen.node_allocator_),branch[0]);
-               details::free_node(*(expr_gen.node_allocator_),branch[1]);
-
-               expression_node_ptr result = error_node();
-
-               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,c,result))
-                  return result;
-               else if (!expr_gen.valid_operator(o2,f2))
-                  return error_node();
-
-               exprtk_debug(("((v0 o0 (v1 o1 v2)) o2 c)\n"));
-
-               return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,c,f0,f1,f2);
-            }
-
-            static inline std::string id(expression_generator<Type>& expr_gen,
-                                         const details::operator_type o0,
-                                         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");
-            }
-         };
-
-         struct synthesize_vovocov_expression4
-         {
-            typedef typename vovocov_t::type4 node_type;
-            typedef typename vovocov_t::sf4_type sf4_type;
-            typedef typename node_type::T0 T0;
-            typedef typename node_type::T1 T1;
-            typedef typename node_type::T2 T2;
-            typedef typename node_type::T3 T3;
-
-            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
-                                                      const details::operator_type& operation,
-                                                      expression_node_ptr (&branch)[2])
-            {
-               // ((v0 o0 (v1 o1 c)) o2 v1)
-               typedef typename synthesize_vovoc_expression1::node_type vovoc_t;
-
-               const vovoc_t* vovoc = static_cast<const vovoc_t*>(branch[0]);
-               const Type& v0 = vovoc->t0();
-               const Type& v1 = vovoc->t1();
-               const Type   c = vovoc->t2();
-               const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
-               const details::operator_type o0 = expr_gen.get_operator(vovoc->f0());
-               const details::operator_type o1 = expr_gen.get_operator(vovoc->f1());
-               const details::operator_type o2 = operation;
-
-               binary_functor_t f0 = vovoc->f0();
-               binary_functor_t f1 = vovoc->f1();
-               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
-
-               details::free_node(*(expr_gen.node_allocator_),branch[0]);
-
-               expression_node_ptr result = error_node();
-
-               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,c,v2,result))
-                  return result;
-               else if (!expr_gen.valid_operator(o2,f2))
-                  return error_node();
-
-               exprtk_debug(("((v0 o0 (v1 o1 c)) o2 v1)\n"));
-
-               return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,c,v2,f0,f1,f2);
-            }
-
-            static inline std::string id(expression_generator<Type>& expr_gen,
-                                         const details::operator_type o0,
-                                         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");
-            }
-         };
-
-         struct synthesize_vocovov_expression4
-         {
-            typedef typename vocovov_t::type4 node_type;
-            typedef typename vocovov_t::sf4_type sf4_type;
-            typedef typename node_type::T0 T0;
-            typedef typename node_type::T1 T1;
-            typedef typename node_type::T2 T2;
-            typedef typename node_type::T3 T3;
-
-            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
-                                                      const details::operator_type& operation,
-                                                      expression_node_ptr (&branch)[2])
-            {
-               // ((v0 o0 (c o1 v1)) o2 v2)
-               typedef typename synthesize_vocov_expression1::node_type vocov_t;
-
-               const vocov_t* vocov = static_cast<const vocov_t*>(branch[0]);
-               const Type& v0 = vocov->t0();
-               const Type   c = vocov->t1();
-               const Type& v1 = vocov->t2();
-               const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
-               const details::operator_type o0 = expr_gen.get_operator(vocov->f0());
-               const details::operator_type o1 = expr_gen.get_operator(vocov->f1());
-               const details::operator_type o2 = operation;
-
-               binary_functor_t f0 = vocov->f0();
-               binary_functor_t f1 = vocov->f1();
-               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
-
-               details::free_node(*(expr_gen.node_allocator_),branch[0]);
-               expression_node_ptr result = error_node();
-
-               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c,v1,v2,result))
-                  return result;
-               else if (!expr_gen.valid_operator(o2,f2))
-                  return error_node();
-
-               exprtk_debug(("((v0 o0 (c o1 v1)) o2 v2)\n"));
-
-               return node_type::allocate(*(expr_gen.node_allocator_),v0,c,v1,v2,f0,f1,f2);
-            }
-
-            static inline std::string id(expression_generator<Type>& expr_gen,
-                                         const details::operator_type o0,
-                                         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");
-            }
-         };
-
-         struct synthesize_covovov_expression4
-         {
-            typedef typename covovov_t::type4 node_type;
-            typedef typename covovov_t::sf4_type sf4_type;
-            typedef typename node_type::T0 T0;
-            typedef typename node_type::T1 T1;
-            typedef typename node_type::T2 T2;
-            typedef typename node_type::T3 T3;
-
-            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
-                                                      const details::operator_type& operation,
-                                                      expression_node_ptr (&branch)[2])
-            {
-               // ((c o0 (v0 o1 v1)) o2 v2)
-               typedef typename synthesize_covov_expression1::node_type covov_t;
-
-               const covov_t* covov = static_cast<const covov_t*>(branch[0]);
-               const Type   c = covov->t0();
-               const Type& v0 = covov->t1();
-               const Type& v1 = covov->t2();
-               const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
-               const details::operator_type o0 = expr_gen.get_operator(covov->f0());
-               const details::operator_type o1 = expr_gen.get_operator(covov->f1());
-               const details::operator_type o2 = operation;
-
-               binary_functor_t f0 = covov->f0();
-               binary_functor_t f1 = covov->f1();
-               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
-
-               details::free_node(*(expr_gen.node_allocator_),branch[0]);
-
-               expression_node_ptr result = error_node();
-
-               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c,v0,v1,v2,result))
-                  return result;
-               else if (!expr_gen.valid_operator(o2,f2))
-                  return error_node();
-
-               exprtk_debug(("((c o0 (v0 o1 v1)) o2 v2)\n"));
-
-               return node_type::allocate(*(expr_gen.node_allocator_),c,v0,v1,v2,f0,f1,f2);
-            }
-
-            static inline std::string id(expression_generator<Type>& expr_gen,
-                                         const details::operator_type o0,
-                                         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");
-            }
-         };
-
-         struct synthesize_covocov_expression4
-         {
-            typedef typename covocov_t::type4 node_type;
-            typedef typename covocov_t::sf4_type sf4_type;
-            typedef typename node_type::T0 T0;
-            typedef typename node_type::T1 T1;
-            typedef typename node_type::T2 T2;
-            typedef typename node_type::T3 T3;
-
-            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
-                                                      const details::operator_type& operation,
-                                                      expression_node_ptr (&branch)[2])
-            {
-               // ((c0 o0 (v0 o1 c1)) o2 v1)
-               typedef typename synthesize_covoc_expression1::node_type covoc_t;
-
-               const covoc_t* covoc = static_cast<const covoc_t*>(branch[0]);
-               const Type  c0 = covoc->t0();
-               const Type& v0 = covoc->t1();
-               const Type  c1 = covoc->t2();
-               const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
-               const details::operator_type o0 = expr_gen.get_operator(covoc->f0());
-               const details::operator_type o1 = expr_gen.get_operator(covoc->f1());
-               const details::operator_type o2 = operation;
-
-               binary_functor_t f0 = covoc->f0();
-               binary_functor_t f1 = covoc->f1();
-               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
-
-               details::free_node(*(expr_gen.node_allocator_),branch[0]);
-
-               expression_node_ptr result = error_node();
-
-               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,c1,v1,result))
-                  return result;
-               else if (!expr_gen.valid_operator(o2,f2))
-                  return error_node();
-
-               exprtk_debug(("((c0 o0 (v0 o1 c1)) o2 v1)\n"));
-
-               return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,c1,v1,f0,f1,f2);
-            }
-
-            static inline std::string id(expression_generator<Type>& expr_gen,
-                                         const details::operator_type o0,
-                                         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");
-            }
-         };
-
-         struct synthesize_vocovoc_expression4
-         {
-            typedef typename vocovoc_t::type4 node_type;
-            typedef typename vocovoc_t::sf4_type sf4_type;
-            typedef typename node_type::T0 T0;
-            typedef typename node_type::T1 T1;
-            typedef typename node_type::T2 T2;
-            typedef typename node_type::T3 T3;
-
-            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
-                                                      const details::operator_type& operation,
-                                                      expression_node_ptr (&branch)[2])
-            {
-               // ((v0 o0 (c0 o1 v1)) o2 c1)
-               typedef typename synthesize_vocov_expression1::node_type vocov_t;
-
-               const vocov_t* vocov = static_cast<const vocov_t*>(branch[0]);
-               const Type& v0 = vocov->t0();
-               const Type  c0 = vocov->t1();
-               const Type& v1 = vocov->t2();
-               const Type  c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
-               const details::operator_type o0 = expr_gen.get_operator(vocov->f0());
-               const details::operator_type o1 = expr_gen.get_operator(vocov->f1());
-               const details::operator_type o2 = operation;
-
-               binary_functor_t f0 = vocov->f0();
-               binary_functor_t f1 = vocov->f1();
-               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
-
-               details::free_node(*(expr_gen.node_allocator_),branch[0]);
-               details::free_node(*(expr_gen.node_allocator_),branch[1]);
-
-               expression_node_ptr result = error_node();
-
-               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c0,v1,c1,result))
-                  return result;
-               else if (!expr_gen.valid_operator(o2,f2))
-                  return error_node();
-
-               exprtk_debug(("((v0 o0 (c0 o1 v1)) o2 c1)\n"));
-
-               return node_type::allocate(*(expr_gen.node_allocator_),v0,c0,v1,c1,f0,f1,f2);
-            }
-
-            static inline std::string id(expression_generator<Type>& expr_gen,
-                                         const details::operator_type o0,
-                                         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");
-            }
-         };
-
-         struct synthesize_covovoc_expression4
-         {
-            typedef typename covovoc_t::type4 node_type;
-            typedef typename covovoc_t::sf4_type sf4_type;
-            typedef typename node_type::T0 T0;
-            typedef typename node_type::T1 T1;
-            typedef typename node_type::T2 T2;
-            typedef typename node_type::T3 T3;
-
-            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
-                                                      const details::operator_type& operation,
-                                                      expression_node_ptr (&branch)[2])
-            {
-               // ((c0 o0 (v0 o1 v1)) o2 c1)
-               typedef typename synthesize_covov_expression1::node_type covov_t;
-
-               const covov_t* covov = static_cast<const covov_t*>(branch[0]);
-               const Type  c0 = covov->t0();
-               const Type& v0 = covov->t1();
-               const Type& v1 = covov->t2();
-               const Type  c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
-               const details::operator_type o0 = expr_gen.get_operator(covov->f0());
-               const details::operator_type o1 = expr_gen.get_operator(covov->f1());
-               const details::operator_type o2 = operation;
-
-               binary_functor_t f0 = covov->f0();
-               binary_functor_t f1 = covov->f1();
-               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
-
-               details::free_node(*(expr_gen.node_allocator_),branch[0]);
-               details::free_node(*(expr_gen.node_allocator_),branch[1]);
-
-               expression_node_ptr result = error_node();
-
-               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,v1,c1,result))
-                  return result;
-               else if (!expr_gen.valid_operator(o2,f2))
-                  return error_node();
-
-               exprtk_debug(("((c0 o0 (v0 o1 v1)) o2 c1)\n"));
-
-               return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,v1,c1,f0,f1,f2);
-            }
-
-            static inline std::string id(expression_generator<Type>& expr_gen,
-                                         const details::operator_type o0,
-                                         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");
-            }
-         };
-
-         struct synthesize_vococov_expression4
-         {
-            typedef typename vococov_t::type4 node_type;
-            static inline expression_node_ptr process(expression_generator<Type>&, const details::operator_type&, expression_node_ptr (&)[2])
-            {
-               // ((v0 o0 (c0 o1 c1)) o2 v1) - Not possible
-               exprtk_debug(("((v0 o0 (c0 o1 c1)) o2 v1) - Not possible\n"));
-               return error_node();
-            }
-
-            static inline std::string id(expression_generator<Type>&,
-                                         const details::operator_type, const details::operator_type, const details::operator_type)
-            {
-               return "INVALID";
-            }
-         };
-         #endif
-
-         inline expression_node_ptr synthesize_uvouv_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
-         {
-            // Definition: uv o uv
-            details::operator_type o0 = static_cast<details::uv_base_node<Type>*>(branch[0])->operation();
-            details::operator_type o1 = static_cast<details::uv_base_node<Type>*>(branch[1])->operation();
-            const Type& v0 = static_cast<details::uv_base_node<Type>*>(branch[0])->v();
-            const Type& v1 = static_cast<details::uv_base_node<Type>*>(branch[1])->v();
-            unary_functor_t u0 = reinterpret_cast<unary_functor_t> (0);
-            unary_functor_t u1 = reinterpret_cast<unary_functor_t> (0);
-            binary_functor_t f = reinterpret_cast<binary_functor_t>(0);
-
-            if (!valid_operator(o0,u0))
-               return error_node();
-            else if (!valid_operator(o1,u1))
-               return error_node();
-            else if (!valid_operator(operation,f))
-               return error_node();
-
-            expression_node_ptr result = error_node();
-
-            if (
-                 (details::e_neg == o0) &&
-                 (details::e_neg == o1)
-               )
-            {
-               switch (operation)
-               {
-                  // (-v0 + -v1) --> -(v0 + v1)
-                  case details::e_add : result = (*this)(details::e_neg,
-                                                    node_allocator_->
-                                                       allocate_rr<typename details::
-                                                          vov_node<Type,details::add_op<Type> > >(v0,v1));
-                                        exprtk_debug(("(-v0 + -v1) --> -(v0 + v1)\n"));
-                                        break;
-
-                  // (-v0 - -v1) --> (v1 - v0)
-                  case details::e_sub : result = node_allocator_->
-                                                    allocate_rr<typename details::
-                                                       vov_node<Type,details::sub_op<Type> > >(v1,v0);
-                                        exprtk_debug(("(-v0 - -v1) --> (v1 - v0)\n"));
-                                        break;
-
-                  // (-v0 * -v1) --> (v0 * v1)
-                  case details::e_mul : result = node_allocator_->
-                                                    allocate_rr<typename details::
-                                                       vov_node<Type,details::mul_op<Type> > >(v0,v1);
-                                        exprtk_debug(("(-v0 * -v1) --> (v0 * v1)\n"));
-                                        break;
-
-                  // (-v0 / -v1) --> (v0 / v1)
-                  case details::e_div : result = node_allocator_->
-                                                    allocate_rr<typename details::
-                                                       vov_node<Type,details::div_op<Type> > >(v0,v1);
-                                        exprtk_debug(("(-v0 / -v1) --> (v0 / v1)\n"));
-                                        break;
-
-                  default             : break;
-               }
-            }
-
-            if (0 == result)
-            {
-               result = node_allocator_->
-                            allocate_rrrrr<typename details::uvouv_node<Type> >(v0,v1,u0,u1,f);
-            }
-
-            details::free_all_nodes(*node_allocator_,branch);
-            return result;
-         }
-
-         #undef basic_opr_switch_statements
-         #undef extended_opr_switch_statements
-         #undef unary_opr_switch_statements
-
-         #ifndef exprtk_disable_string_capabilities
-
-         #define string_opr_switch_statements          \
-         case_stmt(details::  e_lt ,details::   lt_op) \
-         case_stmt(details:: e_lte ,details::  lte_op) \
-         case_stmt(details::  e_gt ,details::   gt_op) \
-         case_stmt(details:: e_gte ,details::  gte_op) \
-         case_stmt(details::  e_eq ,details::   eq_op) \
-         case_stmt(details::  e_ne ,details::   ne_op) \
-         case_stmt(details::e_in   ,details::   in_op) \
-         case_stmt(details::e_like ,details:: like_op) \
-         case_stmt(details::e_ilike,details::ilike_op) \
-
-         template <typename T0, typename T1>
-         inline expression_node_ptr synthesize_str_xrox_expression_impl(const details::operator_type& opr,
-                                                                        T0 s0, T1 s1,
-                                                                        range_t rp0)
-         {
-            switch (opr)
-            {
-               #define case_stmt(op0,op1)                                                                       \
-               case op0 : return node_allocator_->                                                              \
-                             allocate_ttt<typename details::str_xrox_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \
-                                (s0,s1,rp0);                                                                    \
-
-               string_opr_switch_statements
-               #undef case_stmt
-               default : return error_node();
-            }
-         }
-
-         template <typename T0, typename T1>
-         inline expression_node_ptr synthesize_str_xoxr_expression_impl(const details::operator_type& opr,
-                                                                        T0 s0, T1 s1,
-                                                                        range_t rp1)
-         {
-            switch (opr)
-            {
-               #define case_stmt(op0,op1)                                                                       \
-               case op0 : return node_allocator_->                                                              \
-                             allocate_ttt<typename details::str_xoxr_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \
-                                (s0,s1,rp1);                                                                    \
-
-               string_opr_switch_statements
-               #undef case_stmt
-               default : return error_node();
-            }
-         }
-
-         template <typename T0, typename T1>
-         inline expression_node_ptr synthesize_str_xroxr_expression_impl(const details::operator_type& opr,
-                                                                         T0 s0, T1 s1,
-                                                                         range_t rp0, range_t rp1)
-         {
-            switch (opr)
-            {
-               #define case_stmt(op0,op1)                                                                         \
-               case op0 : return node_allocator_->                                                                \
-                             allocate_tttt<typename details::str_xroxr_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \
-                                (s0,s1,rp0,rp1);                                                                  \
-
-               string_opr_switch_statements
-               #undef case_stmt
-               default : return error_node();
-            }
-         }
-
-         template <typename T0, typename T1>
-         inline expression_node_ptr synthesize_sos_expression_impl(const details::operator_type& opr, T0 s0, T1 s1)
-         {
-            switch (opr)
-            {
-               #define case_stmt(op0,op1)                                                                 \
-               case op0 : return node_allocator_->                                                        \
-                             allocate_tt<typename details::sos_node<Type,T0,T1,op1<Type> >,T0,T1>(s0,s1); \
-
-               string_opr_switch_statements
-               #undef case_stmt
-               default : return error_node();
-            }
-         }
-
-         inline expression_node_ptr synthesize_sos_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
-         {
-            std::string& s0 = static_cast<details::stringvar_node<Type>*>(branch[0])->ref();
-            std::string& s1 = static_cast<details::stringvar_node<Type>*>(branch[1])->ref();
-
-            return synthesize_sos_expression_impl<std::string&,std::string&>(opr,s0,s1);
-         }
-
-         inline expression_node_ptr synthesize_sros_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
-         {
-            std::string&  s0 = static_cast<details::string_range_node<Type>*>(branch[0])->ref  ();
-            std::string&  s1 = static_cast<details::stringvar_node<Type>*>   (branch[1])->ref  ();
-            range_t      rp0 = static_cast<details::string_range_node<Type>*>(branch[0])->range();
-
-            static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear();
-
-            free_node(*node_allocator_,branch[0]);
-
-            return synthesize_str_xrox_expression_impl<std::string&,std::string&>(opr,s0,s1,rp0);
-         }
-
-         inline expression_node_ptr synthesize_sosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
-         {
-            std::string&  s0 = static_cast<details::stringvar_node<Type>*>   (branch[0])->ref  ();
-            std::string&  s1 = static_cast<details::string_range_node<Type>*>(branch[1])->ref  ();
-            range_t      rp1 = static_cast<details::string_range_node<Type>*>(branch[1])->range();
-
-            static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear();
-
-            free_node(*node_allocator_,branch[1]);
-
-            return synthesize_str_xoxr_expression_impl<std::string&,std::string&>(opr,s0,s1,rp1);
-         }
-
-         inline expression_node_ptr synthesize_socsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
-         {
-            std::string&  s0 = static_cast<details::stringvar_node<Type>*>         (branch[0])->ref  ();
-            std::string   s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str  ();
-            range_t      rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range();
-
-            static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear();
-
-            free_node(*node_allocator_,branch[1]);
-
-            return synthesize_str_xoxr_expression_impl<std::string&,const std::string>(opr,s0,s1,rp1);
-         }
-
-         inline expression_node_ptr synthesize_srosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
-         {
-            std::string&  s0 = static_cast<details::string_range_node<Type>*>(branch[0])->ref  ();
-            std::string&  s1 = static_cast<details::string_range_node<Type>*>(branch[1])->ref  ();
-            range_t      rp0 = static_cast<details::string_range_node<Type>*>(branch[0])->range();
-            range_t      rp1 = static_cast<details::string_range_node<Type>*>(branch[1])->range();
-
-            static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear();
-            static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear();
-
-            details::free_node(*node_allocator_,branch[0]);
-            details::free_node(*node_allocator_,branch[1]);
-
-            return synthesize_str_xroxr_expression_impl<std::string&,std::string&>(opr,s0,s1,rp0,rp1);
-         }
-
-         inline expression_node_ptr synthesize_socs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
-         {
-            std::string& s0 = static_cast<     details::stringvar_node<Type>*>(branch[0])->ref();
-            std::string  s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str();
-
-            details::free_node(*node_allocator_,branch[1]);
-
-            return synthesize_sos_expression_impl<std::string&,const std::string>(opr,s0,s1);
-         }
-
-         inline expression_node_ptr synthesize_csos_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
-         {
-            std::string  s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
-            std::string& s1 = static_cast<     details::stringvar_node<Type>*>(branch[1])->ref();
-
-            details::free_node(*node_allocator_,branch[0]);
-
-            return synthesize_sos_expression_impl<const std::string,std::string&>(opr,s0,s1);
-         }
-
-         inline expression_node_ptr synthesize_csosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
-         {
-            std::string   s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str  ();
-            std::string&  s1 = static_cast<details::string_range_node<Type>*>  (branch[1])->ref  ();
-            range_t      rp1 = static_cast<details::string_range_node<Type>*>  (branch[1])->range();
-
-            static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear();
-
-            details::free_node(*node_allocator_,branch[0]);
-            details::free_node(*node_allocator_,branch[1]);
-
-            return synthesize_str_xoxr_expression_impl<const std::string,std::string&>(opr,s0,s1,rp1);
-         }
-
-         inline expression_node_ptr synthesize_srocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
-         {
-            std::string&  s0 = static_cast<details::string_range_node<Type>*>  (branch[0])->ref  ();
-            std::string   s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str  ();
-            range_t      rp0 = static_cast<details::string_range_node<Type>*>  (branch[0])->range();
-
-            static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear();
-
-            details::free_node(*node_allocator_,branch[0]);
-            details::free_node(*node_allocator_,branch[1]);
-
-            return synthesize_str_xrox_expression_impl<std::string&,const std::string>(opr,s0,s1,rp0);
-         }
-
-         inline expression_node_ptr synthesize_srocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
-         {
-            std::string&  s0 = static_cast<details::string_range_node<Type>*>      (branch[0])->ref  ();
-            std::string   s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str  ();
-            range_t      rp0 = static_cast<details::string_range_node<Type>*>      (branch[0])->range();
-            range_t      rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range();
-
-            static_cast<details::string_range_node<Type>*>      (branch[0])->range_ref().clear();
-            static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear();
-
-            details::free_node(*node_allocator_,branch[0]);
-            details::free_node(*node_allocator_,branch[1]);
-
-            return synthesize_str_xroxr_expression_impl<std::string&,const std::string>(opr,s0,s1,rp0,rp1);
-         }
-
-         inline expression_node_ptr synthesize_csocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
-         {
-            const std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
-            const std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str();
-
-            expression_node_ptr result = error_node();
-
-            if (details::e_add == opr)
-               result = node_allocator_->allocate_c<details::string_literal_node<Type> >(s0 + s1);
-            else if (details::e_in == opr)
-               result = node_allocator_->allocate_c<details::literal_node<Type> >(details::in_op<Type>::process(s0,s1));
-            else if (details::e_like == opr)
-               result = node_allocator_->allocate_c<details::literal_node<Type> >(details::like_op<Type>::process(s0,s1));
-            else if (details::e_ilike == opr)
-               result = node_allocator_->allocate_c<details::literal_node<Type> >(details::ilike_op<Type>::process(s0,s1));
-            else
-            {
-               expression_node_ptr temp = synthesize_sos_expression_impl<const std::string,const std::string>(opr,s0,s1);
-               Type v = temp->value();
-               details::free_node(*node_allocator_,temp);
-               result = node_allocator_->allocate<literal_node_t>(v);
-            }
-
-            details::free_all_nodes(*node_allocator_,branch);
-
-            return result;
-         }
-
-         inline expression_node_ptr synthesize_csocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
-         {
-            const std::string s0 = static_cast<details::string_literal_node<Type>*>    (branch[0])->str  ();
-                  std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str  ();
-            range_t          rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range();
-
-            static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear();
-
-            free_node(*node_allocator_,branch[0]);
-            free_node(*node_allocator_,branch[1]);
-
-            return synthesize_str_xoxr_expression_impl<const std::string,const std::string>(opr,s0,s1,rp1);
-         }
-
-         inline expression_node_ptr synthesize_csros_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::stringvar_node<Type>*>         (branch[1])->ref  ();
-            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();
-
-            free_node(*node_allocator_,branch[0]);
-
-            return synthesize_str_xrox_expression_impl<const std::string,std::string&>(opr,s0,s1,rp0);
-         }
-
-         inline expression_node_ptr synthesize_csrosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
-         {
-            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();
-
-            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();
-
-            free_node(*node_allocator_,branch[0]);
-            free_node(*node_allocator_,branch[1]);
-
-            return synthesize_str_xroxr_expression_impl<const std::string,std::string&>(opr,s0,s1,rp0,rp1);
-         }
-
-         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 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();
-
-            static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear();
-
-            details::free_all_nodes(*node_allocator_,branch);
-
-            return synthesize_str_xrox_expression_impl<const std::string,std::string>(opr,s0,s1,rp0);
-         }
-
-         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();
-
-            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();
-
-            details::free_all_nodes(*node_allocator_,branch);
-
-            return synthesize_str_xroxr_expression_impl<const std::string,const std::string>(opr,s0,s1,rp0,rp1);
-         }
-
-         inline expression_node_ptr synthesize_strogen_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
-         {
-            switch (opr)
-            {
-               #define case_stmt(op0,op1)                                                       \
-               case op0 : return node_allocator_->                                              \
-                             allocate_ttt<typename details::str_sogens_node<Type,op1<Type> > >  \
-                                (opr,branch[0],branch[1]);                                      \
-
-               string_opr_switch_statements
-               #undef case_stmt
-               default : return error_node();
-            }
-         }
-         #endif
-
-         #ifndef exprtk_disable_string_capabilities
-         inline expression_node_ptr synthesize_string_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
-         {
-            if ((0 == branch[0]) || (0 == branch[1]))
-            {
-               details::free_all_nodes(*node_allocator_,branch);
-
-               return error_node();
-            }
-
-            const bool b0_is_s   = details::is_string_node            (branch[0]);
-            const bool b0_is_cs  = details::is_const_string_node      (branch[0]);
-            const bool b0_is_sr  = details::is_string_range_node      (branch[0]);
-            const bool b0_is_csr = details::is_const_string_range_node(branch[0]);
-            const bool b1_is_s   = details::is_string_node            (branch[1]);
-            const bool b1_is_cs  = details::is_const_string_node      (branch[1]);
-            const bool b1_is_sr  = details::is_string_range_node      (branch[1]);
-            const bool b1_is_csr = details::is_const_string_range_node(branch[1]);
-
-            const bool b0_is_gen = details::is_string_assignment_node (branch[0]) ||
-                                   details::is_genricstring_range_node(branch[0]) ||
-                                   details::is_string_concat_node     (branch[0]) ||
-                                   details::is_string_function_node   (branch[0]) ;
-
-            const bool b1_is_gen = details::is_string_assignment_node (branch[1]) ||
-                                   details::is_genricstring_range_node(branch[1]) ||
-                                   details::is_string_concat_node     (branch[1]) ||
-                                   details::is_string_function_node   (branch[1]) ;
-
-            if (details::e_add == opr)
-            {
-               if (!b0_is_cs || !b1_is_cs)
-               {
-                  return synthesize_expression<string_concat_node_t,2>(opr,branch);
-               }
-            }
-
-            if (b0_is_gen || b1_is_gen)
-            {
-               return synthesize_strogen_expression(opr,branch);
-            }
-            else if (b0_is_s)
-            {
-                    if (b1_is_s  ) return synthesize_sos_expression   (opr,branch);
-               else if (b1_is_cs ) return synthesize_socs_expression  (opr,branch);
-               else if (b1_is_sr ) return synthesize_sosr_expression  (opr,branch);
-               else if (b1_is_csr) return synthesize_socsr_expression (opr,branch);
-            }
-            else if (b0_is_cs)
-            {
-                    if (b1_is_s  ) return synthesize_csos_expression  (opr,branch);
-               else if (b1_is_cs ) return synthesize_csocs_expression (opr,branch);
-               else if (b1_is_sr ) return synthesize_csosr_expression (opr,branch);
-               else if (b1_is_csr) return synthesize_csocsr_expression(opr,branch);
-            }
-            else if (b0_is_sr)
-            {
-                    if (b1_is_s  ) return synthesize_sros_expression  (opr,branch);
-               else if (b1_is_sr ) return synthesize_srosr_expression (opr,branch);
-               else if (b1_is_cs ) return synthesize_srocs_expression (opr,branch);
-               else if (b1_is_csr) return synthesize_srocsr_expression(opr,branch);
-            }
-            else if (b0_is_csr)
-            {
-                    if (b1_is_s  ) return synthesize_csros_expression  (opr,branch);
-               else if (b1_is_sr ) return synthesize_csrosr_expression (opr,branch);
-               else if (b1_is_cs ) return synthesize_csrocs_expression (opr,branch);
-               else if (b1_is_csr) return synthesize_csrocsr_expression(opr,branch);
-            }
-
-            return error_node();
-         }
-         #else
-         inline expression_node_ptr synthesize_string_expression(const details::operator_type&, expression_node_ptr (&branch)[2])
-         {
-            details::free_all_nodes(*node_allocator_,branch);
-            return error_node();
-         }
-         #endif
-
-         #ifndef exprtk_disable_string_capabilities
-         inline expression_node_ptr synthesize_string_expression(const details::operator_type& opr, expression_node_ptr (&branch)[3])
-         {
-            if (details::e_inrange != opr)
-               return error_node();
-            else if ((0 == branch[0]) || (0 == branch[1]) || (0 == branch[2]))
-            {
-               details::free_all_nodes(*node_allocator_,branch);
-
-               return error_node();
-            }
-            else if (
-                      details::is_const_string_node(branch[0]) &&
-                      details::is_const_string_node(branch[1]) &&
-                      details::is_const_string_node(branch[2])
-                    )
-            {
-               const std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
-               const std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str();
-               const std::string s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str();
-
-               Type v = (((s0 <= s1) && (s1 <= s2)) ? Type(1) : Type(0));
-               details::free_all_nodes(*node_allocator_,branch);
-
-               return node_allocator_->allocate_c<details::literal_node<Type> >(v);
-            }
-            else if (
-                      details::is_string_node(branch[0]) &&
-                      details::is_string_node(branch[1]) &&
-                      details::is_string_node(branch[2])
-                    )
-            {
-               std::string& s0 = static_cast<details::stringvar_node<Type>*>(branch[0])->ref();
-               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;
-
-               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]) &&
-                            details::is_string_node(branch[1]) &&
-                      details::is_const_string_node(branch[2])
-                    )
-            {
-               std::string  s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
-               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;
-
-               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);
-            }
-            else if (
-                            details::is_string_node(branch[0]) &&
-                      details::is_const_string_node(branch[1]) &&
-                            details::is_string_node(branch[2])
-                    )
-            {
-               std::string&  s0 = static_cast<     details::stringvar_node<Type>*>(branch[0])->ref();
-               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;
-
-               details::free_node(*node_allocator_,branch[1]);
-
-               return node_allocator_->allocate_type<inrange_t,std::string&,std::string,std::string&>(s0,s1,s2);
-            }
-            else if (
-                      details::is_string_node(branch[0]) &&
-                      details::is_string_node(branch[1]) &&
-                      details::is_const_string_node(branch[2])
-                    )
-            {
-               std::string& s0 = static_cast<     details::stringvar_node<Type>*>(branch[0])->ref();
-               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;
-
-               details::free_node(*node_allocator_,branch[2]);
-
-               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]) &&
-                      details::      is_string_node(branch[1]) &&
-                      details::      is_string_node(branch[2])
-                    )
-            {
-               std::string  s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
-               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;
-
-               details::free_node(*node_allocator_,branch[0]);
-
-               return node_allocator_->allocate_type<inrange_t,std::string,std::string&,std::string&>(s0,s1,s2);
-            }
-            else
-               return error_node();
-         }
-         #else
-         inline expression_node_ptr synthesize_string_expression(const details::operator_type&, expression_node_ptr (&branch)[3])
-         {
-            details::free_all_nodes(*node_allocator_,branch);
-            return error_node();
-         }
-         #endif
-
-         inline expression_node_ptr synthesize_null_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
-         {
-            /*
-             Note: The following are the type promotion rules
-             that relate to operations that include 'null':
-             0. null ==/!=     null --> true false
-             1. null operation null --> null
-             2. x    ==/!=     null --> true/false
-             3. null ==/!=     x    --> true/false
-             4. x   operation  null --> x
-             5. null operation x    --> x
-            */
-
-            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]);
-
-            if (b0_null && b1_null)
-            {
-               expression_node_ptr result = error_node();
-
-               if (details::e_eq == operation)
-                  result = node_allocator_->allocate_c<literal_node_t>(T(1));
-               else if (details::e_ne == operation)
-                  result = node_allocator_->allocate_c<literal_node_t>(T(0));
-
-               if (result)
-               {
-                  details::free_node(*node_allocator_,branch[0]);
-                  details::free_node(*node_allocator_,branch[1]);
-
-                  return result;
-               }
-
-               details::free_node(*node_allocator_,branch[1]);
-
-               return branch[0];
-            }
-            else if (details::e_eq == operation)
-            {
-               expression_node_ptr result = node_allocator_->
-                                                allocate_rc<nulleq_node_t>(branch[b0_null ? 0 : 1],true);
-
-               details::free_node(*node_allocator_,branch[b0_null ? 1 : 0]);
-
-               return result;
-            }
-            else if (details::e_ne == operation)
-            {
-               expression_node_ptr result = node_allocator_->
-                                                allocate_rc<nulleq_node_t>(branch[b0_null ? 0 : 1],false);
-
-               details::free_node(*node_allocator_,branch[b0_null ? 1 : 0]);
-
-               return result;
-            }
-            else if (b0_null)
-            {
-               details::free_node(*node_allocator_,branch[0]);
-               branch[0] = branch[1];
-               branch[1] = error_node();
-            }
-            else if (b1_null)
-            {
-               details::free_node(*node_allocator_,branch[1]);
-               branch[1] = error_node();
-            }
-
-            if (
-                 (details::e_add == operation) || (details::e_sub == operation) ||
-                 (details::e_mul == operation) || (details::e_div == operation) ||
-                 (details::e_mod == operation) || (details::e_pow == operation)
-               )
-            {
-               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)
-                    )
-            {
-               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> >();
-         }
-
-         template <typename NodeType, std::size_t N>
-         inline expression_node_ptr synthesize_expression(const details::operator_type& operation, expression_node_ptr (&branch)[N])
-         {
-            if (
-                 (details::e_in    == operation) ||
-                 (details::e_like  == operation) ||
-                 (details::e_ilike == operation)
-               )
-               return error_node();
-            else if (!details::all_nodes_valid<N>(branch))
-            {
-               free_all_nodes(*node_allocator_,branch);
-
-               return error_node();
-            }
-            else if ((details::e_default != operation))
-            {
-               // Attempt simple constant folding optimization.
-               expression_node_ptr expression_point = node_allocator_->allocate<NodeType>(operation,branch);
-
-               if (is_constant_foldable<N>(branch))
-               {
-                  Type v = expression_point->value();
-                  details::free_node(*node_allocator_,expression_point);
-
-                  return node_allocator_->allocate<literal_node_t>(v);
-               }
-               else
-                  return expression_point;
-            }
-            else
-               return error_node();
-         }
-
-         template <typename NodeType, std::size_t N>
-         inline expression_node_ptr synthesize_expression(F* f, expression_node_ptr (&branch)[N])
-         {
-            if (!details::all_nodes_valid<N>(branch))
-            {
-               free_all_nodes(*node_allocator_,branch);
-
-               return error_node();
-            }
-
-            typedef typename details::function_N_node<T,ifunction_t,N> function_N_node_t;
-
-            // Attempt simple constant folding optimization.
-
-            expression_node_ptr expression_point = node_allocator_->allocate<NodeType>(f);
-            function_N_node_t* func_node_ptr = dynamic_cast<function_N_node_t*>(expression_point);
-
-            if (0 == func_node_ptr)
-            {
-               free_all_nodes(*node_allocator_,branch);
-
-               return error_node();
-            }
-            else
-               func_node_ptr->init_branches(branch);
-
-            if (is_constant_foldable<N>(branch) && !f->has_side_effects)
-            {
-               Type v = expression_point->value();
-               details::free_node(*node_allocator_,expression_point);
-
-               return node_allocator_->allocate<literal_node_t>(v);
-            }
-            else
-               return expression_point;
-         }
-
-         bool strength_reduction_enabled_;
-         details::node_allocator* node_allocator_;
-         synthesize_map_t synthesize_map_;
-         unary_op_map_t* unary_op_map_;
-         binary_op_map_t* binary_op_map_;
-         inv_binary_op_map_t* inv_binary_op_map_;
-         sf3_map_t* sf3_map_;
-         sf4_map_t* sf4_map_;
-         parser_t* parser_;
-      };
-
-      inline void set_error(const parser_error::type& error_type)
-      {
-         error_list_.push_back(error_type);
-      }
-
-      inline void remove_last_error()
-      {
-         if (!error_list_.empty())
-         {
-            error_list_.pop_back();
-         }
-      }
-
-      inline void set_synthesis_error(const std::string& synthesis_error_message)
-      {
-         if (synthesis_error_.empty())
-         {
-            synthesis_error_ = synthesis_error_message;
-         }
-      }
-
-      inline void register_local_vars(expression<T>& e)
-      {
-         for (std::size_t i = 0; i < sem_.size(); ++i)
-         {
-            scope_element& se = sem_.get_element(i);
-
-            if (
-                 (scope_element::e_variable == se.type) ||
-                 (scope_element::e_vecelem  == se.type)
-               )
-            {
-               if (se.var_node)
-               {
-                  e.register_local_var(se.var_node);
-               }
-
-               if (se.data)
-               {
-                  e.register_local_data(se.data,1);
-               }
-            }
-            else if (scope_element::e_vector == se.type)
-            {
-               if (se.vec_node)
-               {
-                  e.register_local_var (se.vec_node);
-               }
-
-               if (se.data)
-               {
-                  e.register_local_data(se.data,se.size,true);
-               }
-            }
-
-            se.var_node  = 0;
-            se.vec_node  = 0;
-            se.data      = 0;
-            se.ref_count = 0;
-            se.active    = false;
-         }
-      }
-
-      inline void load_unary_operations_map(unary_op_map_t& m)
-      {
-         #define register_unary_op(Op,UnaryFunctor)             \
-         m.insert(std::make_pair(Op,UnaryFunctor<T>::process)); \
-
-         register_unary_op(details::  e_abs,details::  abs_op)
-         register_unary_op(details:: e_acos,details:: acos_op)
-         register_unary_op(details::e_acosh,details::acosh_op)
-         register_unary_op(details:: e_asin,details:: asin_op)
-         register_unary_op(details::e_asinh,details::asinh_op)
-         register_unary_op(details::e_atanh,details::atanh_op)
-         register_unary_op(details:: e_ceil,details:: ceil_op)
-         register_unary_op(details::  e_cos,details::  cos_op)
-         register_unary_op(details:: e_cosh,details:: cosh_op)
-         register_unary_op(details::  e_exp,details::  exp_op)
-         register_unary_op(details::e_expm1,details::expm1_op)
-         register_unary_op(details::e_floor,details::floor_op)
-         register_unary_op(details::  e_log,details::  log_op)
-         register_unary_op(details::e_log10,details::log10_op)
-         register_unary_op(details:: e_log2,details:: log2_op)
-         register_unary_op(details::e_log1p,details::log1p_op)
-         register_unary_op(details::  e_neg,details::  neg_op)
-         register_unary_op(details::  e_pos,details::  pos_op)
-         register_unary_op(details::e_round,details::round_op)
-         register_unary_op(details::  e_sin,details::  sin_op)
-         register_unary_op(details:: e_sinc,details:: sinc_op)
-         register_unary_op(details:: e_sinh,details:: sinh_op)
-         register_unary_op(details:: e_sqrt,details:: sqrt_op)
-         register_unary_op(details::  e_tan,details::  tan_op)
-         register_unary_op(details:: e_tanh,details:: tanh_op)
-         register_unary_op(details::  e_cot,details::  cot_op)
-         register_unary_op(details::  e_sec,details::  sec_op)
-         register_unary_op(details::  e_csc,details::  csc_op)
-         register_unary_op(details::  e_r2d,details::  r2d_op)
-         register_unary_op(details::  e_d2r,details::  d2r_op)
-         register_unary_op(details::  e_d2g,details::  d2g_op)
-         register_unary_op(details::  e_g2d,details::  g2d_op)
-         register_unary_op(details:: e_notl,details:: notl_op)
-         register_unary_op(details::  e_sgn,details::  sgn_op)
-         register_unary_op(details::  e_erf,details::  erf_op)
-         register_unary_op(details:: e_erfc,details:: erfc_op)
-         register_unary_op(details:: e_ncdf,details:: ncdf_op)
-         register_unary_op(details:: e_frac,details:: frac_op)
-         register_unary_op(details::e_trunc,details::trunc_op)
-         #undef register_unary_op
-      }
-
-      inline void load_binary_operations_map(binary_op_map_t& m)
-      {
-         typedef typename binary_op_map_t::value_type value_type;
-
-         #define register_binary_op(Op,BinaryFunctor)        \
-         m.insert(value_type(Op,BinaryFunctor<T>::process)); \
-
-         register_binary_op(details:: e_add,details:: add_op)
-         register_binary_op(details:: e_sub,details:: sub_op)
-         register_binary_op(details:: e_mul,details:: mul_op)
-         register_binary_op(details:: e_div,details:: div_op)
-         register_binary_op(details:: e_mod,details:: mod_op)
-         register_binary_op(details:: e_pow,details:: pow_op)
-         register_binary_op(details::  e_lt,details::  lt_op)
-         register_binary_op(details:: e_lte,details:: lte_op)
-         register_binary_op(details::  e_gt,details::  gt_op)
-         register_binary_op(details:: e_gte,details:: gte_op)
-         register_binary_op(details::  e_eq,details::  eq_op)
-         register_binary_op(details::  e_ne,details::  ne_op)
-         register_binary_op(details:: e_and,details:: and_op)
-         register_binary_op(details::e_nand,details::nand_op)
-         register_binary_op(details::  e_or,details::  or_op)
-         register_binary_op(details:: e_nor,details:: nor_op)
-         register_binary_op(details:: e_xor,details:: xor_op)
-         register_binary_op(details::e_xnor,details::xnor_op)
-         #undef register_binary_op
-      }
-
-      inline void load_inv_binary_operations_map(inv_binary_op_map_t& m)
-      {
-         typedef typename inv_binary_op_map_t::value_type value_type;
-
-         #define register_binary_op(Op,BinaryFunctor)        \
-         m.insert(value_type(BinaryFunctor<T>::process,Op)); \
-
-         register_binary_op(details:: e_add,details:: add_op)
-         register_binary_op(details:: e_sub,details:: sub_op)
-         register_binary_op(details:: e_mul,details:: mul_op)
-         register_binary_op(details:: e_div,details:: div_op)
-         register_binary_op(details:: e_mod,details:: mod_op)
-         register_binary_op(details:: e_pow,details:: pow_op)
-         register_binary_op(details::  e_lt,details::  lt_op)
-         register_binary_op(details:: e_lte,details:: lte_op)
-         register_binary_op(details::  e_gt,details::  gt_op)
-         register_binary_op(details:: e_gte,details:: gte_op)
-         register_binary_op(details::  e_eq,details::  eq_op)
-         register_binary_op(details::  e_ne,details::  ne_op)
-         register_binary_op(details:: e_and,details:: and_op)
-         register_binary_op(details::e_nand,details::nand_op)
-         register_binary_op(details::  e_or,details::  or_op)
-         register_binary_op(details:: e_nor,details:: nor_op)
-         register_binary_op(details:: e_xor,details:: xor_op)
-         register_binary_op(details::e_xnor,details::xnor_op)
-         #undef register_binary_op
-      }
-
-      inline void load_sf3_map(sf3_map_t& sf3_map)
-      {
-         typedef std::pair<trinary_functor_t,details::operator_type> pair_t;
-
-         #define register_sf3(Op)                                                                             \
-         sf3_map[details::sf##Op##_op<T>::id()] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \
-
-         register_sf3(00) register_sf3(01) register_sf3(02) register_sf3(03)
-         register_sf3(04) register_sf3(05) register_sf3(06) register_sf3(07)
-         register_sf3(08) register_sf3(09) register_sf3(10) register_sf3(11)
-         register_sf3(12) register_sf3(13) register_sf3(14) register_sf3(15)
-         register_sf3(16) register_sf3(17) register_sf3(18) register_sf3(19)
-         register_sf3(20) register_sf3(21) register_sf3(22) register_sf3(23)
-         register_sf3(24) register_sf3(25) register_sf3(26) register_sf3(27)
-         register_sf3(28) register_sf3(29) register_sf3(30)
-         #undef register_sf3
-      }
-
-      inline void load_sf4_map(sf4_map_t& sf4_map)
-      {
-         typedef std::pair<quaternary_functor_t,details::operator_type> pair_t;
-
-         #define register_sf4(Op)                                                                             \
-         sf4_map[details::sf##Op##_op<T>::id()] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \
-
-         register_sf4(48) register_sf4(49) register_sf4(50) register_sf4(51)
-         register_sf4(52) register_sf4(53) register_sf4(54) register_sf4(55)
-         register_sf4(56) register_sf4(57) register_sf4(58) register_sf4(59)
-         register_sf4(60) register_sf4(61) register_sf4(62) register_sf4(63)
-         register_sf4(64) register_sf4(65) register_sf4(66) register_sf4(67)
-         register_sf4(68) register_sf4(69) register_sf4(70) register_sf4(71)
-         register_sf4(72) register_sf4(73) register_sf4(74) register_sf4(75)
-         register_sf4(76) register_sf4(77) register_sf4(78) register_sf4(79)
-         register_sf4(80) register_sf4(81) register_sf4(82) register_sf4(83)
-         #undef register_sf4
-
-         #define register_sf4ext(Op)                                                                                    \
-         sf4_map[details::sfext##Op##_op<T>::id()] = pair_t(details::sfext##Op##_op<T>::process,details::e_sf4ext##Op); \
-
-         register_sf4ext(00) register_sf4ext(01) register_sf4ext(02) register_sf4ext(03)
-         register_sf4ext(04) register_sf4ext(05) register_sf4ext(06) register_sf4ext(07)
-         register_sf4ext(08) register_sf4ext(09) register_sf4ext(10) register_sf4ext(11)
-         register_sf4ext(12) register_sf4ext(13) register_sf4ext(14) register_sf4ext(15)
-         register_sf4ext(16) register_sf4ext(17) register_sf4ext(18) register_sf4ext(19)
-         register_sf4ext(20) register_sf4ext(21) register_sf4ext(22) register_sf4ext(23)
-         register_sf4ext(24) register_sf4ext(25) register_sf4ext(26) register_sf4ext(27)
-         register_sf4ext(28) register_sf4ext(29) register_sf4ext(30) register_sf4ext(31)
-         register_sf4ext(32) register_sf4ext(33) register_sf4ext(34) register_sf4ext(35)
-         register_sf4ext(36) register_sf4ext(36) register_sf4ext(38) register_sf4ext(39)
-         register_sf4ext(40) register_sf4ext(41) register_sf4ext(42) register_sf4ext(43)
-         register_sf4ext(44) register_sf4ext(45) register_sf4ext(46) register_sf4ext(47)
-         register_sf4ext(48) register_sf4ext(49) register_sf4ext(50) register_sf4ext(51)
-         register_sf4ext(52) register_sf4ext(53) register_sf4ext(54) register_sf4ext(55)
-         register_sf4ext(56) register_sf4ext(57) register_sf4ext(58) register_sf4ext(59)
-         #undef register_sf4ext
-      }
-
-   private:
-
-      parser(const parser<T>&);
-      parser<T>& operator=(const parser<T>&);
-
-      lexer::generator lexer_;
-      lexer::token current_token_;
-      lexer::token store_current_token_;
-      expression_generator<T> expression_generator_;
-      details::node_allocator node_allocator_;
-      symbol_table_t symbol_table_;
-      dependent_entity_collector dec_;
-      std::size_t compile_options_;
-      std::deque<parser_error::type> error_list_;
-      std::deque<bool> brkcnt_list_;
-      bool resolve_unknown_symbol_;
-      bool vardef_disabled_;
-      std::size_t scope_depth_;
-      unknown_symbol_resolver* unknown_symbol_resolver_;
-      unknown_symbol_resolver default_usr_;
-      base_ops_map_t base_ops_map_;
-      unary_op_map_t unary_op_map_;
-      binary_op_map_t binary_op_map_;
-      inv_binary_op_map_t inv_binary_op_map_;
-      sf3_map_t sf3_map_;
-      sf4_map_t sf4_map_;
-      std::string synthesis_error_;
-      scope_element_manager sem_;
-
-      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_;
-   };
-
-   template <typename T>
-   inline T integrate(expression<T>& e,
-                      T& x,
-                      const T& r0, const T& r1,
-                      const std::size_t number_of_intervals = 1000000)
-   {
-      if (r0 > r1)
-         return T(0);
-
-      T h = (r1 - r0) / (T(2) * number_of_intervals);
-      T total_area = T(0);
-
-      for (std::size_t i = 0; i < number_of_intervals; ++i)
-      {
-         x = r0 + T(2) * i * h;
-         T y0 = e.value(); x += h;
-         T y1 = e.value(); x += h;
-         T y2 = e.value(); x += h;
-         total_area += h * (y0 + T(4) * y1 + y2) / T(3);
-      }
-
-      return total_area;
-   }
-
-   template <typename T>
-   inline T integrate(expression<T>& e,
-                      const std::string& variable_name,
-                      const T& r0, const T& r1,
-                      const std::size_t number_of_intervals = 1000000)
-   {
-      symbol_table<T>& sym_table = e.get_symbol_table();
-
-      if (!sym_table.valid())
-         return std::numeric_limits<T>::quiet_NaN();
-
-      details::variable_node<T>* var = sym_table.get_variable(variable_name);
-
-      if (var)
-      {
-         T& x = var->ref();
-         T  x_original = x;
-         T result = integrate(e,x,r0,r1,number_of_intervals);
-         x = x_original;
-
-         return result;
-      }
-      else
-         return std::numeric_limits<T>::quiet_NaN();
-   }
-
-   template <typename T>
-   inline T derivative(expression<T>& e,
-                       T& x,
-                       const T& h = T(0.00000001))
-   {
-      T x_init = x;
-      x = x_init + T(2) * h;
-      T y0 = e.value();
-      x = x_init + h;
-      T y1 = e.value();
-      x = x_init - h;
-      T y2 = e.value();
-      x = x_init - T(2) * h;
-      T y3 = e.value();
-      x = x_init;
-
-      return (-y0 + T(8) * (y1 - y2) + y3) / (T(12) * h);
-   }
-
-   template <typename T>
-   inline T second_derivative(expression<T>& e,
-                              T& x,
-                              const T& h = T(0.00001))
-   {
-      T y = e.value();
-      T x_init = x;
-      x = x_init + T(2) * h;
-      T y0 = e.value();
-      x = x_init + h;
-      T y1 = e.value();
-      x = x_init - h;
-      T y2 = e.value();
-      x = x_init - T(2) * h;
-      T y3 = e.value();
-      x = x_init;
-
-      return (-y0 + T(16) * (y1 + y2) - T(30) * y - y3) / (T(12) * h * h);
-   }
-
-   template <typename T>
-   inline T third_derivative(expression<T>& e,
-                             T& x,
-                             const T& h = T(0.0001))
-   {
-      T x_init = x;
-      x = x_init + T(2) * h;
-      T y0 = e.value();
-      x = x_init + h;
-      T y1 = e.value();
-      x = x_init - h;
-      T y2 = e.value();
-      x = x_init - T(2) * h;
-      T y3 = e.value();
-      x = x_init;
-
-      return (y0 + T(2) * (y2 - y1) - y3) / (T(2) * h * h * h);
-   }
-
-   template <typename T>
-   inline T derivative(expression<T>& e,
-                       const std::string& variable_name,
-                       const T& h = T(0.00000001))
-   {
-      symbol_table<T>& sym_table = e.get_symbol_table();
-
-      if (!sym_table.valid())
-      {
-         return std::numeric_limits<T>::quiet_NaN();
-      }
-
-      details::variable_node<T>* var = sym_table.get_variable(variable_name);
-
-      if (var)
-      {
-         T& x = var->ref();
-         T x_original = x;
-         T result = derivative(e,x,h);
-         x = x_original;
-
-         return result;
-      }
-      else
-         return std::numeric_limits<T>::quiet_NaN();
-   }
-
-   template <typename T>
-   inline T second_derivative(expression<T>& e,
-                              const std::string& variable_name,
-                              const T& h = T(0.00001))
-   {
-      symbol_table<T>& sym_table = e.get_symbol_table();
-
-      if (!sym_table.valid())
-      {
-         return std::numeric_limits<T>::quiet_NaN();
-      }
-
-      details::variable_node<T>* var = sym_table.get_variable(variable_name);
-
-      if (var)
-      {
-         T& x = var->ref();
-         T x_original = x;
-         T result = second_derivative(e,x,h);
-         x = x_original;
-
-         return result;
-      }
-      else
-         return std::numeric_limits<T>::quiet_NaN();
-   }
-
-   template <typename T>
-   inline T third_derivative(expression<T>& e,
-                             const std::string& variable_name,
-                             const T& h = T(0.0001))
-   {
-      symbol_table<T>& sym_table = e.get_symbol_table();
-
-      if (!sym_table.valid())
-      {
-         return std::numeric_limits<T>::quiet_NaN();
-      }
-
-      details::variable_node<T>* var = sym_table.get_variable(variable_name);
-
-      if (var)
-      {
-         T& x = var->ref();
-         T x_original = x;
-         T result = third_derivative(e,x,h);
-         x = x_original;
-
-         return result;
-      }
-      else
-         return std::numeric_limits<T>::quiet_NaN();
-   }
-
-   /*
-      Note: The following 'compute' routines are simple helpers,
-      for quickly setting up the required pieces of code in order
-      to evaluate an expression. By virtue of how they operate
-      there will be an overhead with regards to their setup and
-      teardown and hence should not be used in time critical
-      sections of code.
-      Furthermore they only assume a small sub set of variables - no
-      string variables or user defined functions.
-   */
-   template <typename T>
-   inline bool compute(const std::string& expression_string, T& result)
-   {
-      // No variables
-      symbol_table<T> symbol_table;
-      symbol_table.add_constants();
-
-      expression<T> expression;
-      parser<T> parser;
-
-      if (parser.compile(expression_string,expression))
-      {
-         result = expression.value();
-
-         return true;
-      }
-      else
-         return false;
-   }
-
-   template <typename T>
-   inline bool compute(const std::string& expression_string,
-                       const T& x,
-                       T& result)
-   {
-      // Only 'x'
-      static const std::string x_var("x");
-
-      symbol_table<T> symbol_table;
-      symbol_table.add_constants();
-      symbol_table.add_variable(x_var,x);
-
-      expression<T> expression;
-      parser<T> parser;
-
-      if (parser.compile(expression_string,expression))
-      {
-         result = expression.value();
-
-         return true;
-      }
-      else
-         return false;
-   }
-
-   template <typename T>
-   inline bool compute(const std::string& expression_string,
-                       const T&x, const T& y,
-                       T& result)
-   {
-      // Only 'x' and 'y'
-      static const std::string x_var("x");
-      static const std::string y_var("y");
-
-      symbol_table<T> symbol_table;
-      symbol_table.add_constants();
-      symbol_table.add_variable(x_var,x);
-      symbol_table.add_variable(y_var,y);
-
-      expression<T> expression;
-      parser<T> parser;
-
-      if (parser.compile(expression_string,expression))
-      {
-         result = expression.value();
-
-         return true;
-      }
-      else
-         return false;
-   }
-
-   template <typename T>
-   inline bool compute(const std::string& expression_string,
-                       const T& x, const T& y, const T& z,
-                       T& result)
-   {
-      // Only 'x', 'y' or 'z'
-      static const std::string x_var("x");
-      static const std::string y_var("y");
-      static const std::string z_var("z");
-
-      symbol_table<T> symbol_table;
-      symbol_table.add_constants();
-      symbol_table.add_variable(x_var,x);
-      symbol_table.add_variable(y_var,y);
-      symbol_table.add_variable(z_var,z);
-
-      expression<T> expression;
-      parser<T> parser;
-
-      if (parser.compile(expression_string,expression))
-      {
-         result = expression.value();
-
-         return true;
-      }
-      else
-         return false;
-   }
-
-   template <typename T, std::size_t N>
-   class polynomial : public ifunction<T>
-   {
-   private:
-
-      template <typename Type, std::size_t NumberOfCoefficients>
-      struct poly_impl { };
-
-      template <typename Type>
-      struct poly_impl <Type,12>
-      {
-         static inline T evaluate(const Type x,
-                                  const Type c12, const Type c11, const Type c10, const Type c9, const Type c8,
-                                  const Type  c7, const Type  c6, const Type  c5, const Type c4, const Type c3,
-                                  const Type  c2, const Type  c1, const Type  c0)
-         {
-            // p(x) = c_12x^12 + c_11x^11 + c_10x^10 + c_9x^9 + c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
-            return ((((((((((((c12 * x + c11) * x + c10) * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
-         }
-      };
-
-      template <typename Type>
-      struct poly_impl <Type,11>
-      {
-         static inline T evaluate(const Type x,
-                                  const Type c11, const Type c10, const Type c9, const Type c8, const Type c7,
-                                  const Type c6,  const Type  c5, const Type c4, const Type c3, const Type c2,
-                                  const Type c1,  const Type  c0)
-         {
-            // p(x) = c_11x^11 + c_10x^10 + c_9x^9 + c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
-            return (((((((((((c11 * x + c10) * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
-         }
-      };
-
-      template <typename Type>
-      struct poly_impl <Type,10>
-      {
-         static inline T evaluate(const Type x,
-                                  const Type c10, const Type c9, const Type c8, const Type c7, const Type c6,
-                                  const Type c5,  const Type c4, const Type c3, const Type c2, const Type c1,
-                                  const Type c0)
-         {
-            // p(x) = c_10x^10 + c_9x^9 + c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
-            return ((((((((((c10 * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
-         }
-      };
-
-      template <typename Type>
-      struct poly_impl <Type,9>
-      {
-         static inline T evaluate(const Type x,
-                                  const Type c9, const Type c8, const Type c7, const Type c6, const Type c5,
-                                  const Type c4, const Type c3, const Type c2, const Type c1, const Type c0)
-         {
-            // p(x) = c_9x^9 + c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
-            return (((((((((c9 * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
-         }
-      };
-
-      template <typename Type>
-      struct poly_impl <Type,8>
-      {
-         static inline T evaluate(const Type x,
-                                  const Type c8, const Type c7, const Type c6, const Type c5, const Type c4,
-                                  const Type c3, const Type c2, const Type c1, const Type c0)
-         {
-            // p(x) = c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
-            return ((((((((c8 * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
-         }
-      };
-
-      template <typename Type>
-      struct poly_impl <Type,7>
-      {
-         static inline T evaluate(const Type x,
-                                  const Type c7, const Type c6, const Type c5, const Type c4, const Type c3,
-                                  const Type c2, const Type c1, const Type c0)
-         {
-            // p(x) = c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
-            return (((((((c7 * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
-         }
-      };
-
-      template <typename Type>
-      struct poly_impl <Type,6>
-      {
-         static inline T evaluate(const Type x,
-                                  const Type c6, const Type c5, const Type c4, const Type c3, const Type c2,
-                                  const Type c1, const Type c0)
-         {
-            // p(x) = c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
-            return ((((((c6 * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
-         }
-      };
-
-      template <typename Type>
-      struct poly_impl <Type,5>
-      {
-         static inline T evaluate(const Type x,
-                                  const Type c5, const Type c4, const Type c3, const Type c2,
-                                  const Type c1, const Type c0)
-         {
-            // p(x) = c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
-            return (((((c5 * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
-         }
-      };
-
-      template <typename Type>
-      struct poly_impl <Type,4>
-      {
-         static inline T evaluate(const Type x, const Type c4, const Type c3, const Type c2, const Type c1, const Type c0)
-         {
-            // p(x) = c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
-            return ((((c4 * x + c3) * x + c2) * x + c1) * x + c0);
-         }
-      };
-
-      template <typename Type>
-      struct poly_impl <Type,3>
-      {
-         static inline T evaluate(const Type x, const Type c3, const Type c2, const Type c1, const Type c0)
-         {
-            // p(x) = c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
-            return (((c3 * x + c2) * x + c1) * x + c0);
-         }
-      };
-
-      template <typename Type>
-      struct poly_impl <Type,2>
-      {
-         static inline T evaluate(const Type x, const Type c2, const Type c1, const Type c0)
-         {
-            // p(x) = c_2x^2 + c_1x^1 + c_0x^0
-            return ((c2 * x + c1) * x + c0);
-         }
-      };
-
-      template <typename Type>
-      struct poly_impl <Type,1>
-      {
-         static inline T evaluate(const Type x, const Type c1, const Type c0)
-         {
-            // p(x) = c_1x^1 + c_0x^0
-            return (c1 * x + c0);
-         }
-      };
-
-   public:
-
-      polynomial()
-      : exprtk::ifunction<T>((N+2 <= 20) ? (N + 2) : std::numeric_limits<std::size_t>::max(),false)
-      {}
-
-      inline virtual T operator()(const T& x, const T& c1, const T& c0)
-      {
-         return ((1 == N) ? poly_impl<T,1>::evaluate(x,c1,c0) : std::numeric_limits<T>::quiet_NaN());
-      }
-
-      inline virtual T operator()(const T& x, const T& c2, const T& c1, const T& c0)
-      {
-         return ((2 == N) ? poly_impl<T,2>::evaluate(x,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
-      }
-
-      inline virtual T operator()(const T& x, const T& c3, const T& c2, const T& c1, const T& c0)
-      {
-         return ((3 == N) ? poly_impl<T,3>::evaluate(x,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
-      }
-
-      inline virtual T operator()(const T& x, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
-      {
-         return ((4 == N) ? poly_impl<T,4>::evaluate(x,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
-      }
-
-      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)
-      {
-         return ((5 == N) ? poly_impl<T,5>::evaluate(x,c5,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
-      }
-
-      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)
-      {
-         return ((6 == N) ? poly_impl<T,6>::evaluate(x,c6,c5,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
-      }
-
-      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)
-      {
-         return ((7 == N) ? poly_impl<T,7>::evaluate(x,c7,c6,c5,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
-      }
-
-      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)
-      {
-         return ((8 == N) ? poly_impl<T,8>::evaluate(x,c8,c7,c6,c5,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
-      }
-
-      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)
-      {
-         return ((9 == N) ? poly_impl<T,9>::evaluate(x,c9,c8,c7,c6,c5,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
-      }
-
-      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)
-      {
-         return ((10 == N) ? poly_impl<T,10>::evaluate(x,c10,c9,c8,c7,c6,c5,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
-      }
-
-      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)
-      {
-         return ((11 == N) ? poly_impl<T,11>::evaluate(x,c11,c10,c9,c8,c7,c6,c5,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
-      }
-
-      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)
-      {
-         return ((12 == N) ? poly_impl<T,12>::evaluate(x,c12,c11,c10,c9,c8,c7,c6,c5,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
-      }
-
-      inline virtual T operator()()
-      {
-         return std::numeric_limits<T>::quiet_NaN();
-      }
-
-      inline virtual T operator()(const T&)
-      {
-         return std::numeric_limits<T>::quiet_NaN();
-      }
-
-      inline virtual T operator()(const T&, const T&)
-      {
-         return std::numeric_limits<T>::quiet_NaN();
-      }
-   };
-
-   template <typename T>
-   class function_compositor
-   {
-   public:
-
-      typedef exprtk::expression<T>   expression_t;
-      typedef exprtk::symbol_table<T> symbol_table_t;
-      typedef exprtk::parser<T>       parser_t;
-
-      struct function
-      {
-         function()
-         {}
-
-         function(const std::string& n)
-         : name_(n)
-         {}
-
-         inline function& name(const std::string& n)
-         {
-            name_ = n;
-            return (*this);
-         }
-
-         inline function& expression(const std::string& e)
-         {
-            expression_ = e;
-            return (*this);
-         }
-
-         inline function& var(const std::string& v)
-         {
-            v_.push_back(v);
-            return (*this);
-         }
-
-         std::string name_;
-         std::string expression_;
-         std::deque<std::string> v_;
-      };
-
-   private:
-
-      struct base_func : public exprtk::ifunction<T>
-      {
-         typedef const T& type;
-         typedef exprtk::ifunction<T> function_t;
-         typedef std::vector<T*> varref_t;
-         typedef std::vector<T> var_t;
-         typedef std::pair<T*,std::size_t> lvarref_t;
-         typedef std::vector<lvarref_t> lvr_vec_t;
-
-         base_func(const std::size_t& pc = 0)
-         : exprtk::ifunction<T>(pc),
-           local_var_stack_size(0),
-           stack_depth(0)
-         {
-            v.resize(pc);
-         }
-
-         virtual ~base_func()
-         {}
-
-         inline void update(const T& v0)
-         {
-            (*v[0]) = v0;
-         }
-
-         inline void update(const T& v0, const T& v1)
-         {
-            (*v[0]) = v0; (*v[1]) = v1;
-         }
-
-         inline void update(const T& v0, const T& v1, const T& v2)
-         {
-            (*v[0]) = v0; (*v[1]) = v1;
-            (*v[2]) = v2;
-         }
-
-         inline void update(const T& v0, const T& v1, const T& v2, const T& v3)
-         {
-            (*v[0]) = v0; (*v[1]) = v1;
-            (*v[2]) = v2; (*v[3]) = v3;
-         }
-
-         inline void update(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4)
-         {
-            (*v[0]) = v0; (*v[1]) = v1;
-            (*v[2]) = v2; (*v[3]) = v3;
-            (*v[4]) = v4;
-         }
-
-         inline void update(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5)
-         {
-            (*v[0]) = v0; (*v[1]) = v1;
-            (*v[2]) = v2; (*v[3]) = v3;
-            (*v[4]) = v4; (*v[5]) = v5;
-         }
-
-         inline function_t& setup(expression_t& expr)
-         {
-            expression = expr;
-
-            typedef typename expression_t::expression_holder::local_data_list_t ldl_t;
-            ldl_t ldl = expr.local_data_list();
-
-            std::vector<std::size_t> index_list;
-
-            for (std::size_t i = 0; i < ldl.size(); ++i)
-            {
-               if (ldl[i].size)
-               {
-                  index_list.push_back(i);
-               }
-            }
-
-            std::size_t input_param_count = 0;
-
-            for (std::size_t i = 0; i < index_list.size(); ++i)
-            {
-               const std::size_t index = index_list[i];
-
-               if (i < (index_list.size() - v.size()))
-               {
-                  lv.push_back(
-                        std::make_pair(
-                           reinterpret_cast<T*>(ldl[index].pointer),
-                           ldl[index].size));
-
-                  local_var_stack_size += ldl[index].size;
-               }
-               else
-                  v[input_param_count++] = reinterpret_cast<T*>(ldl[index].pointer);
+#endif
+            
+            struct synthesize_binary_ext_expression
+            {
+                static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                          const details::operator_type& operation,
+                                                          expression_node_ptr (&branch)[2])
+                {
+                    const bool left_neg  = is_neg_unary_node(branch[0]);
+                    const bool right_neg = is_neg_unary_node(branch[1]);
+                    
+                    if (left_neg && right_neg)
+                    {
+                        if (
+                            (details::e_add == operation) ||
+                            (details::e_sub == operation) ||
+                            (details::e_mul == operation) ||
+                            (details::e_div == operation)
+                            )
+                        {
+                            if (
+                                !expr_gen.parser_->simplify_unary_negation_branch(branch[0]) ||
+                                !expr_gen.parser_->simplify_unary_negation_branch(branch[1])
+                                )
+                            {
+                                details::free_all_nodes(*expr_gen.node_allocator_,branch);
+                                
+                                return error_node();
+                            }
+                        }
+                        
+                        switch (operation)
+                        {
+                                // -f(x + 1) + -g(y + 1) --> -(f(x + 1) + g(y + 1))
+                            case details::e_add : return expr_gen(details::e_neg,
+                                                                  expr_gen.node_allocator_->
+                                                                  template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > >
+                                                                  (branch[0],branch[1]));
+                                
+                                // -f(x + 1) - -g(y + 1) --> g(y + 1) - f(x + 1)
+                            case details::e_sub : return expr_gen.node_allocator_->
+                                template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > >
+                                (branch[1],branch[0]);
+                                
+                            default             : break;
+                        }
+                    }
+                    else if (left_neg && !right_neg)
+                    {
+                        if (
+                            (details::e_add == operation) ||
+                            (details::e_sub == operation) ||
+                            (details::e_mul == operation) ||
+                            (details::e_div == operation)
+                            )
+                        {
+                            if (!expr_gen.parser_->simplify_unary_negation_branch(branch[0]))
+                            {
+                                details::free_all_nodes(*expr_gen.node_allocator_,branch);
+                                
+                                return error_node();
+                            }
+                            
+                            switch (operation)
+                            {
+                                    // -f(x + 1) + g(y + 1) --> g(y + 1) - f(x + 1)
+                                case details::e_add : return expr_gen.node_allocator_->
+                                    template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > >
+                                    (branch[1],branch[0]);
+                                    
+                                    // -f(x + 1) - g(y + 1) --> -(f(x + 1) + g(y + 1))
+                                case details::e_sub : return expr_gen(details::e_neg,
+                                                                      expr_gen.node_allocator_->
+                                                                      template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > >
+                                                                      (branch[0],branch[1]));
+                                    
+                                    // -f(x + 1) * g(y + 1) --> -(f(x + 1) * g(y + 1))
+                                case details::e_mul : return expr_gen(details::e_neg,
+                                                                      expr_gen.node_allocator_->
+                                                                      template allocate<typename details::binary_ext_node<Type,details::mul_op<Type> > >
+                                                                      (branch[0],branch[1]));
+                                    
+                                    // -f(x + 1) / g(y + 1) --> -(f(x + 1) / g(y + 1))
+                                case details::e_div : return expr_gen(details::e_neg,
+                                                                      expr_gen.node_allocator_->
+                                                                      template allocate<typename details::binary_ext_node<Type,details::div_op<Type> > >
+                                                                      (branch[0],branch[1]));
+                                    
+                                default             : return error_node();
+                            }
+                        }
+                    }
+                    else if (!left_neg && right_neg)
+                    {
+                        if (
+                            (details::e_add == operation) ||
+                            (details::e_sub == operation) ||
+                            (details::e_mul == operation) ||
+                            (details::e_div == operation)
+                            )
+                        {
+                            if (!expr_gen.parser_->simplify_unary_negation_branch(branch[1]))
+                            {
+                                details::free_all_nodes(*expr_gen.node_allocator_,branch);
+                                
+                                return error_node();
+                            }
+                            
+                            switch (operation)
+                            {
+                                    // f(x + 1) + -g(y + 1) --> f(x + 1) - g(y + 1)
+                                case details::e_add : return expr_gen.node_allocator_->
+                                    template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > >
+                                    (branch[0],branch[1]);
+                                    
+                                    // f(x + 1) - - g(y + 1) --> f(x + 1) + g(y + 1)
+                                case details::e_sub : return expr_gen.node_allocator_->
+                                    template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > >
+                                    (branch[0],branch[1]);
+                                    
+                                    // f(x + 1) * -g(y + 1) --> -(f(x + 1) * g(y + 1))
+                                case details::e_mul : return expr_gen(details::e_neg,
+                                                                      expr_gen.node_allocator_->
+                                                                      template allocate<typename details::binary_ext_node<Type,details::mul_op<Type> > >
+                                                                      (branch[0],branch[1]));
+                                    
+                                    // f(x + 1) / -g(y + 1) --> -(f(x + 1) / g(y + 1))
+                                case details::e_div : return expr_gen(details::e_neg,
+                                                                      expr_gen.node_allocator_->
+                                                                      template allocate<typename details::binary_ext_node<Type,details::div_op<Type> > >
+                                                                      (branch[0],branch[1]));
+                                    
+                                default             : return error_node();
+                            }
+                        }
+                    }
+                    
+                    switch (operation)
+                    {
+#define case_stmt(op0,op1)                                                           \
+case op0 : return expr_gen.node_allocator_->                                         \
+template allocate<typename details::binary_ext_node<Type,op1<Type> > > \
+(branch[0],branch[1]);                                              \
+
+                            basic_opr_switch_statements
+                            extended_opr_switch_statements
+#undef case_stmt
+                        default : return error_node();
+                    }
+                }
+            };
+            
+            struct synthesize_vob_expression
+            {
+                static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                          const details::operator_type& operation,
+                                                          expression_node_ptr (&branch)[2])
+                {
+                    const Type& v = static_cast<details::variable_node<Type>*>(branch[0])->ref();
+                    
+#ifndef exprtk_disable_enhanced_features
+                    if (details::is_sf3ext_node(branch[1]))
+                    {
+                        expression_node_ptr result = error_node();
+                        
+                        if (synthesize_sf4ext_expression::template compile_right<vtype>(expr_gen,v,operation,branch[1],result))
+                        {
+                            free_node(*expr_gen.node_allocator_,branch[1]);
+                            return result;
+                        }
+                    }
+#endif
+                    
+                    if (
+                        (details::e_mul == operation) ||
+                        (details::e_div == operation)
+                        )
+                    {
+                        if (details::is_uv_node(branch[1]))
+                        {
+                            typedef details::uv_base_node<Type>* uvbn_ptr_t;
+                            
+                            details::operator_type o = static_cast<uvbn_ptr_t>(branch[1])->operation();
+                            
+                            if (details::e_neg == o)
+                            {
+                                const Type& v1 = static_cast<uvbn_ptr_t>(branch[1])->v();
+                                
+                                free_node(*expr_gen.node_allocator_,branch[1]);
+                                
+                                switch (operation)
+                                {
+                                    case details::e_mul : return expr_gen(details::e_neg,
+                                                                          expr_gen.node_allocator_->
+                                                                          template allocate_rr<typename details::
+                                                                          vov_node<Type,details::mul_op<Type> > >(v,v1));
+                                        
+                                    case details::e_div : return expr_gen(details::e_neg,
+                                                                          expr_gen.node_allocator_->
+                                                                          template allocate_rr<typename details::
+                                                                          vov_node<Type,details::div_op<Type> > >(v,v1));
+                                        
+                                    default             : break;
+                                }
+                            }
+                        }
+                    }
+                    
+                    switch (operation)
+                    {
+#define case_stmt(op0,op1)                                                       \
+case op0 : return expr_gen.node_allocator_->                                     \
+template allocate_rc<typename details::vob_node<Type,op1<Type> > > \
+(v,branch[1]);                                                  \
+
+                            basic_opr_switch_statements
+                            extended_opr_switch_statements
+#undef case_stmt
+                        default : return error_node();
+                    }
+                }
+            };
+            
+            struct synthesize_bov_expression
+            {
+                static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                          const details::operator_type& operation,
+                                                          expression_node_ptr (&branch)[2])
+                {
+                    const Type& v = static_cast<details::variable_node<Type>*>(branch[1])->ref();
+                    
+#ifndef exprtk_disable_enhanced_features
+                    if (details::is_sf3ext_node(branch[0]))
+                    {
+                        expression_node_ptr result = error_node();
+                        
+                        if (synthesize_sf4ext_expression::template compile_left<vtype>(expr_gen,v,operation,branch[0],result))
+                        {
+                            free_node(*expr_gen.node_allocator_,branch[0]);
+                            
+                            return result;
+                        }
+                    }
+#endif
+                    
+                    if (
+                        (details::e_add == operation) ||
+                        (details::e_sub == operation) ||
+                        (details::e_mul == operation) ||
+                        (details::e_div == operation)
+                        )
+                    {
+                        if (details::is_uv_node(branch[0]))
+                        {
+                            typedef details::uv_base_node<Type>* uvbn_ptr_t;
+                            
+                            details::operator_type o = static_cast<uvbn_ptr_t>(branch[0])->operation();
+                            
+                            if (details::e_neg == o)
+                            {
+                                const Type& v0 = static_cast<uvbn_ptr_t>(branch[0])->v();
+                                
+                                free_node(*expr_gen.node_allocator_,branch[0]);
+                                
+                                switch (operation)
+                                {
+                                    case details::e_add : return expr_gen.node_allocator_->
+                                        template allocate_rr<typename details::
+                                        vov_node<Type,details::sub_op<Type> > >(v,v0);
+                                        
+                                    case details::e_sub : return expr_gen(details::e_neg,
+                                                                          expr_gen.node_allocator_->
+                                                                          template allocate_rr<typename details::
+                                                                          vov_node<Type,details::add_op<Type> > >(v0,v));
+                                        
+                                    case details::e_mul : return expr_gen(details::e_neg,
+                                                                          expr_gen.node_allocator_->
+                                                                          template allocate_rr<typename details::
+                                                                          vov_node<Type,details::mul_op<Type> > >(v0,v));
+                                        
+                                    case details::e_div : return expr_gen(details::e_neg,
+                                                                          expr_gen.node_allocator_->
+                                                                          template allocate_rr<typename details::
+                                                                          vov_node<Type,details::div_op<Type> > >(v0,v));
+                                    default : break;
+                                }
+                            }
+                        }
+                    }
+                    
+                    switch (operation)
+                    {
+#define case_stmt(op0,op1)                                                       \
+case op0 : return expr_gen.node_allocator_->                                     \
+template allocate_cr<typename details::bov_node<Type,op1<Type> > > \
+(branch[0],v);                                                  \
+
+                            basic_opr_switch_statements
+                            extended_opr_switch_statements
+#undef case_stmt
+                        default : return error_node();
+                    }
+                }
+            };
+            
+            struct synthesize_cob_expression
+            {
+                static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                          const details::operator_type& operation,
+                                                          expression_node_ptr (&branch)[2])
+                {
+                    const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value();
+                    
+                    free_node(*expr_gen.node_allocator_,branch[0]);
+                    
+                    if ((T(0) == c) && (details::e_mul == operation))
+                    {
+                        free_node(*expr_gen.node_allocator_,branch[1]);
+                        
+                        return expr_gen(T(0));
+                    }
+                    else if ((T(0) == c) && (details::e_div == operation))
+                    {
+                        free_node(*expr_gen.node_allocator_, branch[1]);
+                        
+                        return expr_gen(T(0));
+                    }
+                    else if ((T(0) == c) && (details::e_add == operation))
+                        return branch[1];
+                    else if ((T(1) == c) && (details::e_mul == operation))
+                        return branch[1];
+                    
+                    if (details::is_cob_node(branch[1]))
+                    {
+                        // Simplify expressions of the form:
+                        // 1. (1 * (2 * (3 * (4 * (5 * (6 * (7 * (8 * (9 + x))))))))) --> 40320 * (9 + x)
+                        // 2. (1 + (2 + (3 + (4 + (5 + (6 + (7 + (8 + (9 + x))))))))) --> 45 + x
+                        if (
+                            (operation == details::e_mul) ||
+                            (operation == details::e_add)
+                            )
+                        {
+                            details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]);
+                            
+                            if (operation == cobnode->operation())
+                            {
+                                switch (operation)
+                                {
+                                    case details::e_add : cobnode->set_c(c + cobnode->c()); break;
+                                    case details::e_mul : cobnode->set_c(c * cobnode->c()); break;
+                                    default             : return error_node();
+                                }
+                                
+                                return cobnode;
+                            }
+                        }
+                        
+                        if (operation == details::e_mul)
+                        {
+                            details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]);
+                            details::operator_type cob_opr = cobnode->operation();
+                            
+                            if (
+                                (details::e_div == cob_opr) ||
+                                (details::e_mul == cob_opr)
+                                )
+                            {
+                                switch (cob_opr)
+                                {
+                                    case details::e_div : cobnode->set_c(c * cobnode->c()); break;
+                                    case details::e_mul : cobnode->set_c(cobnode->c() / c); break;
+                                    default             : return error_node();
+                                }
+                                
+                                return cobnode;
+                            }
+                        }
+                        else if (operation == details::e_div)
+                        {
+                            details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]);
+                            details::operator_type cob_opr = cobnode->operation();
+                            
+                            if (
+                                (details::e_div == cob_opr) ||
+                                (details::e_mul == cob_opr)
+                                )
+                            {
+                                details::expression_node<Type>* new_cobnode = error_node();
+                                
+                                switch (cob_opr)
+                                {
+                                    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));
+                                        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));
+                                        break;
+                                        
+                                    default             : return error_node();
+                                }
+                                
+                                free_node(*expr_gen.node_allocator_,branch[1]);
+                                
+                                return new_cobnode;
+                            }
+                        }
+                    }
+#ifndef exprtk_disable_enhanced_features
+                    else if (details::is_sf3ext_node(branch[1]))
+                    {
+                        expression_node_ptr result = error_node();
+                        
+                        if (synthesize_sf4ext_expression::template compile_right<ctype>(expr_gen,c,operation,branch[1],result))
+                        {
+                            free_node(*expr_gen.node_allocator_,branch[1]);
+                            
+                            return result;
+                        }
+                    }
+#endif
+                    
+                    switch (operation)
+                    {
+#define case_stmt(op0,op1)                                                       \
+case op0 : return expr_gen.node_allocator_->                                     \
+template allocate_tt<typename details::cob_node<Type,op1<Type> > > \
+(c,branch[1]);                                                  \
+
+                            basic_opr_switch_statements
+                            extended_opr_switch_statements
+#undef case_stmt
+                        default : return error_node();
+                    }
+                }
+            };
+            
+            struct synthesize_boc_expression
+            {
+                static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                          const details::operator_type& operation,
+                                                          expression_node_ptr (&branch)[2])
+                {
+                    const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
+                    
+                    details::free_node(*(expr_gen.node_allocator_),branch[1]);
+                    
+                    if ((T(0) == c) && (details::e_mul == operation))
+                    {
+                        free_node(*expr_gen.node_allocator_,branch[0]);
+                        
+                        return expr_gen(T(0));
+                    }
+                    else if ((T(0) == c) && (details::e_div == operation))
+                    {
+                        free_node(*expr_gen.node_allocator_, branch[0]);
+                        
+                        return expr_gen(std::numeric_limits<T>::quiet_NaN());
+                    }
+                    else if ((T(0) == c) && (details::e_add == operation))
+                        return branch[0];
+                    else if ((T(1) == c) && (details::e_mul == operation))
+                        return branch[0];
+                    
+                    if (details::is_boc_node(branch[0]))
+                    {
+                        // Simplify expressions of the form:
+                        // 1. (((((((((x + 9) * 8) * 7) * 6) * 5) * 4) * 3) * 2) * 1) --> (x + 9) * 40320
+                        // 2. (((((((((x + 9) + 8) + 7) + 6) + 5) + 4) + 3) + 2) + 1) --> x + 45
+                        if (
+                            (operation == details::e_mul) ||
+                            (operation == details::e_add)
+                            )
+                        {
+                            details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]);
+                            
+                            if (operation == bocnode->operation())
+                            {
+                                switch (operation)
+                                {
+                                    case details::e_add : bocnode->set_c(c + bocnode->c()); break;
+                                    case details::e_mul : bocnode->set_c(c * bocnode->c()); break;
+                                    default             : return error_node();
+                                }
+                                
+                                return bocnode;
+                            }
+                        }
+                        else if (operation == details::e_div)
+                        {
+                            details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]);
+                            details::operator_type boc_opr = bocnode->operation();
+                            
+                            if (
+                                (details::e_div == boc_opr) ||
+                                (details::e_mul == boc_opr)
+                                )
+                            {
+                                switch (boc_opr)
+                                {
+                                    case details::e_div : bocnode->set_c(c * bocnode->c()); break;
+                                    case details::e_mul : bocnode->set_c(bocnode->c() / c); break;
+                                    default             : return error_node();
+                                }
+                                
+                                return bocnode;
+                            }
+                        }
+                        else if (operation == details::e_pow)
+                        {
+                            // (v ^ c0) ^ c1 --> v ^(c0 * c1)
+                            details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]);
+                            details::operator_type boc_opr = bocnode->operation();
+                            
+                            if (details::e_pow == boc_opr)
+                            {
+                                bocnode->set_c(bocnode->c() * c);
+                                
+                                return bocnode;
+                            }
+                        }
+                    }
+                    
+#ifndef exprtk_disable_enhanced_features
+                    if (details::is_sf3ext_node(branch[0]))
+                    {
+                        expression_node_ptr result = error_node();
+                        
+                        if (synthesize_sf4ext_expression::template compile_left<ctype>(expr_gen,c,operation,branch[0],result))
+                        {
+                            free_node(*expr_gen.node_allocator_,branch[0]);
+                            
+                            return result;
+                        }
+                    }
+#endif
+                    
+                    switch (operation)
+                    {
+#define case_stmt(op0,op1)                                                       \
+case op0 : return expr_gen.node_allocator_->                                     \
+template allocate_cr<typename details::boc_node<Type,op1<Type> > > \
+(branch[0],c);                                                  \
+
+                            basic_opr_switch_statements
+                            extended_opr_switch_statements
+#undef case_stmt
+                        default : return error_node();
+                    }
+                }
+            };
+            
+            struct synthesize_cocob_expression
+            {
+                static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                          const details::operator_type& operation,
+                                                          expression_node_ptr (&branch)[2])
+                {
+                    expression_node_ptr result = error_node();
+                    
+                    // (cob) o c --> cob
+                    if (details::is_cob_node(branch[0]))
+                    {
+                        details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[0]);
+                        const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
+                        
+                        if ((T(0) == c) && (details::e_mul == operation))
+                        {
+                            free_node(*expr_gen.node_allocator_,branch[0]);
+                            free_node(*expr_gen.node_allocator_,branch[1]);
+                            
+                            return expr_gen(T(0));
+                        }
+                        else if ((T(0) == c) && (details::e_div == operation))
+                        {
+                            free_node(*expr_gen.node_allocator_,branch[0]);
+                            free_node(*expr_gen.node_allocator_,branch[1]);
+                            
+                            return expr_gen(T(std::numeric_limits<T>::quiet_NaN()));
+                        }
+                        else if ((T(0) == c) && (details::e_add == operation))
+                        {
+                            free_node(*expr_gen.node_allocator_, branch[1]);
+                            return branch[0];
+                        }
+                        else if ((T(1) == c) && (details::e_mul == operation))
+                        {
+                            free_node(*expr_gen.node_allocator_, branch[1]);
+                            return branch[0];
+                        }
+                        else if ((T(1) == c) && (details::e_div == operation))
+                        {
+                            free_node(*expr_gen.node_allocator_, branch[1]);
+                            return branch[0];
+                        }
+                        
+                        bool op_addsub = (details::e_add == cobnode->operation()) ||
+                        (details::e_sub == cobnode->operation());
+                        
+                        if (op_addsub)
+                        {
+                            switch (operation)
+                            {
+                                case details::e_add : cobnode->set_c(cobnode->c() + c); break;
+                                case details::e_sub : cobnode->set_c(cobnode->c() - c); break;
+                                default             : return error_node();
+                            }
+                            
+                            result = cobnode;
+                        }
+                        else if (details::e_mul == cobnode->operation())
+                        {
+                            switch (operation)
+                            {
+                                case details::e_mul : cobnode->set_c(cobnode->c() * c); break;
+                                case details::e_div : cobnode->set_c(cobnode->c() / c); break;
+                                default             : return error_node();
+                            }
+                            
+                            result = cobnode;
+                        }
+                        else if (details::e_div == cobnode->operation())
+                        {
+                            if (details::e_mul == operation)
+                            {
+                                cobnode->set_c(cobnode->c() * c);
+                                result = cobnode;
+                            }
+                            else if (details::e_div == operation)
+                            {
+                                result = expr_gen.node_allocator_->
+                                template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
+                                (cobnode->c() / c,cobnode->move_branch(0));
+                                
+                                free_node(*expr_gen.node_allocator_,branch[0]);
+                            }
+                        }
+                        
+                        if (result)
+                        {
+                            free_node(*expr_gen.node_allocator_,branch[1]);
+                        }
+                    }
+                    
+                    // c o (cob) --> cob
+                    else if (details::is_cob_node(branch[1]))
+                    {
+                        details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]);
+                        const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value();
+                        
+                        if ((T(0) == c) && (details::e_mul == operation))
+                        {
+                            free_node(*expr_gen.node_allocator_,branch[0]);
+                            free_node(*expr_gen.node_allocator_,branch[1]);
+                            
+                            return expr_gen(T(0));
+                        }
+                        else if ((T(0) == c) && (details::e_div == operation))
+                        {
+                            free_node(*expr_gen.node_allocator_,branch[0]);
+                            free_node(*expr_gen.node_allocator_,branch[1]);
+                            
+                            return expr_gen(T(0));
+                        }
+                        else if ((T(0) == c) && (details::e_add == operation))
+                        {
+                            free_node(*expr_gen.node_allocator_, branch[0]);
+                            return branch[1];
+                        }
+                        else if ((T(1) == c) && (details::e_mul == operation))
+                        {
+                            free_node(*expr_gen.node_allocator_, branch[0]);
+                            return branch[1];
+                        }
+                        
+                        if (details::e_add == cobnode->operation())
+                        {
+                            if (details::e_add == operation)
+                            {
+                                cobnode->set_c(c + cobnode->c());
+                                result = cobnode;
+                            }
+                            else if (details::e_sub == operation)
+                            {
+                                result = expr_gen.node_allocator_->
+                                template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > >
+                                (c - cobnode->c(),cobnode->move_branch(0));
+                                
+                                free_node(*expr_gen.node_allocator_,branch[1]);
+                            }
+                        }
+                        else if (details::e_sub == cobnode->operation())
+                        {
+                            if (details::e_add == operation)
+                            {
+                                cobnode->set_c(c + cobnode->c());
+                                result = cobnode;
+                            }
+                            else if (details::e_sub == operation)
+                            {
+                                result = expr_gen.node_allocator_->
+                                template allocate_tt<typename details::cob_node<Type,details::add_op<Type> > >
+                                (c - cobnode->c(),cobnode->move_branch(0));
+                                
+                                free_node(*expr_gen.node_allocator_,branch[1]);
+                            }
+                        }
+                        else if (details::e_mul == cobnode->operation())
+                        {
+                            if (details::e_mul == operation)
+                            {
+                                cobnode->set_c(c * cobnode->c());
+                                result = cobnode;
+                            }
+                            else if (details::e_div == operation)
+                            {
+                                result = expr_gen.node_allocator_->
+                                template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
+                                (c / cobnode->c(),cobnode->move_branch(0));
+                                
+                                free_node(*expr_gen.node_allocator_,branch[1]);
+                            }
+                        }
+                        else if (details::e_div == cobnode->operation())
+                        {
+                            if (details::e_mul == operation)
+                            {
+                                cobnode->set_c(c * cobnode->c());
+                                result = cobnode;
+                            }
+                            else if (details::e_div == operation)
+                            {
+                                result = expr_gen.node_allocator_->
+                                template allocate_tt<typename details::cob_node<Type,details::mul_op<Type> > >
+                                (c / cobnode->c(),cobnode->move_branch(0));
+                                
+                                free_node(*expr_gen.node_allocator_,branch[1]);
+                            }
+                        }
+                        
+                        if (result)
+                        {
+                            free_node(*expr_gen.node_allocator_,branch[0]);
+                        }
+                    }
+                    
+                    return result;
+                }
+            };
+            
+            struct synthesize_coboc_expression
+            {
+                static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                          const details::operator_type& operation,
+                                                          expression_node_ptr (&branch)[2])
+                {
+                    expression_node_ptr result = error_node();
+                    
+                    // (boc) o c --> boc
+                    if (details::is_boc_node(branch[0]))
+                    {
+                        details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]);
+                        const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
+                        
+                        if (details::e_add == bocnode->operation())
+                        {
+                            switch (operation)
+                            {
+                                case details::e_add : bocnode->set_c(bocnode->c() + c); break;
+                                case details::e_sub : bocnode->set_c(bocnode->c() - c); break;
+                                default             : return error_node();
+                            }
+                            
+                            result = bocnode;
+                        }
+                        else if (details::e_mul == bocnode->operation())
+                        {
+                            switch (operation)
+                            {
+                                case details::e_mul : bocnode->set_c(bocnode->c() * c); break;
+                                case details::e_div : bocnode->set_c(bocnode->c() / c); break;
+                                default             : return error_node();
+                            }
+                            
+                            result = bocnode;
+                        }
+                        else if (details::e_sub == bocnode->operation())
+                        {
+                            if (details::e_add == operation)
+                            {
+                                result = expr_gen.node_allocator_->
+                                template allocate_tt<typename details::boc_node<Type,details::add_op<Type> > >
+                                (bocnode->move_branch(0),c - bocnode->c());
+                                
+                                free_node(*expr_gen.node_allocator_,branch[0]);
+                            }
+                            else if (details::e_sub == operation)
+                            {
+                                bocnode->set_c(bocnode->c() + c);
+                                result = bocnode;
+                            }
+                        }
+                        else if (details::e_div == bocnode->operation())
+                        {
+                            switch (operation)
+                            {
+                                case details::e_div : bocnode->set_c(bocnode->c() * c); break;
+                                case details::e_mul : bocnode->set_c(bocnode->c() / c); break;
+                                default             : return error_node();
+                            }
+                            
+                            result = bocnode;
+                        }
+                        
+                        if (result)
+                        {
+                            free_node(*expr_gen.node_allocator_,branch[1]);
+                        }
+                    }
+                    
+                    // c o (boc) --> boc
+                    else if (details::is_boc_node(branch[1]))
+                    {
+                        details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[1]);
+                        const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value();
+                        
+                        if (details::e_add == bocnode->operation())
+                        {
+                            if (details::e_add == operation)
+                            {
+                                bocnode->set_c(c + bocnode->c());
+                                result = bocnode;
+                            }
+                            else if (details::e_sub == operation)
+                            {
+                                result = expr_gen.node_allocator_->
+                                template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > >
+                                (c - bocnode->c(),bocnode->move_branch(0));
+                                
+                                free_node(*expr_gen.node_allocator_,branch[1]);
+                            }
+                        }
+                        else if (details::e_sub == bocnode->operation())
+                        {
+                            if (details::e_add == operation)
+                            {
+                                result = expr_gen.node_allocator_->
+                                template allocate_tt<typename details::boc_node<Type,details::add_op<Type> > >
+                                (bocnode->move_branch(0),c - bocnode->c());
+                                
+                                free_node(*expr_gen.node_allocator_,branch[1]);
+                            }
+                            else if (details::e_sub == operation)
+                            {
+                                result = expr_gen.node_allocator_->
+                                template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > >
+                                (c + bocnode->c(),bocnode->move_branch(0));
+                                
+                                free_node(*expr_gen.node_allocator_,branch[1]);
+                            }
+                        }
+                        else if (details::e_mul == bocnode->operation())
+                        {
+                            if (details::e_mul == operation)
+                            {
+                                bocnode->set_c(c * bocnode->c());
+                                result = bocnode;
+                            }
+                            else if (details::e_div == operation)
+                            {
+                                result = expr_gen.node_allocator_->
+                                template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
+                                (c / bocnode->c(),bocnode->move_branch(0));
+                                
+                                free_node(*expr_gen.node_allocator_,branch[1]);
+                            }
+                        }
+                        else if (details::e_div == bocnode->operation())
+                        {
+                            if (details::e_mul == operation)
+                            {
+                                bocnode->set_c(bocnode->c() / c);
+                                result = bocnode;
+                            }
+                            else if (details::e_div == operation)
+                            {
+                                result = expr_gen.node_allocator_->
+                                template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
+                                (c * bocnode->c(),bocnode->move_branch(0));
+                                
+                                free_node(*expr_gen.node_allocator_,branch[1]);
+                            }
+                        }
+                        
+                        if (result)
+                        {
+                            free_node(*expr_gen.node_allocator_,branch[0]);
+                        }
+                    }
+                    
+                    return result;
+                }
+            };
+            
+#ifndef exprtk_disable_enhanced_features
+            inline bool synthesize_expression(const details::operator_type& operation,
+                                              expression_node_ptr (&branch)[2],
+                                              expression_node_ptr& result)
+            {
+                result = error_node();
+                
+                if (!operation_optimisable(operation))
+                    return false;
+                
+                const std::string node_id = branch_to_id(branch);
+                typename synthesize_map_t::iterator itr = synthesize_map_.find(node_id);
+                
+                if (synthesize_map_.end() != itr)
+                {
+                    result = itr->second(*this,operation,branch);
+                    
+                    return true;
+                }
+                else
+                    return false;
+            }
+            
+            struct synthesize_vov_expression
+            {
+                static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                          const details::operator_type& operation,
+                                                          expression_node_ptr (&branch)[2])
+                {
+                    const Type& v1 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
+                    const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
+                    
+                    switch (operation)
+                    {
+#define case_stmt(op0,op1)                                                       \
+case op0 : return expr_gen.node_allocator_->                                     \
+template allocate_rr<typename details::vov_node<Type,op1<Type> > > \
+(v1,v2);                                                        \
+
+                            basic_opr_switch_statements
+                            extended_opr_switch_statements
+#undef case_stmt
+                        default : return error_node();
+                    }
+                }
+            };
+            
+            struct synthesize_cov_expression
+            {
+                static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                          const details::operator_type& operation,
+                                                          expression_node_ptr (&branch)[2])
+                {
+                    const Type  c = static_cast<details::literal_node<Type>*> (branch[0])->value();
+                    const Type& v = static_cast<details::variable_node<Type>*>(branch[1])->ref();
+                    
+                    details::free_node(*(expr_gen.node_allocator_),branch[0]);
+                    
+                    if ((T(0) == c) && (details::e_mul == operation))
+                        return expr_gen(T(0));
+                    else if ((T(0) == c) && (details::e_div == operation))
+                        return expr_gen(T(0));
+                    else if ((T(0) == c) && (details::e_add == operation))
+                        return static_cast<details::variable_node<Type>*>(branch[1]);
+                    else if ((T(1) == c) && (details::e_mul == operation))
+                        return static_cast<details::variable_node<Type>*>(branch[1]);
+                    
+                    switch (operation)
+                    {
+#define case_stmt(op0,op1)                                                       \
+case op0 : return expr_gen.node_allocator_->                                     \
+template allocate_cr<typename details::cov_node<Type,op1<Type> > > \
+(c,v);                                                          \
+
+                            basic_opr_switch_statements
+                            extended_opr_switch_statements
+#undef case_stmt
+                        default : return error_node();
+                    }
+                }
+            };
+            
+            struct synthesize_voc_expression
+            {
+                static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                          const details::operator_type& operation,
+                                                          expression_node_ptr (&branch)[2])
+                {
+                    const Type& v = static_cast<details::variable_node<Type>*>(branch[0])->ref();
+                    const Type  c = static_cast<details::literal_node<Type>*> (branch[1])->value();
+                    
+                    details::free_node(*(expr_gen.node_allocator_),branch[1]);
+                    
+                    if (expr_gen.cardinal_pow_optimisable(operation,c))
+                    {
+                        if (std::equal_to<T>()(T(1),c))
+                            return branch[0];
+                        else
+                            return expr_gen.cardinal_pow_optimisation(v,c);
+                    }
+                    else if ((T(0) == c) && (details::e_mul == operation))
+                        return expr_gen(T(0));
+                    else if ((T(0) == c) && (details::e_div == operation))
+                        return expr_gen(std::numeric_limits<T>::quiet_NaN());
+                    else if ((T(0) == c) && (details::e_add == operation))
+                        return static_cast<details::variable_node<Type>*>(branch[0]);
+                    else if ((T(1) == c) && (details::e_mul == operation))
+                        return static_cast<details::variable_node<Type>*>(branch[0]);
+                    else if ((T(1) == c) && (details::e_div == operation))
+                        return static_cast<details::variable_node<Type>*>(branch[0]);
+                    
+                    switch (operation)
+                    {
+#define case_stmt(op0,op1)                                                       \
+case op0 : return expr_gen.node_allocator_->                                     \
+template allocate_rc<typename details::voc_node<Type,op1<Type> > > \
+(v,c);                                                          \
+
+                            basic_opr_switch_statements
+                            extended_opr_switch_statements
+#undef case_stmt
+                        default : return error_node();
+                    }
+                }
+            };
+            
+            struct synthesize_sf3ext_expression
+            {
+                template <typename T0, typename T1, typename T2>
+                static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                          const details::operator_type& sf3opr,
+                                                          T0 t0, T1 t1, T2 t2)
+                {
+                    switch (sf3opr)
+                    {
+#define case_stmt(op)                                                                              \
+case details::e_sf##op : return details::T0oT1oT2_sf3ext<T,T0,T1,T2,details::sf##op##_op<Type> >:: \
+allocate(*(expr_gen.node_allocator_),t0,t1,t2);                                      \
+
+                            case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03)
+                            case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07)
+                            case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11)
+                            case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15)
+                            case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19)
+                            case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23)
+                            case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27)
+                            case_stmt(28) case_stmt(29) case_stmt(30)
+#undef case_stmt
+                        default : return error_node();
+                    }
+                }
+                
+                template <typename T0, typename T1, typename T2>
+                static inline bool compile(expression_generator<Type>& expr_gen, const std::string& id,
+                                           T0 t0, T1 t1, T2 t2,
+                                           expression_node_ptr& result)
+                {
+                    details::operator_type sf3opr;
+                    
+                    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);
+                    
+                    return true;
+                }
+            };
+            
+            struct synthesize_sf4ext_expression
+            {
+                template <typename T0, typename T1, typename T2, typename T3>
+                static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                          const details::operator_type& sf4opr,
+                                                          T0 t0, T1 t1, T2 t2, T3 t3)
+                {
+                    switch (sf4opr)
+                    {
+#define case_stmt0(op)                                                                                      \
+case details::e_sf##op : return details::T0oT1oT2oT3_sf4ext<Type,T0,T1,T2,T3,details::sf##op##_op<Type> >:: \
+allocate(*(expr_gen.node_allocator_),t0,t1,t2,t3);                                            \
+
+                            
+#define case_stmt1(op)                                                                                             \
+case details::e_sf4ext##op : return details::T0oT1oT2oT3_sf4ext<Type,T0,T1,T2,T3,details::sfext##op##_op<Type> >:: \
+allocate(*(expr_gen.node_allocator_),t0,t1,t2,t3);                                                   \
+
+                            case_stmt0(48) case_stmt0(49) case_stmt0(50) case_stmt0(51)
+                            case_stmt0(52) case_stmt0(53) case_stmt0(54) case_stmt0(55)
+                            case_stmt0(56) case_stmt0(57) case_stmt0(58) case_stmt0(59)
+                            case_stmt0(60) case_stmt0(61) case_stmt0(62) case_stmt0(63)
+                            case_stmt0(64) case_stmt0(65) case_stmt0(66) case_stmt0(67)
+                            case_stmt0(68) case_stmt0(69) case_stmt0(70) case_stmt0(71)
+                            case_stmt0(72) case_stmt0(73) case_stmt0(74) case_stmt0(75)
+                            case_stmt0(76) case_stmt0(77) case_stmt0(78) case_stmt0(79)
+                            case_stmt0(80) case_stmt0(81) case_stmt0(82) case_stmt0(83)
+                            
+                            case_stmt1(00) case_stmt1(01) case_stmt1(02) case_stmt1(03)
+                            case_stmt1(04) case_stmt1(05) case_stmt1(06) case_stmt1(07)
+                            case_stmt1(08) case_stmt1(09) case_stmt1(10) case_stmt1(11)
+                            case_stmt1(12) case_stmt1(13) case_stmt1(14) case_stmt1(15)
+                            case_stmt1(16) case_stmt1(17) case_stmt1(18) case_stmt1(19)
+                            case_stmt1(20) case_stmt1(21) case_stmt1(22) case_stmt1(23)
+                            case_stmt1(24) case_stmt1(25) case_stmt1(26) case_stmt1(27)
+                            case_stmt1(28) case_stmt1(29) case_stmt1(30) case_stmt1(31)
+                            case_stmt1(32) case_stmt1(33) case_stmt1(34) case_stmt1(35)
+                            case_stmt1(36) case_stmt1(37) case_stmt1(38) case_stmt1(39)
+                            case_stmt1(40) case_stmt1(41) case_stmt1(42) case_stmt1(43)
+                            case_stmt1(44) case_stmt1(45) case_stmt1(46) case_stmt1(47)
+                            case_stmt1(48) case_stmt1(49) case_stmt1(50) case_stmt1(51)
+                            case_stmt1(52) case_stmt1(53) case_stmt1(54) case_stmt1(55)
+                            case_stmt1(56) case_stmt1(57) case_stmt1(58) case_stmt1(59)
+                            case_stmt1(60)
+                            
+#undef case_stmt0
+#undef case_stmt1
+                        default : return error_node();
+                    }
+                }
+                
+                template <typename T0, typename T1, typename T2, typename T3>
+                static inline bool compile(expression_generator<Type>& expr_gen, const std::string& id,
+                                           T0 t0, T1 t1, T2 t2, T3 t3,
+                                           expression_node_ptr& result)
+                {
+                    details::operator_type sf4opr;
+                    
+                    if (!expr_gen.sf4_optimisable(id,sf4opr))
+                        return false;
+                    else
+                        result = synthesize_sf4ext_expression::template process<T0,T1,T2,T3>(expr_gen,sf4opr,t0,t1,t2,t3);
+                    
+                    return true;
+                }
+                
+                // T o (sf3ext)
+                template <typename ExternalType>
+                static inline bool compile_right(expression_generator<Type>& expr_gen,
+                                                 ExternalType t,
+                                                 const details::operator_type& operation,
+                                                 expression_node_ptr& sf3node,
+                                                 expression_node_ptr& result)
+                {
+                    if (!details::is_sf3ext_node(sf3node))
+                        return false;
+                    
+                    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() + ")";
+                    
+                    switch (n->type())
+                    {
+                        case details::expression_node<Type>::e_covoc : return compile_right_impl
+                            <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>
+                            (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>
+                            (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>
+                            (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>
+                            (expr_gen,id,t,sf3node,result);
+                            
+                        default                                      : return false;
+                    }
+                }
+                
+                // (sf3ext) o T
+                template <typename ExternalType>
+                static inline bool compile_left(expression_generator<Type>& expr_gen,
+                                                ExternalType t,
+                                                const details::operator_type& operation,
+                                                expression_node_ptr& sf3node,
+                                                expression_node_ptr& result)
+                {
+                    if (!details::is_sf3ext_node(sf3node))
+                        return false;
+                    
+                    typedef details::T0oT1oT2_base_node<Type>* sf3ext_base_ptr;
+                    
+                    sf3ext_base_ptr n = static_cast<sf3ext_base_ptr>(sf3node);
+                    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>
+                            (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>
+                            (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>
+                            (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>
+                            (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>
+                            (expr_gen,id,t,sf3node,result);
+                            
+                        default                                      : return false;
+                    }
+                }
+                
+                template <typename SF3TypeNode, typename ExternalType, typename T0, typename T1, typename T2>
+                static inline bool compile_right_impl(expression_generator<Type>& expr_gen,
+                                                      const std::string& id,
+                                                      ExternalType t,
+                                                      expression_node_ptr& node,
+                                                      expression_node_ptr& result)
+                {
+                    SF3TypeNode* n = dynamic_cast<SF3TypeNode*>(node);
+                    
+                    if (n)
+                    {
+                        T0 t0 = n->t0();
+                        T1 t1 = n->t1();
+                        T2 t2 = n->t2();
+                        
+                        return synthesize_sf4ext_expression::
+                        template compile<ExternalType,T0,T1,T2>(expr_gen,id,t,t0,t1,t2,result);
+                    }
+                    else
+                        return false;
+                }
+                
+                template <typename SF3TypeNode, typename ExternalType, typename T0, typename T1, typename T2>
+                static inline bool compile_left_impl(expression_generator<Type>& expr_gen,
+                                                     const std::string& id,
+                                                     ExternalType t,
+                                                     expression_node_ptr& node,
+                                                     expression_node_ptr& result)
+                {
+                    SF3TypeNode* n = dynamic_cast<SF3TypeNode*>(node);
+                    
+                    if (n)
+                    {
+                        T0 t0 = n->t0();
+                        T1 t1 = n->t1();
+                        T2 t2 = n->t2();
+                        
+                        return synthesize_sf4ext_expression::
+                        template compile<T0,T1,T2,ExternalType>(expr_gen,id,t0,t1,t2,t,result);
+                    }
+                    else
+                        return false;
+                }
+            };
+            
+            struct synthesize_vovov_expression0
+            {
+                typedef typename vovov_t::type0 node_type;
+                typedef typename vovov_t::sf3_type sf3_type;
+                
+                static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                          const details::operator_type& operation,
+                                                          expression_node_ptr (&branch)[2])
+                {
+                    // (v0 o0 v1) o1 (v2)
+                    const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]);
+                    const Type& v0 = vov->v0();
+                    const Type& v1 = vov->v1();
+                    const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
+                    const details::operator_type o0 = vov->operation();
+                    const details::operator_type o1 = operation;
+                    
+                    binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+                    binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
+                    
+                    details::free_node(*(expr_gen.node_allocator_),branch[0]);
+                    
+                    expression_node_ptr result = error_node();
+                    
+                    if (expr_gen.parser_->settings_.strength_reduction_enabled())
+                    {
+                        // (v0 / v1) / v2 --> (vovov) v0 / (v1 * v2)
+                        if ((details::e_div == o0) && (details::e_div == o1))
+                        {
+                            const bool synthesis_result =
+                            synthesize_sf3ext_expression::
+                            template compile<vtype,vtype,vtype>(expr_gen,"t/(t*t)",v0,v1,v2,result);
+                            
+                            exprtk_debug(("(v0 / v1) / v2 --> (vovov) v0 / (v1 * v2)\n"));
+                            
+                            return (synthesis_result) ? result : error_node();
+                        }
+                    }
+                    
+                    if (synthesize_sf3ext_expression::template compile<vtype,vtype,vtype>(expr_gen,id(expr_gen,o0,o1),v0,v1,v2,result))
+                        return result;
+                    else if (!expr_gen.valid_operator(o0,f0))
+                        return error_node();
+                    else if (!expr_gen.valid_operator(o1,f1))
+                        return error_node();
+                    else
+                        return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,f0,f1);
+                }
+                
+                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");
+                }
+            };
+            
+            struct synthesize_vovov_expression1
+            {
+                typedef typename vovov_t::type1 node_type;
+                typedef typename vovov_t::sf3_type sf3_type;
+                
+                static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                          const details::operator_type& operation,
+                                                          expression_node_ptr (&branch)[2])
+                {
+                    // (v0) o0 (v1 o1 v2)
+                    const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]);
+                    const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
+                    const Type& v1 = vov->v0();
+                    const Type& v2 = vov->v1();
+                    const details::operator_type o0 = operation;
+                    const details::operator_type o1 = vov->operation();
+                    
+                    binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+                    binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
+                    
+                    details::free_node(*(expr_gen.node_allocator_),branch[1]);
+                    
+                    expression_node_ptr result = error_node();
+                    
+                    if (expr_gen.parser_->settings_.strength_reduction_enabled())
+                    {
+                        // v0 / (v1 / v2) --> (vovov) (v0 * v2) / v1
+                        if ((details::e_div == o0) && (details::e_div == o1))
+                        {
+                            const bool synthesis_result =
+                            synthesize_sf3ext_expression::
+                            template compile<vtype,vtype,vtype>(expr_gen,"(t*t)/t",v0,v2,v1,result);
+                            
+                            exprtk_debug(("v0 / (v1 / v2) --> (vovov) (v0 * v2) / v1\n"));
+                            
+                            return (synthesis_result) ? result : error_node();
+                        }
+                    }
+                    
+                    if (synthesize_sf3ext_expression::template compile<vtype,vtype,vtype>(expr_gen,id(expr_gen,o0,o1),v0,v1,v2,result))
+                        return result;
+                    else if (!expr_gen.valid_operator(o0,f0))
+                        return error_node();
+                    else if (!expr_gen.valid_operator(o1,f1))
+                        return error_node();
+                    else
+                        return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,f0,f1);
+                }
+                
+                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)");
+                }
+            };
+            
+            struct synthesize_vovoc_expression0
+            {
+                typedef typename vovoc_t::type0 node_type;
+                typedef typename vovoc_t::sf3_type sf3_type;
+                
+                static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                          const details::operator_type& operation,
+                                                          expression_node_ptr (&branch)[2])
+                {
+                    // (v0 o0 v1) o1 (c)
+                    const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]);
+                    const Type& v0 = vov->v0();
+                    const Type& v1 = vov->v1();
+                    const Type   c = static_cast<details::literal_node<Type>*>(branch[1])->value();
+                    const details::operator_type o0 = vov->operation();
+                    const details::operator_type o1 = operation;
+                    
+                    binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+                    binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
+                    
+                    details::free_node(*(expr_gen.node_allocator_),branch[0]);
+                    details::free_node(*(expr_gen.node_allocator_),branch[1]);
+                    
+                    expression_node_ptr result = error_node();
+                    
+                    if (expr_gen.parser_->settings_.strength_reduction_enabled())
+                    {
+                        // (v0 / v1) / c --> (vovoc) v0 / (v1 * c)
+                        if ((details::e_div == o0) && (details::e_div == o1))
+                        {
+                            const bool synthesis_result =
+                            synthesize_sf3ext_expression::
+                            template compile<vtype,vtype,ctype>(expr_gen,"t/(t*t)",v0,v1,c,result);
+                            
+                            exprtk_debug(("(v0 / v1) / c --> (vovoc) v0 / (v1 * c)\n"));
+                            
+                            return (synthesis_result) ? result : error_node();
+                        }
+                    }
+                    
+                    if (synthesize_sf3ext_expression::template compile<vtype,vtype,ctype>(expr_gen,id(expr_gen,o0,o1),v0,v1,c,result))
+                        return result;
+                    else if (!expr_gen.valid_operator(o0,f0))
+                        return error_node();
+                    else if (!expr_gen.valid_operator(o1,f1))
+                        return error_node();
+                    else
+                        return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,c,f0,f1);
+                }
+                
+                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");
+                }
+            };
+            
+            struct synthesize_vovoc_expression1
+            {
+                typedef typename vovoc_t::type1 node_type;
+                typedef typename vovoc_t::sf3_type sf3_type;
+                
+                static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                          const details::operator_type& operation,
+                                                          expression_node_ptr (&branch)[2])
+                {
+                    // (v0) o0 (v1 o1 c)
+                    const details::voc_base_node<Type>* voc = static_cast<const details::voc_base_node<Type>*>(branch[1]);
+                    const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
+                    const Type& v1 = voc->v();
+                    const Type   c = voc->c();
+                    const details::operator_type o0 = operation;
+                    const details::operator_type o1 = voc->operation();
+                    
+                    binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+                    binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
+                    
+                    details::free_node(*(expr_gen.node_allocator_),branch[1]);
+                    
+                    expression_node_ptr result = error_node();
+                    
+                    if (expr_gen.parser_->settings_.strength_reduction_enabled())
+                    {
+                        // v0 / (v1 / c) --> (vocov) (v0 * c) / v1
+                        if ((details::e_div == o0) && (details::e_div == o1))
+                        {
+                            const bool synthesis_result =
+                            synthesize_sf3ext_expression::
+                            template compile<vtype,ctype,vtype>(expr_gen,"(t*t)/t",v0,c,v1,result);
+                            
+                            exprtk_debug(("v0 / (v1 / c) --> (vocov) (v0 * c) / v1\n"));
+                            
+                            return (synthesis_result) ? result : error_node();
+                        }
+                    }
+                    
+                    if (synthesize_sf3ext_expression::template compile<vtype,vtype,ctype>(expr_gen,id(expr_gen,o0,o1),v0,v1,c,result))
+                        return result;
+                    else if (!expr_gen.valid_operator(o0,f0))
+                        return error_node();
+                    else if (!expr_gen.valid_operator(o1,f1))
+                        return error_node();
+                    else
+                        return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,c,f0,f1);
+                }
+                
+                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)");
+                }
+            };
+            
+            struct synthesize_vocov_expression0
+            {
+                typedef typename vocov_t::type0 node_type;
+                typedef typename vocov_t::sf3_type sf3_type;
+                
+                static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                          const details::operator_type& operation,
+                                                          expression_node_ptr (&branch)[2])
+                {
+                    // (v0 o0 c) o1 (v1)
+                    const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]);
+                    const Type& v0 = voc->v();
+                    const Type   c = voc->c();
+                    const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
+                    const details::operator_type o0 = voc->operation();
+                    const details::operator_type o1 = operation;
+                    
+                    binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+                    binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
+                    
+                    details::free_node(*(expr_gen.node_allocator_),branch[0]);
+                    
+                    expression_node_ptr result = error_node();
+                    
+                    if (expr_gen.parser_->settings_.strength_reduction_enabled())
+                    {
+                        // (v0 / c) / v1 --> (vovoc) v0 / (v1 * c)
+                        if ((details::e_div == o0) && (details::e_div == o1))
+                        {
+                            const bool synthesis_result =
+                            synthesize_sf3ext_expression::
+                            template compile<vtype,vtype,ctype>(expr_gen,"t/(t*t)",v0,v1,c,result);
+                            
+                            exprtk_debug(("(v0 / c) / v1 --> (vovoc) v0 / (v1 * c)\n"));
+                            
+                            return (synthesis_result) ? result : error_node();
+                        }
+                    }
+                    
+                    if (synthesize_sf3ext_expression::template compile<vtype,ctype,vtype>(expr_gen,id(expr_gen,o0,o1),v0,c,v1,result))
+                        return result;
+                    else if (!expr_gen.valid_operator(o0,f0))
+                        return error_node();
+                    else if (!expr_gen.valid_operator(o1,f1))
+                        return error_node();
+                    else
+                        return node_type::allocate(*(expr_gen.node_allocator_),v0,c,v1,f0,f1);
+                }
+                
+                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");
+                }
+            };
+            
+            struct synthesize_vocov_expression1
+            {
+                typedef typename vocov_t::type1 node_type;
+                typedef typename vocov_t::sf3_type sf3_type;
+                
+                static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                          const details::operator_type& operation,
+                                                          expression_node_ptr (&branch)[2])
+                {
+                    // (v0) o0 (c o1 v1)
+                    const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]);
+                    const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
+                    const Type   c = cov->c();
+                    const Type& v1 = cov->v();
+                    const details::operator_type o0 = operation;
+                    const details::operator_type o1 = cov->operation();
+                    
+                    binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+                    binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
+                    
+                    details::free_node(*(expr_gen.node_allocator_),branch[1]);
+                    
+                    expression_node_ptr result = error_node();
+                    
+                    if (expr_gen.parser_->settings_.strength_reduction_enabled())
+                    {
+                        // v0 / (c / v1) --> (vovoc) (v0 * v1) / c
+                        if ((details::e_div == o0) && (details::e_div == o1))
+                        {
+                            const bool synthesis_result =
+                            synthesize_sf3ext_expression::
+                            template compile<vtype,vtype,ctype>(expr_gen,"(t*t)/t",v0,v1,c,result);
+                            
+                            exprtk_debug(("v0 / (c / v1) --> (vovoc) (v0 * v1) / c\n"));
+                            
+                            return (synthesis_result) ? result : error_node();
+                        }
+                    }
+                    
+                    if (synthesize_sf3ext_expression::template compile<vtype,ctype,vtype>(expr_gen,id(expr_gen,o0,o1),v0,c,v1,result))
+                        return result;
+                    else if (!expr_gen.valid_operator(o0,f0))
+                        return error_node();
+                    else if (!expr_gen.valid_operator(o1,f1))
+                        return error_node();
+                    else
+                        return node_type::allocate(*(expr_gen.node_allocator_),v0,c,v1,f0,f1);
+                }
+                
+                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)");
+                }
+            };
+            
+            struct synthesize_covov_expression0
+            {
+                typedef typename covov_t::type0 node_type;
+                typedef typename covov_t::sf3_type sf3_type;
+                
+                static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                          const details::operator_type& operation,
+                                                          expression_node_ptr (&branch)[2])
+                {
+                    // (c o0 v0) o1 (v1)
+                    const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]);
+                    const Type   c = cov->c();
+                    const Type& v0 = cov->v();
+                    const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
+                    const details::operator_type o0 = cov->operation();
+                    const details::operator_type o1 = operation;
+                    
+                    binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+                    binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
+                    
+                    details::free_node(*(expr_gen.node_allocator_),branch[0]);
+                    
+                    expression_node_ptr result = error_node();
+                    
+                    if (expr_gen.parser_->settings_.strength_reduction_enabled())
+                    {
+                        // (c / v0) / v1 --> (covov) c / (v0 * v1)
+                        if ((details::e_div == o0) && (details::e_div == o1))
+                        {
+                            const bool synthesis_result =
+                            synthesize_sf3ext_expression::
+                            template compile<ctype,vtype,vtype>(expr_gen,"t/(t*t)",c,v0,v1,result);
+                            
+                            exprtk_debug(("(c / v0) / v1 --> (covov) c / (v0 * v1)\n"));
+                            
+                            return (synthesis_result) ? result : error_node();
+                        }
+                    }
+                    
+                    if (synthesize_sf3ext_expression::template compile<ctype,vtype,vtype>(expr_gen,id(expr_gen,o0,o1),c,v0,v1,result))
+                        return result;
+                    else if (!expr_gen.valid_operator(o0,f0))
+                        return error_node();
+                    else if (!expr_gen.valid_operator(o1,f1))
+                        return error_node();
+                    else
+                        return node_type::allocate(*(expr_gen.node_allocator_),c,v0,v1,f0,f1);
+                }
+                
+                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");
+                }
+            };
+            
+            struct synthesize_covov_expression1
+            {
+                typedef typename covov_t::type1 node_type;
+                typedef typename covov_t::sf3_type sf3_type;
+                
+                static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                          const details::operator_type& operation,
+                                                          expression_node_ptr (&branch)[2])
+                {
+                    // (c) o0 (v0 o1 v1)
+                    const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]);
+                    const Type   c = static_cast<details::literal_node<Type>*>(branch[0])->value();
+                    const Type& v0 = vov->v0();
+                    const Type& v1 = vov->v1();
+                    const details::operator_type o0 = operation;
+                    const details::operator_type o1 = vov->operation();
+                    
+                    binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+                    binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
+                    
+                    details::free_node(*(expr_gen.node_allocator_),branch[0]);
+                    details::free_node(*(expr_gen.node_allocator_),branch[1]);
+                    
+                    expression_node_ptr result = error_node();
+                    
+                    if (expr_gen.parser_->settings_.strength_reduction_enabled())
+                    {
+                        // c / (v0 / v1) --> (covov) (c * v1) / v0
+                        if ((details::e_div == o0) && (details::e_div == o1))
+                        {
+                            const bool synthesis_result =
+                            synthesize_sf3ext_expression::
+                            template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",c,v1,v0,result);
+                            
+                            exprtk_debug(("c / (v0 / v1) --> (covov) (c * v1) / v0\n"));
+                            
+                            return (synthesis_result) ? result : error_node();
+                        }
+                    }
+                    
+                    if (synthesize_sf3ext_expression::template compile<ctype,vtype,vtype>(expr_gen,id(expr_gen,o0,o1),c,v0,v1,result))
+                        return result;
+                    else if (!expr_gen.valid_operator(o0,f0))
+                        return error_node();
+                    else if (!expr_gen.valid_operator(o1,f1))
+                        return error_node();
+                    else
+                        return node_type::allocate(*(expr_gen.node_allocator_),c,v0,v1,f0,f1);
+                }
+                
+                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)");
+                }
+            };
+            
+            struct synthesize_covoc_expression0
+            {
+                typedef typename covoc_t::type0 node_type;
+                typedef typename covoc_t::sf3_type sf3_type;
+                
+                static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                          const details::operator_type& operation,
+                                                          expression_node_ptr (&branch)[2])
+                {
+                    // (c0 o0 v) o1 (c1)
+                    const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]);
+                    const Type  c0 = cov->c();
+                    const Type&  v = cov->v();
+                    const Type  c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
+                    const details::operator_type o0 = cov->operation();
+                    const details::operator_type o1 = operation;
+                    
+                    binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+                    binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
+                    
+                    details::free_node(*(expr_gen.node_allocator_),branch[0]);
+                    details::free_node(*(expr_gen.node_allocator_),branch[1]);
+                    
+                    expression_node_ptr result = error_node();
+                    
+                    if (expr_gen.parser_->settings_.strength_reduction_enabled())
+                    {
+                        // (c0 + v) + c1 --> (cov) (c0 + c1) + v
+                        if ((details::e_add == o0) && (details::e_add == o1))
+                        {
+                            exprtk_debug(("(c0 + v) + c1 --> (cov) (c0 + c1) + v\n"));
+                            
+                            return expr_gen.node_allocator_->
+                            template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1,v);
+                        }
+                        // (c0 + v) - c1 --> (cov) (c0 - c1) + v
+                        else if ((details::e_add == o0) && (details::e_sub == o1))
+                        {
+                            exprtk_debug(("(c0 + v) - c1 --> (cov) (c0 - c1) + v\n"));
+                            
+                            return expr_gen.node_allocator_->
+                            template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1,v);
+                        }
+                        // (c0 - v) + c1 --> (cov) (c0 + c1) - v
+                        else if ((details::e_sub == o0) && (details::e_add == o1))
+                        {
+                            exprtk_debug(("(c0 - v) + c1 --> (cov) (c0 + c1) - v\n"));
+                            
+                            return expr_gen.node_allocator_->
+                            template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1,v);
+                        }
+                        // (c0 - v) - c1 --> (cov) (c0 - c1) - v
+                        else if ((details::e_sub == o0) && (details::e_sub == o1))
+                        {
+                            exprtk_debug(("(c0 - v) - c1 --> (cov) (c0 - c1) - v\n"));
+                            
+                            return expr_gen.node_allocator_->
+                            template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1,v);
+                        }
+                        // (c0 * v) * c1 --> (cov) (c0 * c1) * v
+                        else if ((details::e_mul == o0) && (details::e_mul == o1))
+                        {
+                            exprtk_debug(("(c0 * v) * c1 --> (cov) (c0 * c1) * v\n"));
+                            
+                            return expr_gen.node_allocator_->
+                            template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1,v);
+                        }
+                        // (c0 * v) / c1 --> (cov) (c0 / c1) * v
+                        else if ((details::e_mul == o0) && (details::e_div == o1))
+                        {
+                            exprtk_debug(("(c0 * v) / c1 --> (cov) (c0 / c1) * v\n"));
+                            
+                            return expr_gen.node_allocator_->
+                            template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1,v);
+                        }
+                        // (c0 / v) * c1 --> (cov) (c0 * c1) / v
+                        else if ((details::e_div == o0) && (details::e_mul == o1))
+                        {
+                            exprtk_debug(("(c0 / v) * c1 --> (cov) (c0 * c1) / v\n"));
+                            
+                            return expr_gen.node_allocator_->
+                            template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1,v);
+                        }
+                        // (c0 / v) / c1 --> (cov) (c0 / c1) / v
+                        else if ((details::e_div == o0) && (details::e_div == o1))
+                        {
+                            exprtk_debug(("(c0 / v) / c1 --> (cov) (c0 / c1) / v\n"));
+                            
+                            return expr_gen.node_allocator_->
+                            template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1,v);
+                        }
+                    }
+                    
+                    if (synthesize_sf3ext_expression::template compile<ctype,vtype,ctype>(expr_gen,id(expr_gen,o0,o1),c0,v,c1,result))
+                        return result;
+                    else if (!expr_gen.valid_operator(o0,f0))
+                        return error_node();
+                    else if (!expr_gen.valid_operator(o1,f1))
+                        return error_node();
+                    else
+                        return node_type::allocate(*(expr_gen.node_allocator_),c0,v,c1,f0,f1);
+                }
+                
+                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");
+                }
+            };
+            
+            struct synthesize_covoc_expression1
+            {
+                typedef typename covoc_t::type1 node_type;
+                typedef typename covoc_t::sf3_type sf3_type;
+                
+                static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                          const details::operator_type& operation,
+                                                          expression_node_ptr (&branch)[2])
+                {
+                    // (c0) o0 (v o1 c1)
+                    const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]);
+                    const Type  c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
+                    const Type&  v = voc->v();
+                    const Type  c1 = voc->c();
+                    const details::operator_type o0 = operation;
+                    const details::operator_type o1 = voc->operation();
+                    
+                    binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+                    binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
+                    
+                    details::free_node(*(expr_gen.node_allocator_),branch[0]);
+                    details::free_node(*(expr_gen.node_allocator_),branch[1]);
+                    
+                    expression_node_ptr result = error_node();
+                    
+                    if (expr_gen.parser_->settings_.strength_reduction_enabled())
+                    {
+                        // (c0) + (v + c1) --> (cov) (c0 + c1) + v
+                        if ((details::e_add == o0) && (details::e_add == o1))
+                        {
+                            exprtk_debug(("(c0) + (v + c1) --> (cov) (c0 + c1) + v\n"));
+                            
+                            return expr_gen.node_allocator_->
+                            template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1,v);
+                        }
+                        // (c0) + (v - c1) --> (cov) (c0 - c1) + v
+                        else if ((details::e_add == o0) && (details::e_sub == o1))
+                        {
+                            exprtk_debug(("(c0) + (v - c1) --> (cov) (c0 - c1) + v\n"));
+                            
+                            return expr_gen.node_allocator_->
+                            template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1,v);
+                        }
+                        // (c0) - (v + c1) --> (cov) (c0 - c1) - v
+                        else if ((details::e_sub == o0) && (details::e_add == o1))
+                        {
+                            exprtk_debug(("(c0) - (v + c1) --> (cov) (c0 - c1) - v\n"));
+                            
+                            return expr_gen.node_allocator_->
+                            template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1,v);
+                        }
+                        // (c0) - (v - c1) --> (cov) (c0 + c1) - v
+                        else if ((details::e_sub == o0) && (details::e_sub == o1))
+                        {
+                            exprtk_debug(("(c0) - (v - c1) --> (cov) (c0 + c1) - v\n"));
+                            
+                            return expr_gen.node_allocator_->
+                            template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1,v);
+                        }
+                        // (c0) * (v * c1) --> (voc) v * (c0 * c1)
+                        else if ((details::e_mul == o0) && (details::e_mul == o1))
+                        {
+                            exprtk_debug(("(c0) * (v * c1) --> (voc) v * (c0 * c1)\n"));
+                            
+                            return expr_gen.node_allocator_->
+                            template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1,v);
+                        }
+                        // (c0) * (v / c1) --> (cov) (c0 / c1) * v
+                        else if ((details::e_mul == o0) && (details::e_div == o1))
+                        {
+                            exprtk_debug(("(c0) * (v / c1) --> (cov) (c0 / c1) * v\n"));
+                            
+                            return expr_gen.node_allocator_->
+                            template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1,v);
+                        }
+                        // (c0) / (v * c1) --> (cov) (c0 / c1) / v
+                        else if ((details::e_div == o0) && (details::e_mul == o1))
+                        {
+                            exprtk_debug(("(c0) / (v * c1) --> (cov) (c0 / c1) / v\n"));
+                            
+                            return expr_gen.node_allocator_->
+                            template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1,v);
+                        }
+                        // (c0) / (v / c1) --> (cov) (c0 * c1) / v
+                        else if ((details::e_div == o0) && (details::e_div == o1))
+                        {
+                            exprtk_debug(("(c0) / (v / c1) --> (cov) (c0 * c1) / v\n"));
+                            
+                            return expr_gen.node_allocator_->
+                            template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1,v);
+                        }
+                    }
+                    
+                    if (synthesize_sf3ext_expression::template compile<ctype,vtype,ctype>(expr_gen,id(expr_gen,o0,o1),c0,v,c1,result))
+                        return result;
+                    else if (!expr_gen.valid_operator(o0,f0))
+                        return error_node();
+                    else if (!expr_gen.valid_operator(o1,f1))
+                        return error_node();
+                    else
+                        return node_type::allocate(*(expr_gen.node_allocator_),c0,v,c1,f0,f1);
+                }
+                
+                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)");
+                }
+            };
+            
+            struct synthesize_cocov_expression0
+            {
+                typedef typename cocov_t::type0 node_type;
+                static inline expression_node_ptr process(expression_generator<Type>&, const details::operator_type&, expression_node_ptr (&)[2])
+                {
+                    // (c0 o0 c1) o1 (v) - Not possible.
+                    return error_node();
+                }
+            };
+            
+            struct synthesize_cocov_expression1
+            {
+                typedef typename cocov_t::type1 node_type;
+                typedef typename cocov_t::sf3_type sf3_type;
+                
+                static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                          const details::operator_type& operation,
+                                                          expression_node_ptr (&branch)[2])
+                {
+                    // (c0) o0 (c1 o1 v)
+                    const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]);
+                    const Type  c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
+                    const Type  c1 = cov->c();
+                    const Type&  v = cov->v();
+                    const details::operator_type o0 = operation;
+                    const details::operator_type o1 = cov->operation();
+                    
+                    binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+                    binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
+                    
+                    details::free_node(*(expr_gen.node_allocator_),branch[0]);
+                    details::free_node(*(expr_gen.node_allocator_),branch[1]);
+                    
+                    expression_node_ptr result = error_node();
+                    
+                    if (expr_gen.parser_->settings_.strength_reduction_enabled())
+                    {
+                        // (c0) + (c1 + v) --> (cov) (c0 + c1) + v
+                        if ((details::e_add == o0) && (details::e_add == o1))
+                        {
+                            exprtk_debug(("(c0) + (c1 + v) --> (cov) (c0 + c1) + v\n"));
+                            
+                            return expr_gen.node_allocator_->
+                            template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1,v);
+                        }
+                        // (c0) + (c1 - v) --> (cov) (c0 + c1) - v
+                        else if ((details::e_add == o0) && (details::e_sub == o1))
+                        {
+                            exprtk_debug(("(c0) + (c1 - v) --> (cov) (c0 + c1) - v\n"));
+                            
+                            return expr_gen.node_allocator_->
+                            template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1,v);
+                        }
+                        // (c0) - (c1 + v) --> (cov) (c0 - c1) - v
+                        else if ((details::e_sub == o0) && (details::e_add == o1))
+                        {
+                            exprtk_debug(("(c0) - (c1 + v) --> (cov) (c0 - c1) - v\n"));
+                            
+                            return expr_gen.node_allocator_->
+                            template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1,v);
+                        }
+                        // (c0) - (c1 - v) --> (cov) (c0 - c1) + v
+                        else if ((details::e_sub == o0) && (details::e_sub == o1))
+                        {
+                            exprtk_debug(("(c0) - (c1 - v) --> (cov) (c0 - c1) + v\n"));
+                            
+                            return expr_gen.node_allocator_->
+                            template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1,v);
+                        }
+                        // (c0) * (c1 * v) --> (cov) (c0 * c1) * v
+                        else if ((details::e_mul == o0) && (details::e_mul == o1))
+                        {
+                            exprtk_debug(("(c0) * (c1 * v) --> (cov) (c0 * c1) * v\n"));
+                            
+                            return expr_gen.node_allocator_->
+                            template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1,v);
+                        }
+                        // (c0) * (c1 / v) --> (cov) (c0 * c1) / v
+                        else if ((details::e_mul == o0) && (details::e_div == o1))
+                        {
+                            exprtk_debug(("(c0) * (c1 / v) --> (cov) (c0 * c1) / v\n"));
+                            
+                            return expr_gen.node_allocator_->
+                            template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1,v);
+                        }
+                        // (c0) / (c1 * v) --> (cov) (c0 / c1) / v
+                        else if ((details::e_div == o0) && (details::e_mul == o1))
+                        {
+                            exprtk_debug(("(c0) / (c1 * v) --> (cov) (c0 / c1) / v\n"));
+                            
+                            return expr_gen.node_allocator_->
+                            template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1,v);
+                        }
+                        // (c0) / (c1 / v) --> (cov) (c0 / c1) * v
+                        else if ((details::e_div == o0) && (details::e_div == o1))
+                        {
+                            exprtk_debug(("(c0) / (c1 / v) --> (cov) (c0 / c1) * v\n"));
+                            
+                            return expr_gen.node_allocator_->
+                            template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1,v);
+                        }
+                    }
+                    
+                    if (synthesize_sf3ext_expression::template compile<ctype,ctype,vtype>(expr_gen,id(expr_gen,o0,o1),c0,c1,v,result))
+                        return result;
+                    else if (!expr_gen.valid_operator(o0,f0))
+                        return error_node();
+                    else if (!expr_gen.valid_operator(o1,f1))
+                        return error_node();
+                    else
+                        return node_type::allocate(*(expr_gen.node_allocator_),c0,c1,v,f0,f1);
+                }
+                
+                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)");
+                }
+            };
+            
+            struct synthesize_vococ_expression0
+            {
+                typedef typename vococ_t::type0 node_type;
+                typedef typename vococ_t::sf3_type sf3_type;
+                
+                static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                          const details::operator_type& operation,
+                                                          expression_node_ptr (&branch)[2])
+                {
+                    // (v o0 c0) o1 (c1)
+                    const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]);
+                    const Type&  v = voc->v();
+                    const Type& c0 = voc->c();
+                    const Type& c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
+                    const details::operator_type o0 = voc->operation();
+                    const details::operator_type o1 = operation;
+                    
+                    binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+                    binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
+                    
+                    details::free_node(*(expr_gen.node_allocator_),branch[0]);
+                    details::free_node(*(expr_gen.node_allocator_),branch[1]);
+                    
+                    expression_node_ptr result = error_node();
+                    
+                    if (expr_gen.parser_->settings_.strength_reduction_enabled())
+                    {
+                        // (v + c0) + c1 --> (voc) v + (c0 + c1)
+                        if ((details::e_add == o0) && (details::e_add == o1))
+                        {
+                            exprtk_debug(("(v + c0) + c1 --> (voc) v + (c0 + c1)\n"));
+                            
+                            return expr_gen.node_allocator_->
+                            template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v,c0 + c1);
+                        }
+                        // (v + c0) - c1 --> (voc) v + (c0 - c1)
+                        else if ((details::e_add == o0) && (details::e_sub == o1))
+                        {
+                            exprtk_debug(("(v + c0) - c1 --> (voc) v + (c0 - c1)\n"));
+                            
+                            return expr_gen.node_allocator_->
+                            template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v,c0 - c1);
+                        }
+                        // (v - c0) + c1 --> (voc) v - (c0 + c1)
+                        else if ((details::e_sub == o0) && (details::e_add == o1))
+                        {
+                            exprtk_debug(("(v - c0) + c1 --> (voc) v - (c0 + c1)\n"));
+                            
+                            return expr_gen.node_allocator_->
+                            template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v,c1 - c0);
+                        }
+                        // (v - c0) - c1 --> (voc) v - (c0 + c1)
+                        else if ((details::e_sub == o0) && (details::e_sub == o1))
+                        {
+                            exprtk_debug(("(v - c0) - c1 --> (voc) v - (c0 + c1)\n"));
+                            
+                            return expr_gen.node_allocator_->
+                            template allocate_rc<typename details::voc_node<Type,details::sub_op<Type> > >(v,c0 + c1);
+                        }
+                        // (v * c0) * c1 --> (voc) v * (c0 * c1)
+                        else if ((details::e_mul == o0) && (details::e_mul == o1))
+                        {
+                            exprtk_debug(("(v * c0) * c1 --> (voc) v * (c0 * c1)\n"));
+                            
+                            return expr_gen.node_allocator_->
+                            template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v,c0 * c1);
+                        }
+                        // (v * c0) / c1 --> (voc) v * (c0 / c1)
+                        else if ((details::e_mul == o0) && (details::e_div == o1))
+                        {
+                            exprtk_debug(("(v * c0) / c1 --> (voc) v * (c0 / c1)\n"));
+                            
+                            return expr_gen.node_allocator_->
+                            template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v,c0 / c1);
+                        }
+                        // (v / c0) * c1 --> (voc) v * (c1 / c0)
+                        else if ((details::e_div == o0) && (details::e_mul == o1))
+                        {
+                            exprtk_debug(("(v / c0) * c1 --> (voc) v * (c1 / c0)\n"));
+                            
+                            return expr_gen.node_allocator_->
+                            template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v,c1 / c0);
+                        }
+                        // (v / c0) / c1 --> (voc) v / (c0 * c1)
+                        else if ((details::e_div == o0) && (details::e_div == o1))
+                        {
+                            exprtk_debug(("(v / c0) / c1 --> (voc) v / (c0 * c1)\n"));
+                            
+                            return expr_gen.node_allocator_->
+                            template allocate_rc<typename details::voc_node<Type,details::div_op<Type> > >(v,c0 * c1);
+                        }
+                        // (v ^ c0) ^ c1 --> (voc) v ^ (c0 * c1)
+                        else if ((details::e_pow == o0) && (details::e_pow == o1))
+                        {
+                            exprtk_debug(("(v ^ c0) ^ c1 --> (voc) v ^ (c0 * c1)\n"));
+                            
+                            return expr_gen.node_allocator_->
+                            template allocate_rc<typename details::voc_node<Type,details::pow_op<Type> > >(v,c0 * c1);
+                        }
+                    }
+                    
+                    if (synthesize_sf3ext_expression::template compile<vtype,ctype,ctype>(expr_gen,id(expr_gen,o0,o1),v,c0,c1,result))
+                        return result;
+                    else if (!expr_gen.valid_operator(o0,f0))
+                        return error_node();
+                    else if (!expr_gen.valid_operator(o1,f1))
+                        return error_node();
+                    else
+                        return node_type::allocate(*(expr_gen.node_allocator_),v,c0,c1,f0,f1);
+                }
+                
+                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");
+                }
+            };
+            
+            struct synthesize_vococ_expression1
+            {
+                typedef typename vococ_t::type0 node_type;
+                
+                static inline expression_node_ptr process(expression_generator<Type>&, const details::operator_type&, expression_node_ptr (&)[2])
+                {
+                    // (v) o0 (c0 o1 c1) - Not possible.
+                    exprtk_debug(("(v) o0 (c0 o1 c1) - Not possible.\n"));
+                    return error_node();
+                }
+            };
+            
+            struct synthesize_vovovov_expression0
+            {
+                typedef typename vovovov_t::type0 node_type;
+                typedef typename vovovov_t::sf4_type sf4_type;
+                typedef typename node_type::T0 T0;
+                typedef typename node_type::T1 T1;
+                typedef typename node_type::T2 T2;
+                typedef typename node_type::T3 T3;
+                
+                static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                          const details::operator_type& operation,
+                                                          expression_node_ptr (&branch)[2])
+                {
+                    // (v0 o0 v1) o1 (v2 o2 v3)
+                    const details::vov_base_node<Type>* vov0 = static_cast<details::vov_base_node<Type>*>(branch[0]);
+                    const details::vov_base_node<Type>* vov1 = static_cast<details::vov_base_node<Type>*>(branch[1]);
+                    const Type& v0 = vov0->v0();
+                    const Type& v1 = vov0->v1();
+                    const Type& v2 = vov1->v0();
+                    const Type& v3 = vov1->v1();
+                    const details::operator_type o0 = vov0->operation();
+                    const details::operator_type o1 = operation;
+                    const details::operator_type o2 = vov1->operation();
+                    
+                    binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+                    binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
+                    binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
+                    
+                    details::free_node(*(expr_gen.node_allocator_),branch[0]);
+                    details::free_node(*(expr_gen.node_allocator_),branch[1]);
+                    
+                    expression_node_ptr result = error_node();
+                    
+                    if (expr_gen.parser_->settings_.strength_reduction_enabled())
+                    {
+                        // (v0 / v1) * (v2 / v3) --> (vovovov) (v0 * v2) / (v1 * v3)
+                        if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
+                        {
+                            const bool synthesis_result =
+                            synthesize_sf4ext_expression::
+                            template compile<vtype,vtype,vtype,vtype>(expr_gen,"(t*t)/(t*t)",v0,v2,v1,v3,result);
+                            
+                            exprtk_debug(("(v0 / v1) * (v2 / v3) --> (vovovov) (v0 * v2) / (v1 * v3)\n"));
+                            
+                            return (synthesis_result) ? result : error_node();
+                        }
+                        // (v0 / v1) / (v2 / v3) --> (vovovov) (v0 * v3) / (v1 * v2)
+                        else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
+                        {
+                            const bool synthesis_result =
+                            synthesize_sf4ext_expression::
+                            template compile<vtype,vtype,vtype,vtype>(expr_gen,"(t*t)/(t*t)",v0,v3,v1,v2,result);
+                            
+                            exprtk_debug(("(v0 / v1) / (v2 / v3) --> (vovovov) (v0 * v3) / (v1 * v2)\n"));
+                            
+                            return (synthesis_result) ? result : error_node();
+                        }
+                        // (v0 + v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2)
+                        else if ((details::e_add == o0) && (details::e_div == o1) && (details::e_div == o2))
+                        {
+                            const bool synthesis_result =
+                            synthesize_sf4ext_expression::
+                            template compile<vtype,vtype,vtype,vtype>(expr_gen,"(t+t)*(t/t)",v0,v1,v3,v2,result);
+                            
+                            exprtk_debug(("(v0 + v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2)\n"));
+                            
+                            return (synthesis_result) ? result : error_node();
+                        }
+                        // (v0 - v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2)
+                        else if ((details::e_sub == o0) && (details::e_div == o1) && (details::e_div == o2))
+                        {
+                            const bool synthesis_result =
+                            synthesize_sf4ext_expression::
+                            template compile<vtype,vtype,vtype,vtype>(expr_gen,"(t-t)*(t/t)",v0,v1,v3,v2,result);
+                            
+                            exprtk_debug(("(v0 - v1) / (v2 / v3) --> (vovovov) (v0 - v1) * (v3 / v2)\n"));
+                            
+                            return (synthesis_result) ? result : error_node();
+                        }
+                        // (v0 * v1) / (v2 / v3) --> (vovovov) ((v0 * v1) * v3) / v2
+                        else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
+                        {
+                            const bool synthesis_result =
+                            synthesize_sf4ext_expression::
+                            template compile<vtype,vtype,vtype,vtype>(expr_gen,"((t*t)*t)/t",v0,v1,v3,v2,result);
+                            
+                            exprtk_debug(("(v0 * v1) / (v2 / v3) --> (vovovov) ((v0 * v1) * v3) / v2\n"));
+                            
+                            return (synthesis_result) ? result : error_node();
+                        }
+                    }
+                    
+                    if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,v3,result))
+                        return result;
+                    else if (!expr_gen.valid_operator(o0,f0))
+                        return error_node();
+                    else if (!expr_gen.valid_operator(o1,f1))
+                        return error_node();
+                    else if (!expr_gen.valid_operator(o2,f2))
+                        return error_node();
+                    else
+                        return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,v3,f0,f1,f2);
+                }
+                
+                static inline std::string id(expression_generator<Type>& expr_gen,
+                                             const details::operator_type o0,
+                                             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)");
+                }
+            };
+            
+            struct synthesize_vovovoc_expression0
+            {
+                typedef typename vovovoc_t::type0 node_type;
+                typedef typename vovovoc_t::sf4_type sf4_type;
+                typedef typename node_type::T0 T0;
+                typedef typename node_type::T1 T1;
+                typedef typename node_type::T2 T2;
+                typedef typename node_type::T3 T3;
+                
+                static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                          const details::operator_type& operation,
+                                                          expression_node_ptr (&branch)[2])
+                {
+                    // (v0 o0 v1) o1 (v2 o2 c)
+                    const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]);
+                    const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]);
+                    const Type& v0 = vov->v0();
+                    const Type& v1 = vov->v1();
+                    const Type& v2 = voc->v ();
+                    const Type   c = voc->c ();
+                    const details::operator_type o0 = vov->operation();
+                    const details::operator_type o1 = operation;
+                    const details::operator_type o2 = voc->operation();
+                    
+                    binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+                    binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
+                    binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
+                    
+                    details::free_node(*(expr_gen.node_allocator_),branch[0]);
+                    details::free_node(*(expr_gen.node_allocator_),branch[1]);
+                    
+                    expression_node_ptr result = error_node();
+                    
+                    if (expr_gen.parser_->settings_.strength_reduction_enabled())
+                    {
+                        // (v0 / v1) * (v2 / c) --> (vovovoc) (v0 * v2) / (v1 * c)
+                        if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
+                        {
+                            const bool synthesis_result =
+                            synthesize_sf4ext_expression::
+                            template compile<vtype,vtype,vtype,ctype>(expr_gen,"(t*t)/(t*t)",v0,v2,v1,c,result);
+                            
+                            exprtk_debug(("(v0 / v1) * (v2 / c) --> (vovovoc) (v0 * v2) / (v1 * c)\n"));
+                            
+                            return (synthesis_result) ? result : error_node();
+                        }
+                        // (v0 / v1) / (v2 / c) --> (vocovov) (v0 * c) / (v1 * v2)
+                        if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
+                        {
+                            const bool synthesis_result =
+                            synthesize_sf4ext_expression::
+                            template compile<vtype,ctype,vtype,vtype>(expr_gen,"(t*t)/(t*t)",v0,c,v1,v2,result);
+                            
+                            exprtk_debug(("(v0 / v1) / (v2 / c) --> (vocovov) (v0 * c) / (v1 * v2)\n"));
+                            
+                            return (synthesis_result) ? result : error_node();
+                        }
+                    }
+                    
+                    if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,c,result))
+                        return result;
+                    else if (!expr_gen.valid_operator(o0,f0))
+                        return error_node();
+                    else if (!expr_gen.valid_operator(o1,f1))
+                        return error_node();
+                    else if (!expr_gen.valid_operator(o2,f2))
+                        return error_node();
+                    else
+                        return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,c,f0,f1,f2);
+                }
+                
+                static inline std::string id(expression_generator<Type>& expr_gen,
+                                             const details::operator_type o0,
+                                             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)");
+                }
+            };
+            
+            struct synthesize_vovocov_expression0
+            {
+                typedef typename vovocov_t::type0 node_type;
+                typedef typename vovocov_t::sf4_type sf4_type;
+                typedef typename node_type::T0 T0;
+                typedef typename node_type::T1 T1;
+                typedef typename node_type::T2 T2;
+                typedef typename node_type::T3 T3;
+                
+                static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                          const details::operator_type& operation,
+                                                          expression_node_ptr (&branch)[2])
+                {
+                    // (v0 o0 v1) o1 (c o2 v2)
+                    const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]);
+                    const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]);
+                    const Type& v0 = vov->v0();
+                    const Type& v1 = vov->v1();
+                    const Type& v2 = cov->v ();
+                    const Type   c = cov->c ();
+                    const details::operator_type o0 = vov->operation();
+                    const details::operator_type o1 = operation;
+                    const details::operator_type o2 = cov->operation();
+                    
+                    binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+                    binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
+                    binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
+                    
+                    details::free_node(*(expr_gen.node_allocator_),branch[0]);
+                    details::free_node(*(expr_gen.node_allocator_),branch[1]);
+                    
+                    expression_node_ptr result = error_node();
+                    
+                    if (expr_gen.parser_->settings_.strength_reduction_enabled())
+                    {
+                        // (v0 / v1) * (c / v2) --> (vocovov) (v0 * c) / (v1 * v2)
+                        if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
+                        {
+                            const bool synthesis_result =
+                            synthesize_sf4ext_expression::
+                            template compile<vtype,ctype,vtype,vtype>(expr_gen,"(t*t)/(t*t)",v0,c,v1,v2,result);
+                            
+                            exprtk_debug(("(v0 / v1) * (c / v2) --> (vocovov) (v0 * c) / (v1 * v2)\n"));
+                            
+                            return (synthesis_result) ? result : error_node();
+                        }
+                        // (v0 / v1) / (c / v2) --> (vovovoc) (v0 * v2) / (v1 * c)
+                        if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
+                        {
+                            const bool synthesis_result =
+                            synthesize_sf4ext_expression::
+                            template compile<vtype,vtype,vtype,ctype>(expr_gen,"(t*t)/(t*t)",v0,v2,v1,c,result);
+                            
+                            exprtk_debug(("(v0 / v1) / (c / v2) --> (vovovoc) (v0 * v2) / (v1 * c)\n"));
+                            
+                            return (synthesis_result) ? result : error_node();
+                        }
+                    }
+                    
+                    if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,c,v2,result))
+                        return result;
+                    else if (!expr_gen.valid_operator(o0,f0))
+                        return error_node();
+                    else if (!expr_gen.valid_operator(o1,f1))
+                        return error_node();
+                    else if (!expr_gen.valid_operator(o2,f2))
+                        return error_node();
+                    else
+                        return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,c,v2,f0,f1,f2);
+                }
+                
+                static inline std::string id(expression_generator<Type>& expr_gen,
+                                             const details::operator_type o0,
+                                             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)");
+                }
+            };
+            
+            struct synthesize_vocovov_expression0
+            {
+                typedef typename vocovov_t::type0 node_type;
+                typedef typename vocovov_t::sf4_type sf4_type;
+                typedef typename node_type::T0 T0;
+                typedef typename node_type::T1 T1;
+                typedef typename node_type::T2 T2;
+                typedef typename node_type::T3 T3;
+                
+                static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                          const details::operator_type& operation,
+                                                          expression_node_ptr (&branch)[2])
+                {
+                    // (v0 o0 c) o1 (v1 o2 v2)
+                    const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]);
+                    const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]);
+                    const Type   c = voc->c ();
+                    const Type& v0 = voc->v ();
+                    const Type& v1 = vov->v0();
+                    const Type& v2 = vov->v1();
+                    const details::operator_type o0 = voc->operation();
+                    const details::operator_type o1 = operation;
+                    const details::operator_type o2 = vov->operation();
+                    
+                    binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+                    binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
+                    binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
+                    
+                    details::free_node(*(expr_gen.node_allocator_),branch[0]);
+                    details::free_node(*(expr_gen.node_allocator_),branch[1]);
+                    
+                    expression_node_ptr result = error_node();
+                    
+                    if (expr_gen.parser_->settings_.strength_reduction_enabled())
+                    {
+                        // (v0 / c) * (v1 / v2) --> (vovocov) (v0 * v1) / (c * v2)
+                        if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
+                        {
+                            const bool synthesis_result =
+                            synthesize_sf4ext_expression::
+                            template compile<vtype,vtype,ctype,vtype>(expr_gen,"(t*t)/(t*t)",v0,v1,c,v2,result);
+                            
+                            exprtk_debug(("(v0 / c) * (v1 / v2) --> (vovocov) (v0 * v1) / (c * v2)\n"));
+                            
+                            return (synthesis_result) ? result : error_node();
+                        }
+                        // (v0 / c) / (v1 / v2) --> (vovocov) (v0 * v2) / (c * v1)
+                        if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
+                        {
+                            const bool synthesis_result =
+                            synthesize_sf4ext_expression::
+                            template compile<vtype,vtype,ctype,vtype>(expr_gen,"(t*t)/(t*t)",v0,v2,c,v1,result);
+                            
+                            exprtk_debug(("(v0 / c) / (v1 / v2) --> (vovocov) (v0 * v2) / (c * v1)\n"));
+                            
+                            return (synthesis_result) ? result : error_node();
+                        }
+                    }
+                    
+                    if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c,v1,v2,result))
+                        return result;
+                    else if (!expr_gen.valid_operator(o0,f0))
+                        return error_node();
+                    else if (!expr_gen.valid_operator(o1,f1))
+                        return error_node();
+                    else if (!expr_gen.valid_operator(o2,f2))
+                        return error_node();
+                    else
+                        return node_type::allocate(*(expr_gen.node_allocator_),v0,c,v1,v2,f0,f1,f2);
+                }
+                
+                static inline std::string id(expression_generator<Type>& expr_gen,
+                                             const details::operator_type o0,
+                                             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)");
+                }
+            };
+            
+            struct synthesize_covovov_expression0
+            {
+                typedef typename covovov_t::type0 node_type;
+                typedef typename covovov_t::sf4_type sf4_type;
+                typedef typename node_type::T0 T0;
+                typedef typename node_type::T1 T1;
+                typedef typename node_type::T2 T2;
+                typedef typename node_type::T3 T3;
+                
+                static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                          const details::operator_type& operation,
+                                                          expression_node_ptr (&branch)[2])
+                {
+                    // (c o0 v0) o1 (v1 o2 v2)
+                    const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]);
+                    const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]);
+                    const Type   c = cov->c ();
+                    const Type& v0 = cov->v ();
+                    const Type& v1 = vov->v0();
+                    const Type& v2 = vov->v1();
+                    const details::operator_type o0 = cov->operation();
+                    const details::operator_type o1 = operation;
+                    const details::operator_type o2 = vov->operation();
+                    
+                    binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+                    binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
+                    binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
+                    
+                    details::free_node(*(expr_gen.node_allocator_),branch[0]);
+                    details::free_node(*(expr_gen.node_allocator_),branch[1]);
+                    
+                    expression_node_ptr result = error_node();
+                    
+                    if (expr_gen.parser_->settings_.strength_reduction_enabled())
+                    {
+                        // (c / v0) * (v1 / v2) --> (covovov) (c * v1) / (v0 * v2)
+                        if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
+                        {
+                            const bool synthesis_result =
+                            synthesize_sf4ext_expression::
+                            template compile<ctype,vtype,vtype,vtype>(expr_gen,"(t*t)/(t*t)",c,v1,v0,v2,result);
+                            
+                            exprtk_debug(("(c / v0) * (v1 / v2) --> (covovov) (c * v1) / (v0 * v2)\n"));
+                            
+                            return (synthesis_result) ? result : error_node();
+                        }
+                        // (c / v0) / (v1 / v2) --> (covovov) (c * v2) / (v0 * v1)
+                        if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
+                        {
+                            const bool synthesis_result =
+                            synthesize_sf4ext_expression::
+                            template compile<ctype,vtype,vtype,vtype>(expr_gen,"(t*t)/(t*t)",c,v2,v0,v1,result);
+                            
+                            exprtk_debug(("(c / v0) / (v1 / v2) --> (covovov) (c * v2) / (v0 * v1)\n"));
+                            
+                            return (synthesis_result) ? result : error_node();
+                        }
+                    }
+                    
+                    if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c,v0,v1,v2,result))
+                        return result;
+                    else if (!expr_gen.valid_operator(o0,f0))
+                        return error_node();
+                    else if (!expr_gen.valid_operator(o1,f1))
+                        return error_node();
+                    else if (!expr_gen.valid_operator(o2,f2))
+                        return error_node();
+                    else
+                        return node_type::allocate(*(expr_gen.node_allocator_),c,v0,v1,v2,f0,f1,f2);
+                }
+                
+                static inline std::string id(expression_generator<Type>& expr_gen,
+                                             const details::operator_type o0,
+                                             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)");
+                }
+            };
+            
+            struct synthesize_covocov_expression0
+            {
+                typedef typename covocov_t::type0 node_type;
+                typedef typename covocov_t::sf4_type sf4_type;
+                typedef typename node_type::T0 T0;
+                typedef typename node_type::T1 T1;
+                typedef typename node_type::T2 T2;
+                typedef typename node_type::T3 T3;
+                
+                static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                          const details::operator_type& operation,
+                                                          expression_node_ptr (&branch)[2])
+                {
+                    // (c0 o0 v0) o1 (c1 o2 v1)
+                    const details::cov_base_node<Type>* cov0 = static_cast<details::cov_base_node<Type>*>(branch[0]);
+                    const details::cov_base_node<Type>* cov1 = static_cast<details::cov_base_node<Type>*>(branch[1]);
+                    const Type  c0 = cov0->c();
+                    const Type& v0 = cov0->v();
+                    const Type  c1 = cov1->c();
+                    const Type& v1 = cov1->v();
+                    const details::operator_type o0 = cov0->operation();
+                    const details::operator_type o1 = operation;
+                    const details::operator_type o2 = cov1->operation();
+                    
+                    binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+                    binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
+                    binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
+                    
+                    details::free_node(*(expr_gen.node_allocator_),branch[0]);
+                    details::free_node(*(expr_gen.node_allocator_),branch[1]);
+                    
+                    expression_node_ptr result = error_node();
+                    
+                    if (expr_gen.parser_->settings_.strength_reduction_enabled())
+                    {
+                        // (c0 + v0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1
+                        if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2))
+                        {
+                            const bool synthesis_result =
+                            synthesize_sf3ext_expression::
+                            template compile<ctype,vtype,vtype>(expr_gen,"(t+t)+t",(c0 + c1),v0,v1,result);
+                            
+                            exprtk_debug(("(c0 + v0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1\n"));
+                            
+                            return (synthesis_result) ? result : error_node();
+                        }
+                        // (c0 + v0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1
+                        else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2))
+                        {
+                            const bool synthesis_result =
+                            synthesize_sf3ext_expression::
+                            template compile<ctype,vtype,vtype>(expr_gen,"(t+t)-t",(c0 - c1),v0,v1,result);
+                            
+                            exprtk_debug(("(c0 + v0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1\n"));
+                            
+                            return (synthesis_result) ? result : error_node();
+                        }
+                        // (c0 - v0) - (c1 - v1) --> (covov) (c0 - c1) - v0 + v1
+                        else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2))
+                        {
+                            const bool synthesis_result =
+                            synthesize_sf3ext_expression::
+                            template compile<ctype,vtype,vtype>(expr_gen,"(t-t)+t",(c0 - c1),v0,v1,result);
+                            
+                            exprtk_debug(("(c0 - v0) - (c1 - v1) --> (covov) (c0 - c1) - v0 + v1\n"));
+                            
+                            return (synthesis_result) ? result : error_node();
+                        }
+                        // (c0 * v0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1
+                        else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
+                        {
+                            const bool synthesis_result =
+                            synthesize_sf3ext_expression::
+                            template compile<ctype,vtype,vtype>(expr_gen,"(t*t)*t",(c0 * c1),v0,v1,result);
+                            
+                            exprtk_debug(("(c0 * v0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1\n"));
+                            
+                            return (synthesis_result) ? result : error_node();
+                        }
+                        // (c0 * v0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 / v1)
+                        else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
+                        {
+                            const bool synthesis_result =
+                            synthesize_sf3ext_expression::
+                            template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",(c0 / c1),v0,v1,result);
+                            
+                            exprtk_debug(("(c0 * v0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 / v1)\n"));
+                            
+                            return (synthesis_result) ? result : error_node();
+                        }
+                        // (c0 / v0) * (c1 / v1) --> (covov) (c0 * c1) / (v0 * v1)
+                        else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
+                        {
+                            const bool synthesis_result =
+                            synthesize_sf3ext_expression::
+                            template compile<ctype,vtype,vtype>(expr_gen,"t/(t*t)",(c0 * c1),v0,v1,result);
+                            
+                            exprtk_debug(("(c0 / v0) * (c1 / v1) --> (covov) (c0 * c1) / (v0 * v1)\n"));
+                            
+                            return (synthesis_result) ? result : error_node();
+                        }
+                        // (c0 / v0) / (c1 / v1) --> (covov) ((c0 / c1) * v1) / v0
+                        else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
+                        {
+                            const bool synthesis_result =
+                            synthesize_sf3ext_expression::
+                            template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",(c0 / c1),v1,v0,result);
+                            
+                            exprtk_debug(("(c0 / v0) / (c1 / v1) --> (covov) ((c0 / c1) * v1) / v0\n"));
+                            
+                            return (synthesis_result) ? result : error_node();
+                        }
+                        // (c0 * v0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)
+                        else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
+                        {
+                            const bool synthesis_result =
+                            synthesize_sf3ext_expression::
+                            template compile<ctype,vtype,vtype>(expr_gen,"t*(t*t)",(c0 / c1),v0,v1,result);
+                            
+                            exprtk_debug(("(c0 * v0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)\n"));
+                            
+                            return (synthesis_result) ? result : error_node();
+                        }
+                        // (c0 / v0) / (c1 * v1) --> (covov) (c0 / c1) / (v0 * v1)
+                        else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))
+                        {
+                            const bool synthesis_result =
+                            synthesize_sf3ext_expression::
+                            template compile<ctype,vtype,vtype>(expr_gen,"t/(t*t)",(c0 / c1),v0,v1,result);
+                            
+                            exprtk_debug(("(c0 / v0) / (c1 * v1) --> (covov) (c0 / c1) / (v0 * v1)\n"));
+                            
+                            return (synthesis_result) ? result : error_node();
+                        }
+                        // (c * v0) +/- (c * v1) --> (covov) c * (v0 +/- v1)
+                        else if (
+                                 (std::equal_to<T>()(c0,c1)) &&
+                                 (details::e_mul == o0)      &&
+                                 (details::e_mul == o2)      &&
+                                 (
+                                  (details::e_add == o1) ||
+                                  (details::e_sub == o1)
+                                  )
+                                 )
+                        {
+                            std::string specfunc;
+                            
+                            switch (o1)
+                            {
+                                case details::e_add : specfunc = "t*(t+t)"; break;
+                                case details::e_sub : specfunc = "t*(t-t)"; break;
+                                default             : return error_node();
+                            }
+                            
+                            const bool synthesis_result =
+                            synthesize_sf3ext_expression::
+                            template compile<ctype,vtype,vtype>(expr_gen,specfunc,c0,v0,v1,result);
+                            
+                            exprtk_debug(("(c * v0) +/- (c * v1) --> (covov) c * (v0 +/- v1)\n"));
+                            
+                            return (synthesis_result) ? result : error_node();
+                        }
+                    }
+                    
+                    if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,c1,v1,result))
+                        return result;
+                    else if (!expr_gen.valid_operator(o0,f0))
+                        return error_node();
+                    else if (!expr_gen.valid_operator(o1,f1))
+                        return error_node();
+                    else if (!expr_gen.valid_operator(o2,f2))
+                        return error_node();
+                    else
+                        return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,c1,v1,f0,f1,f2);
+                }
+                
+                static inline std::string id(expression_generator<Type>& expr_gen,
+                                             const details::operator_type o0,
+                                             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)");
+                }
+            };
+            
+            struct synthesize_vocovoc_expression0
+            {
+                typedef typename vocovoc_t::type0 node_type;
+                typedef typename vocovoc_t::sf4_type sf4_type;
+                typedef typename node_type::T0 T0;
+                typedef typename node_type::T1 T1;
+                typedef typename node_type::T2 T2;
+                typedef typename node_type::T3 T3;
+                
+                static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                          const details::operator_type& operation,
+                                                          expression_node_ptr (&branch)[2])
+                {
+                    // (v0 o0 c0) o1 (v1 o2 c1)
+                    const details::voc_base_node<Type>* voc0 = static_cast<details::voc_base_node<Type>*>(branch[0]);
+                    const details::voc_base_node<Type>* voc1 = static_cast<details::voc_base_node<Type>*>(branch[1]);
+                    const Type  c0 = voc0->c();
+                    const Type& v0 = voc0->v();
+                    const Type  c1 = voc1->c();
+                    const Type& v1 = voc1->v();
+                    const details::operator_type o0 = voc0->operation();
+                    const details::operator_type o1 = operation;
+                    const details::operator_type o2 = voc1->operation();
+                    
+                    binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+                    binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
+                    binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
+                    
+                    details::free_node(*(expr_gen.node_allocator_),branch[0]);
+                    details::free_node(*(expr_gen.node_allocator_),branch[1]);
+                    
+                    expression_node_ptr result = error_node();
+                    
+                    if (expr_gen.parser_->settings_.strength_reduction_enabled())
+                    {
+                        // (v0 + c0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1
+                        if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2))
+                        {
+                            const bool synthesis_result =
+                            synthesize_sf3ext_expression::
+                            template compile<ctype,vtype,vtype>(expr_gen,"(t+t)+t",(c0 + c1),v0,v1,result);
+                            
+                            exprtk_debug(("(v0 + c0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1\n"));
+                            
+                            return (synthesis_result) ? result : error_node();
+                        }
+                        // (v0 + c0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1
+                        else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2))
+                        {
+                            const bool synthesis_result =
+                            synthesize_sf3ext_expression::
+                            template compile<ctype,vtype,vtype>(expr_gen,"(t+t)-t",(c0 - c1),v0,v1,result);
+                            
+                            exprtk_debug(("(v0 + c0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1\n"));
+                            
+                            return (synthesis_result) ? result : error_node();
+                        }
+                        // (v0 - c0) - (v1 - c1) --> (covov) (c1 - c0) + v0 - v1
+                        else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2))
+                        {
+                            const bool synthesis_result =
+                            synthesize_sf3ext_expression::
+                            template compile<ctype,vtype,vtype>(expr_gen,"(t+t)-t",(c1 - c0),v0,v1,result);
+                            
+                            exprtk_debug(("(v0 - c0) - (v1 - c1) --> (covov) (c1 - c0) + v0 - v1\n"));
+                            
+                            return (synthesis_result) ? result : error_node();
+                        }
+                        // (v0 * c0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1
+                        else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
+                        {
+                            const bool synthesis_result =
+                            synthesize_sf3ext_expression::
+                            template compile<ctype,vtype,vtype>(expr_gen,"(t*t)*t",(c0 * c1),v0,v1,result);
+                            
+                            exprtk_debug(("(v0 * c0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1\n"));
+                            
+                            return (synthesis_result) ? result : error_node();
+                        }
+                        // (v0 * c0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)
+                        else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
+                        {
+                            const bool synthesis_result =
+                            synthesize_sf3ext_expression::
+                            template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",(c0 / c1),v0,v1,result);
+                            
+                            exprtk_debug(("(v0 * c0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)\n"));
+                            
+                            return (synthesis_result) ? result : error_node();
+                        }
+                        // (v0 / c0) * (v1 / c1) --> (covov) (1 / (c0 * c1)) * v0 * v1
+                        else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
+                        {
+                            const bool synthesis_result =
+                            synthesize_sf3ext_expression::
+                            template compile<ctype,vtype,vtype>(expr_gen,"(t*t)*t",Type(1) / (c0 * c1),v0,v1,result);
+                            
+                            exprtk_debug(("(v0 / c0) * (v1 / c1) --> (covov) (1 / (c0 * c1)) * v0 * v1\n"));
+                            
+                            return (synthesis_result) ? result : error_node();
+                        }
+                        // (v0 / c0) / (v1 / c1) --> (covov) ((c1 / c0) * v0) / v1
+                        else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
+                        {
+                            const bool synthesis_result =
+                            synthesize_sf3ext_expression::
+                            template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",(c1 / c0),v0,v1,result);
+                            
+                            exprtk_debug(("(v0 / c0) / (v1 / c1) --> (covov) ((c1 / c0) * v0) / v1\n"));
+                            
+                            return (synthesis_result) ? result : error_node();
+                        }
+                        // (v0 * c0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)
+                        else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
+                        {
+                            const bool synthesis_result =
+                            synthesize_sf3ext_expression::
+                            template compile<ctype,vtype,vtype>(expr_gen,"t*(t/t)",(c0 * c1),v0,v1,result);
+                            
+                            exprtk_debug(("(v0 * c0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)\n"));
+                            
+                            return (synthesis_result) ? result : error_node();
+                        }
+                        // (v0 / c0) / (v1 * c1) --> (covov) (1 / (c0 * c1)) * v0 / v1
+                        else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))
+                        {
+                            const bool synthesis_result =
+                            synthesize_sf3ext_expression::
+                            template compile<ctype,vtype,vtype>(expr_gen,"t*(t/t)",Type(1) / (c0 * c1),v0,v1,result);
+                            
+                            exprtk_debug(("(v0 / c0) / (v1 * c1) --> (covov) (1 / (c0 * c1)) * v0 / v1\n"));
+                            
+                            return (synthesis_result) ? result : error_node();
+                        }
+                        // (v0 / c0) * (v1 + c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 + c1)
+                        else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_add == o2))
+                        {
+                            const bool synthesis_result =
+                            synthesize_sf4ext_expression::
+                            template compile<vtype,ctype,vtype,ctype>(expr_gen,"(t*t)*(t+t)",v0,T(1) / c0,v1,c1,result);
+                            
+                            exprtk_debug(("(v0 / c0) * (v1 + c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 + c1)\n"));
+                            
+                            return (synthesis_result) ? result : error_node();
+                        }
+                        // (v0 / c0) * (v1 - c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 - c1)
+                        else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_sub == o2))
+                        {
+                            const bool synthesis_result =
+                            synthesize_sf4ext_expression::
+                            template compile<vtype,ctype,vtype,ctype>(expr_gen,"(t*t)*(t-t)",v0,T(1) / c0,v1,c1,result);
+                            
+                            exprtk_debug(("(v0 / c0) * (v1 - c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 - c1)\n"));
+                            
+                            return (synthesis_result) ? result : error_node();
+                        }
+                        // (v0 * c) +/- (v1 * c) --> (covov) c * (v0 +/- v1)
+                        else if (
+                                 (std::equal_to<T>()(c0,c1)) &&
+                                 (details::e_mul == o0)      &&
+                                 (details::e_mul == o2)      &&
+                                 (
+                                  (details::e_add == o1) ||
+                                  (details::e_sub == o1)
+                                  )
+                                 )
+                        {
+                            std::string specfunc;
+                            
+                            switch (o1)
+                            {
+                                case details::e_add : specfunc = "t*(t+t)"; break;
+                                case details::e_sub : specfunc = "t*(t-t)"; break;
+                                default             : return error_node();
+                            }
+                            
+                            const bool synthesis_result =
+                            synthesize_sf3ext_expression::
+                            template compile<ctype,vtype,vtype>(expr_gen,specfunc,c0,v0,v1,result);
+                            
+                            exprtk_debug(("(v0 * c) +/- (v1 * c) --> (covov) c * (v0 +/- v1)\n"));
+                            
+                            return (synthesis_result) ? result : error_node();
+                        }
+                        // (v0 / c) +/- (v1 / c) --> (vovoc) (v0 +/- v1) / c
+                        else if (
+                                 (std::equal_to<T>()(c0,c1)) &&
+                                 (details::e_div == o0)      &&
+                                 (details::e_div == o2)      &&
+                                 (
+                                  (details::e_add == o1) ||
+                                  (details::e_sub == o1)
+                                  )
+                                 )
+                        {
+                            std::string specfunc;
+                            
+                            switch (o1)
+                            {
+                                case details::e_add : specfunc = "(t+t)/t"; break;
+                                case details::e_sub : specfunc = "(t-t)/t"; break;
+                                default             : return error_node();
+                            }
+                            
+                            const bool synthesis_result =
+                            synthesize_sf3ext_expression::
+                            template compile<vtype,vtype,ctype>(expr_gen,specfunc,v0,v1,c0,result);
+                            
+                            exprtk_debug(("(v0 / c) +/- (v1 / c) --> (vovoc) (v0 +/- v1) / c\n"));
+                            
+                            return (synthesis_result) ? result : error_node();
+                        }
+                    }
+                    
+                    if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c0,v1,c1,result))
+                        return result;
+                    else if (!expr_gen.valid_operator(o0,f0))
+                        return error_node();
+                    else if (!expr_gen.valid_operator(o1,f1))
+                        return error_node();
+                    else if (!expr_gen.valid_operator(o2,f2))
+                        return error_node();
+                    else
+                        return node_type::allocate(*(expr_gen.node_allocator_),v0,c0,v1,c1,f0,f1,f2);
+                }
+                
+                static inline std::string id(expression_generator<Type>& expr_gen,
+                                             const details::operator_type o0,
+                                             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)");
+                }
+            };
+            
+            struct synthesize_covovoc_expression0
+            {
+                typedef typename covovoc_t::type0 node_type;
+                typedef typename covovoc_t::sf4_type sf4_type;
+                typedef typename node_type::T0 T0;
+                typedef typename node_type::T1 T1;
+                typedef typename node_type::T2 T2;
+                typedef typename node_type::T3 T3;
+                
+                static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                          const details::operator_type& operation,
+                                                          expression_node_ptr (&branch)[2])
+                {
+                    // (c0 o0 v0) o1 (v1 o2 c1)
+                    const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]);
+                    const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]);
+                    const Type  c0 = cov->c();
+                    const Type& v0 = cov->v();
+                    const Type  c1 = voc->c();
+                    const Type& v1 = voc->v();
+                    const details::operator_type o0 = cov->operation();
+                    const details::operator_type o1 = operation;
+                    const details::operator_type o2 = voc->operation();
+                    
+                    binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+                    binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
+                    binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
+                    
+                    details::free_node(*(expr_gen.node_allocator_),branch[0]);
+                    details::free_node(*(expr_gen.node_allocator_),branch[1]);
+                    
+                    expression_node_ptr result = error_node();
+                    
+                    if (expr_gen.parser_->settings_.strength_reduction_enabled())
+                    {
+                        // (c0 + v0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1
+                        if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2))
+                        {
+                            const bool synthesis_result =
+                            synthesize_sf3ext_expression::
+                            template compile<ctype,vtype,vtype>(expr_gen,"(t+t)+t",(c0 + c1),v0,v1,result);
+                            
+                            exprtk_debug(("(c0 + v0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1\n"));
+                            
+                            return (synthesis_result) ? result : error_node();
+                        }
+                        // (c0 + v0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1
+                        else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2))
+                        {
+                            const bool synthesis_result =
+                            synthesize_sf3ext_expression::
+                            template compile<ctype,vtype,vtype>(expr_gen,"(t+t)-t",(c0 - c1),v0,v1,result);
+                            
+                            exprtk_debug(("(c0 + v0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1\n"));
+                            
+                            return (synthesis_result) ? result : error_node();
+                        }
+                        // (c0 - v0) - (v1 - c1) --> (covov) (c0 + c1) - v0 - v1
+                        else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2))
+                        {
+                            const bool synthesis_result =
+                            synthesize_sf3ext_expression::
+                            template compile<ctype,vtype,vtype>(expr_gen,"t-(t+t)",(c0 + c1),v0,v1,result);
+                            
+                            exprtk_debug(("(c0 - v0) - (v1 - c1) --> (covov) (c0 + c1) - v0 - v1\n"));
+                            
+                            return (synthesis_result) ? result : error_node();
+                        }
+                        // (c0 * v0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1
+                        else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
+                        {
+                            const bool synthesis_result =
+                            synthesize_sf3ext_expression::
+                            template compile<ctype,vtype,vtype>(expr_gen,"(t*t)*t",(c0 * c1),v0,v1,result);
+                            
+                            exprtk_debug(("(c0 * v0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1\n"));
+                            
+                            return (synthesis_result) ? result : error_node();
+                        }
+                        // (c0 * v0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)
+                        else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
+                        {
+                            const bool synthesis_result =
+                            synthesize_sf3ext_expression::
+                            template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",(c0 / c1),v0,v1,result);
+                            
+                            exprtk_debug(("(c0 * v0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)\n"));
+                            
+                            return (synthesis_result) ? result : error_node();
+                        }
+                        // (c0 / v0) * (v1 / c1) --> (covov) (c0 / c1) * (v1 / v0)
+                        else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
+                        {
+                            const bool synthesis_result =
+                            synthesize_sf3ext_expression::
+                            template compile<ctype,vtype,vtype>(expr_gen,"t*(t/t)",(c0 / c1),v1,v0,result);
+                            
+                            exprtk_debug(("(c0 / v0) * (v1 / c1) --> (covov) (c0 / c1) * (v1 / v0)\n"));
+                            
+                            return (synthesis_result) ? result : error_node();
+                        }
+                        // (c0 / v0) / (v1 / c1) --> (covov) (c0 * c1) / (v0 * v1)
+                        else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
+                        {
+                            const bool synthesis_result =
+                            synthesize_sf3ext_expression::
+                            template compile<ctype,vtype,vtype>(expr_gen,"t/(t*t)",(c0 * c1),v0,v1,result);
+                            
+                            exprtk_debug(("(c0 / v0) / (v1 / c1) --> (covov) (c0 * c1) / (v0 * v1)\n"));
+                            
+                            return (synthesis_result) ? result : error_node();
+                        }
+                        // (c0 * v0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)
+                        else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
+                        {
+                            const bool synthesis_result =
+                            synthesize_sf3ext_expression::
+                            template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",(c0 * c1),v0,v1,result);
+                            
+                            exprtk_debug(("(c0 * v0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)\n"));
+                            
+                            return (synthesis_result) ? result : error_node();
+                        }
+                        // (c0 / v0) / (v1 * c1) --> (covov) (c0 / c1) / (v0 * v1)
+                        else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))
+                        {
+                            const bool synthesis_result =
+                            synthesize_sf3ext_expression::
+                            template compile<ctype,vtype,vtype>(expr_gen,"t/(t*t)",(c0 / c1),v0,v1,result);
+                            
+                            exprtk_debug(("(c0 / v0) / (v1 * c1) --> (covov) (c0 / c1) / (v0 * v1)\n"));
+                            
+                            return (synthesis_result) ? result : error_node();
+                        }
+                        // (c * v0) +/- (v1 * c) --> (covov) c * (v0 +/- v1)
+                        else if (
+                                 (std::equal_to<T>()(c0,c1)) &&
+                                 (details::e_mul == o0)      &&
+                                 (details::e_mul == o2)      &&
+                                 (
+                                  (details::e_add == o1) ||
+                                  (details::e_sub == o1)
+                                  )
+                                 )
+                        {
+                            std::string specfunc;
+                            
+                            switch (o1)
+                            {
+                                case details::e_add : specfunc = "t*(t+t)"; break;
+                                case details::e_sub : specfunc = "t*(t-t)"; break;
+                                default             : return error_node();
+                            }
+                            
+                            const bool synthesis_result =
+                            synthesize_sf3ext_expression::
+                            template compile<ctype,vtype,vtype>(expr_gen,specfunc,c0,v0,v1,result);
+                            
+                            exprtk_debug(("(c * v0) +/- (v1 * c) --> (covov) c * (v0 +/- v1)\n"));
+                            
+                            return (synthesis_result) ? result : error_node();
+                        }
+                    }
+                    
+                    if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,v1,c1,result))
+                        return result;
+                    else if (!expr_gen.valid_operator(o0,f0))
+                        return error_node();
+                    else if (!expr_gen.valid_operator(o1,f1))
+                        return error_node();
+                    else if (!expr_gen.valid_operator(o2,f2))
+                        return error_node();
+                    else
+                        return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,v1,c1,f0,f1,f2);
+                }
+                
+                static inline std::string id(expression_generator<Type>& expr_gen,
+                                             const details::operator_type o0,
+                                             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)");
+                }
+            };
+            
+            struct synthesize_vococov_expression0
+            {
+                typedef typename vococov_t::type0 node_type;
+                typedef typename vococov_t::sf4_type sf4_type;
+                typedef typename node_type::T0 T0;
+                typedef typename node_type::T1 T1;
+                typedef typename node_type::T2 T2;
+                typedef typename node_type::T3 T3;
+                
+                static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                          const details::operator_type& operation,
+                                                          expression_node_ptr (&branch)[2])
+                {
+                    // (v0 o0 c0) o1 (c1 o2 v1)
+                    const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]);
+                    const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]);
+                    const Type  c0 = voc->c();
+                    const Type& v0 = voc->v();
+                    const Type  c1 = cov->c();
+                    const Type& v1 = cov->v();
+                    const details::operator_type o0 = voc->operation();
+                    const details::operator_type o1 = operation;
+                    const details::operator_type o2 = cov->operation();
+                    
+                    binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+                    binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
+                    binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
+                    
+                    details::free_node(*(expr_gen.node_allocator_),branch[0]);
+                    details::free_node(*(expr_gen.node_allocator_),branch[1]);
+                    
+                    expression_node_ptr result = error_node();
+                    
+                    if (expr_gen.parser_->settings_.strength_reduction_enabled())
+                    {
+                        // (v0 + c0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1
+                        if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2))
+                        {
+                            const bool synthesis_result =
+                            synthesize_sf3ext_expression::
+                            template compile<ctype,vtype,vtype>(expr_gen,"(t+t)+t",(c0 + c1),v0,v1,result);
+                            
+                            exprtk_debug(("(v0 + c0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1\n"));
+                            
+                            return (synthesis_result) ? result : error_node();
+                        }
+                        // (v0 + c0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1
+                        else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2))
+                        {
+                            const bool synthesis_result =
+                            synthesize_sf3ext_expression::
+                            template compile<ctype,vtype,vtype>(expr_gen,"(t+t)-t",(c0 - c1),v0,v1,result);
+                            
+                            exprtk_debug(("(v0 + c0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1\n"));
+                            
+                            return (synthesis_result) ? result : error_node();
+                        }
+                        // (v0 - c0) - (c1 - v1) --> (vovoc) v0 + v1 - (c1 + c0)
+                        else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2))
+                        {
+                            const bool synthesis_result =
+                            synthesize_sf3ext_expression::
+                            template compile<vtype,vtype,ctype>(expr_gen,"(t+t)-t",v0,v1,(c1 + c0),result);
+                            
+                            exprtk_debug(("(v0 - c0) - (c1 - v1) --> (vovoc) v0 + v1 - (c1 + c0)\n"));
+                            
+                            return (synthesis_result) ? result : error_node();
+                        }
+                        // (v0 * c0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1
+                        else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
+                        {
+                            const bool synthesis_result =
+                            synthesize_sf3ext_expression::
+                            template compile<ctype,vtype,vtype>(expr_gen,"(t*t)*t",(c0 * c1),v0,v1,result);
+                            
+                            exprtk_debug(("(v0 * c0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1\n"));
+                            
+                            return (synthesis_result) ? result : error_node();
+                        }
+                        // (v0 * c0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 * v1)
+                        else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
+                        {
+                            const bool synthesis_result =
+                            synthesize_sf3ext_expression::
+                            template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",(c0 / c1),v0,v1,result);
+                            
+                            exprtk_debug(("(v0 * c0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 * v1)\n"));
+                            
+                            return (synthesis_result) ? result : error_node();
+                        }
+                        // (v0 / c0) * (c1 / v1) --> (covov) (c1 / c0) * (v0 / v1)
+                        else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
+                        {
+                            const bool synthesis_result =
+                            synthesize_sf3ext_expression::
+                            template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",(c1 / c0),v0,v1,result);
+                            
+                            exprtk_debug(("(v0 / c0) * (c1 / v1) --> (covov) (c1 / c0) * (v0 / v1)\n"));
+                            
+                            return (synthesis_result) ? result : error_node();
+                        }
+                        // (v0 * c0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)
+                        else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
+                        {
+                            const bool synthesis_result =
+                            synthesize_sf3ext_expression::
+                            template compile<ctype,vtype,vtype>(expr_gen,"(t*t)*t",(c0 / c1),v0,v1,result);
+                            
+                            exprtk_debug(("(v0 * c0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)\n"));
+                            
+                            return (synthesis_result) ? result : error_node();
+                        }
+                        // (v0 / c0) / (c1 * v1) --> (covov) (1 / (c0 * c1)) * (v0 / v1)
+                        else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))
+                        {
+                            const bool synthesis_result =
+                            synthesize_sf3ext_expression::
+                            template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",Type(1) / (c0 * c1),v0,v1,result);
+                            
+                            exprtk_debug(("(v0 / c0) / (c1 * v1) --> (covov) (1 / (c0 * c1)) * (v0 / v1)\n"));
+                            
+                            return (synthesis_result) ? result : error_node();
+                        }
+                        // (v0 / c0) / (c1 / v1) --> (vovoc) (v0 * v1) * (1 / (c0 * c1))
+                        else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
+                        {
+                            const bool synthesis_result =
+                            synthesize_sf3ext_expression::
+                            template compile<vtype,vtype,ctype>(expr_gen,"(t*t)*t",v0,v1,Type(1) / (c0 * c1),result);
+                            
+                            exprtk_debug(("(v0 / c0) / (c1 / v1) --> (vovoc) (v0 * v1) * (1 / (c0 * c1))\n"));
+                            
+                            return (synthesis_result) ? result : error_node();
+                        }
+                        // (v0 * c) +/- (c * v1) --> (covov) c * (v0 +/- v1)
+                        else if (
+                                 (std::equal_to<T>()(c0,c1)) &&
+                                 (details::e_mul == o0)      &&
+                                 (details::e_mul == o2)      &&
+                                 (
+                                  (details::e_add == o1) || (details::e_sub == o1)
+                                  )
+                                 )
+                        {
+                            std::string specfunc;
+                            
+                            switch (o1)
+                            {
+                                case details::e_add : specfunc = "t*(t+t)"; break;
+                                case details::e_sub : specfunc = "t*(t-t)"; break;
+                                default             : return error_node();
+                            }
+                            
+                            const bool synthesis_result =
+                            synthesize_sf3ext_expression::
+                            template compile<ctype,vtype,vtype>(expr_gen,specfunc,c0,v0,v1,result);
+                            
+                            exprtk_debug(("(v0 * c) +/- (c * v1) --> (covov) c * (v0 +/- v1)\n"));
+                            
+                            return (synthesis_result) ? result : error_node();
+                        }
+                    }
+                    
+                    if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c0,c1,v1,result))
+                        return result;
+                    else if (!expr_gen.valid_operator(o0,f0))
+                        return error_node();
+                    else if (!expr_gen.valid_operator(o1,f1))
+                        return error_node();
+                    else if (!expr_gen.valid_operator(o2,f2))
+                        return error_node();
+                    else
+                        return node_type::allocate(*(expr_gen.node_allocator_),v0,c0,c1,v1,f0,f1,f2);
+                }
+                
+                static inline std::string id(expression_generator<Type>& expr_gen,
+                                             const details::operator_type o0,
+                                             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)");
+                }
+            };
+            
+            struct synthesize_vovovov_expression1
+            {
+                typedef typename vovovov_t::type1 node_type;
+                typedef typename vovovov_t::sf4_type sf4_type;
+                typedef typename node_type::T0 T0;
+                typedef typename node_type::T1 T1;
+                typedef typename node_type::T2 T2;
+                typedef typename node_type::T3 T3;
+                
+                static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                          const details::operator_type& operation,
+                                                          expression_node_ptr (&branch)[2])
+                {
+                    // v0 o0 (v1 o1 (v2 o2 v3))
+                    typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t;
+                    
+                    const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]);
+                    const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
+                    const Type& v1 = vovov->t0();
+                    const Type& v2 = vovov->t1();
+                    const Type& v3 = vovov->t2();
+                    const details::operator_type o0 = operation;
+                    const details::operator_type o1 = expr_gen.get_operator(vovov->f0());
+                    const details::operator_type o2 = expr_gen.get_operator(vovov->f1());
+                    
+                    binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+                    binary_functor_t f1 = vovov->f0();
+                    binary_functor_t f2 = vovov->f1();
+                    
+                    details::free_node(*(expr_gen.node_allocator_),branch[1]);
+                    
+                    expression_node_ptr result = error_node();
+                    
+                    if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,v3,result))
+                        return result;
+                    else if (!expr_gen.valid_operator(o0,f0))
+                        return error_node();
+                    
+                    exprtk_debug(("v0 o0 (v1 o1 (v2 o2 v3))\n"));
+                    
+                    return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,v3,f0,f1,f2);
+                }
+                
+                static inline std::string id(expression_generator<Type>& expr_gen,
+                                             const details::operator_type o0,
+                                             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))");
+                }
+            };
+            
+            struct synthesize_vovovoc_expression1
+            {
+                typedef typename vovovoc_t::type1 node_type;
+                typedef typename vovovoc_t::sf4_type sf4_type;
+                typedef typename node_type::T0 T0;
+                typedef typename node_type::T1 T1;
+                typedef typename node_type::T2 T2;
+                typedef typename node_type::T3 T3;
+                
+                static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                          const details::operator_type& operation,
+                                                          expression_node_ptr (&branch)[2])
+                {
+                    // v0 o0 (v1 o1 (v2 o2 c))
+                    typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t;
+                    
+                    const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]);
+                    const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
+                    const Type& v1 = vovoc->t0();
+                    const Type& v2 = vovoc->t1();
+                    const Type   c = vovoc->t2();
+                    const details::operator_type o0 = operation;
+                    const details::operator_type o1 = expr_gen.get_operator(vovoc->f0());
+                    const details::operator_type o2 = expr_gen.get_operator(vovoc->f1());
+                    
+                    binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+                    binary_functor_t f1 = vovoc->f0();
+                    binary_functor_t f2 = vovoc->f1();
+                    
+                    details::free_node(*(expr_gen.node_allocator_),branch[1]);
+                    
+                    expression_node_ptr result = error_node();
+                    
+                    if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,c,result))
+                        return result;
+                    else if (!expr_gen.valid_operator(o0,f0))
+                        return error_node();
+                    
+                    exprtk_debug(("v0 o0 (v1 o1 (v2 o2 c))\n"));
+                    
+                    return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,c,f0,f1,f2);
+                }
+                
+                static inline std::string id(expression_generator<Type>& expr_gen,
+                                             const details::operator_type o0,
+                                             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))");
+                }
+            };
+            
+            struct synthesize_vovocov_expression1
+            {
+                typedef typename vovocov_t::type1 node_type;
+                typedef typename vovocov_t::sf4_type sf4_type;
+                typedef typename node_type::T0 T0;
+                typedef typename node_type::T1 T1;
+                typedef typename node_type::T2 T2;
+                typedef typename node_type::T3 T3;
+                
+                static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                          const details::operator_type& operation,
+                                                          expression_node_ptr (&branch)[2])
+                {
+                    // v0 o0 (v1 o1 (c o2 v2))
+                    typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t;
+                    
+                    const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]);
+                    const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
+                    const Type& v1 = vocov->t0();
+                    const Type   c = vocov->t1();
+                    const Type& v2 = vocov->t2();
+                    const details::operator_type o0 = operation;
+                    const details::operator_type o1 = expr_gen.get_operator(vocov->f0());
+                    const details::operator_type o2 = expr_gen.get_operator(vocov->f1());
+                    
+                    binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+                    binary_functor_t f1 = vocov->f0();
+                    binary_functor_t f2 = vocov->f1();
+                    
+                    details::free_node(*(expr_gen.node_allocator_),branch[1]);
+                    
+                    expression_node_ptr result = error_node();
+                    
+                    if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,c,v2,result))
+                        return result;
+                    if (!expr_gen.valid_operator(o0,f0))
+                        return error_node();
+                    
+                    exprtk_debug(("v0 o0 (v1 o1 (c o2 v2))\n"));
+                    
+                    return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,c,v2,f0,f1,f2);
+                }
+                
+                static inline std::string id(expression_generator<Type>& expr_gen,
+                                             const details::operator_type o0,
+                                             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))");
+                }
+            };
+            
+            struct synthesize_vocovov_expression1
+            {
+                typedef typename vocovov_t::type1 node_type;
+                typedef typename vocovov_t::sf4_type sf4_type;
+                typedef typename node_type::T0 T0;
+                typedef typename node_type::T1 T1;
+                typedef typename node_type::T2 T2;
+                typedef typename node_type::T3 T3;
+                
+                static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                          const details::operator_type& operation,
+                                                          expression_node_ptr (&branch)[2])
+                {
+                    // v0 o0 (c o1 (v1 o2 v2))
+                    typedef typename synthesize_covov_expression1::node_type lcl_covov_t;
+                    
+                    const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[1]);
+                    const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
+                    const Type   c = covov->t0();
+                    const Type& v1 = covov->t1();
+                    const Type& v2 = covov->t2();
+                    const details::operator_type o0 = operation;
+                    const details::operator_type o1 = expr_gen.get_operator(covov->f0());
+                    const details::operator_type o2 = expr_gen.get_operator(covov->f1());
+                    
+                    binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+                    binary_functor_t f1 = covov->f0();
+                    binary_functor_t f2 = covov->f1();
+                    
+                    details::free_node(*(expr_gen.node_allocator_),branch[1]);
+                    
+                    expression_node_ptr result = error_node();
+                    
+                    if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c,v1,v2,result))
+                        return result;
+                    else if (!expr_gen.valid_operator(o0,f0))
+                        return error_node();
+                    
+                    exprtk_debug(("v0 o0 (c o1 (v1 o2 v2))\n"));
+                    
+                    return node_type::allocate(*(expr_gen.node_allocator_),v0,c,v1,v2,f0,f1,f2);
+                }
+                
+                static inline std::string id(expression_generator<Type>& expr_gen,
+                                             const details::operator_type o0,
+                                             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))");
+                }
+            };
+            
+            struct synthesize_covovov_expression1
+            {
+                typedef typename covovov_t::type1 node_type;
+                typedef typename covovov_t::sf4_type sf4_type;
+                typedef typename node_type::T0 T0;
+                typedef typename node_type::T1 T1;
+                typedef typename node_type::T2 T2;
+                typedef typename node_type::T3 T3;
+                
+                static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                          const details::operator_type& operation,
+                                                          expression_node_ptr (&branch)[2])
+                {
+                    // c o0 (v0 o1 (v1 o2 v2))
+                    typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t;
+                    
+                    const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]);
+                    const Type   c = static_cast<details::literal_node<Type>*>(branch[0])->value();
+                    const Type& v0 = vovov->t0();
+                    const Type& v1 = vovov->t1();
+                    const Type& v2 = vovov->t2();
+                    const details::operator_type o0 = operation;
+                    const details::operator_type o1 = expr_gen.get_operator(vovov->f0());
+                    const details::operator_type o2 = expr_gen.get_operator(vovov->f1());
+                    
+                    binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+                    binary_functor_t f1 = vovov->f0();
+                    binary_functor_t f2 = vovov->f1();
+                    
+                    details::free_node(*(expr_gen.node_allocator_),branch[0]);
+                    details::free_node(*(expr_gen.node_allocator_),branch[1]);
+                    
+                    expression_node_ptr result = error_node();
+                    
+                    if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c,v0,v1,v2,result))
+                        return result;
+                    if (!expr_gen.valid_operator(o0,f0))
+                        return error_node();
+                    
+                    exprtk_debug(("c o0 (v0 o1 (v1 o2 v2))\n"));
+                    
+                    return node_type::allocate(*(expr_gen.node_allocator_),c,v0,v1,v2,f0,f1,f2);
+                }
+                
+                static inline std::string id(expression_generator<Type>& expr_gen,
+                                             const details::operator_type o0,
+                                             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))");
+                }
+            };
+            
+            struct synthesize_covocov_expression1
+            {
+                typedef typename covocov_t::type1 node_type;
+                typedef typename covocov_t::sf4_type sf4_type;
+                typedef typename node_type::T0 T0;
+                typedef typename node_type::T1 T1;
+                typedef typename node_type::T2 T2;
+                typedef typename node_type::T3 T3;
+                
+                static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                          const details::operator_type& operation,
+                                                          expression_node_ptr (&branch)[2])
+                {
+                    // c0 o0 (v0 o1 (c1 o2 v1))
+                    typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t;
+                    
+                    const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]);
+                    const Type  c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
+                    const Type& v0 = vocov->t0();
+                    const Type  c1 = vocov->t1();
+                    const Type& v1 = vocov->t2();
+                    const details::operator_type o0 = operation;
+                    const details::operator_type o1 = expr_gen.get_operator(vocov->f0());
+                    const details::operator_type o2 = expr_gen.get_operator(vocov->f1());
+                    
+                    binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+                    binary_functor_t f1 = vocov->f0();
+                    binary_functor_t f2 = vocov->f1();
+                    
+                    details::free_node(*(expr_gen.node_allocator_),branch[0]);
+                    details::free_node(*(expr_gen.node_allocator_),branch[1]);
+                    
+                    expression_node_ptr result = error_node();
+                    
+                    if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,c1,v1,result))
+                        return result;
+                    else if (!expr_gen.valid_operator(o0,f0))
+                        return error_node();
+                    
+                    exprtk_debug(("c0 o0 (v0 o1 (c1 o2 v1))\n"));
+                    
+                    return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,c1,v1,f0,f1,f2);
+                }
+                
+                static inline std::string id(expression_generator<Type>& expr_gen,
+                                             const details::operator_type o0,
+                                             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))");
+                }
+            };
+            
+            struct synthesize_vocovoc_expression1
+            {
+                typedef typename vocovoc_t::type1 node_type;
+                typedef typename vocovoc_t::sf4_type sf4_type;
+                typedef typename node_type::T0 T0;
+                typedef typename node_type::T1 T1;
+                typedef typename node_type::T2 T2;
+                typedef typename node_type::T3 T3;
+                
+                static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                          const details::operator_type& operation,
+                                                          expression_node_ptr (&branch)[2])
+                {
+                    // v0 o0 (c0 o1 (v1 o2 c2))
+                    typedef typename synthesize_covoc_expression1::node_type lcl_covoc_t;
+                    
+                    const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[1]);
+                    const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
+                    const Type  c0 = covoc->t0();
+                    const Type& v1 = covoc->t1();
+                    const Type  c1 = covoc->t2();
+                    const details::operator_type o0 = operation;
+                    const details::operator_type o1 = expr_gen.get_operator(covoc->f0());
+                    const details::operator_type o2 = expr_gen.get_operator(covoc->f1());
+                    
+                    binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+                    binary_functor_t f1 = covoc->f0();
+                    binary_functor_t f2 = covoc->f1();
+                    
+                    details::free_node(*(expr_gen.node_allocator_),branch[1]);
+                    
+                    expression_node_ptr result = error_node();
+                    
+                    if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c0,v1,c1,result))
+                        return result;
+                    else if (!expr_gen.valid_operator(o0,f0))
+                        return error_node();
+                    
+                    exprtk_debug(("v0 o0 (c0 o1 (v1 o2 c2))\n"));
+                    
+                    return node_type::allocate(*(expr_gen.node_allocator_),v0,c0,v1,c1,f0,f1,f2);
+                }
+                
+                static inline std::string id(expression_generator<Type>& expr_gen,
+                                             const details::operator_type o0,
+                                             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))");
+                }
+            };
+            
+            struct synthesize_covovoc_expression1
+            {
+                typedef typename covovoc_t::type1 node_type;
+                typedef typename covovoc_t::sf4_type sf4_type;
+                typedef typename node_type::T0 T0;
+                typedef typename node_type::T1 T1;
+                typedef typename node_type::T2 T2;
+                typedef typename node_type::T3 T3;
+                static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                          const details::operator_type& operation,
+                                                          expression_node_ptr (&branch)[2])
+                {
+                    // c0 o0 (v0 o1 (v1 o2 c1))
+                    typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t;
+                    
+                    const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]);
+                    const Type  c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
+                    const Type& v0 = vovoc->t0();
+                    const Type& v1 = vovoc->t1();
+                    const Type  c1 = vovoc->t2();
+                    const details::operator_type o0 = operation;
+                    const details::operator_type o1 = expr_gen.get_operator(vovoc->f0());
+                    const details::operator_type o2 = expr_gen.get_operator(vovoc->f1());
+                    
+                    binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+                    binary_functor_t f1 = vovoc->f0();
+                    binary_functor_t f2 = vovoc->f1();
+                    
+                    details::free_node(*(expr_gen.node_allocator_),branch[0]);
+                    details::free_node(*(expr_gen.node_allocator_),branch[1]);
+                    
+                    expression_node_ptr result = error_node();
+                    
+                    if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,v1,c1,result))
+                        return result;
+                    else if (!expr_gen.valid_operator(o0,f0))
+                        return error_node();
+                    
+                    exprtk_debug(("c0 o0 (v0 o1 (v1 o2 c1))\n"));
+                    
+                    return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,v1,c1,f0,f1,f2);
+                }
+                
+                static inline std::string id(expression_generator<Type>& expr_gen,
+                                             const details::operator_type o0,
+                                             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))");
+                }
+            };
+            
+            struct synthesize_vococov_expression1
+            {
+                typedef typename vococov_t::type1 node_type;
+                typedef typename vococov_t::sf4_type sf4_type;
+                typedef typename node_type::T0 T0;
+                typedef typename node_type::T1 T1;
+                typedef typename node_type::T2 T2;
+                typedef typename node_type::T3 T3;
+                
+                static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                          const details::operator_type& operation,
+                                                          expression_node_ptr (&branch)[2])
+                {
+                    // v0 o0 (c0 o1 (c1 o2 v1))
+                    typedef typename synthesize_cocov_expression1::node_type lcl_cocov_t;
+                    
+                    const lcl_cocov_t* cocov = static_cast<const lcl_cocov_t*>(branch[1]);
+                    const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
+                    const Type  c0 = cocov->t0();
+                    const Type  c1 = cocov->t1();
+                    const Type& v1 = cocov->t2();
+                    const details::operator_type o0 = operation;
+                    const details::operator_type o1 = expr_gen.get_operator(cocov->f0());
+                    const details::operator_type o2 = expr_gen.get_operator(cocov->f1());
+                    
+                    binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+                    binary_functor_t f1 = cocov->f0();
+                    binary_functor_t f2 = cocov->f1();
+                    
+                    details::free_node(*(expr_gen.node_allocator_),branch[1]);
+                    
+                    expression_node_ptr result = error_node();
+                    
+                    if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c0,c1,v1,result))
+                        return result;
+                    else if (!expr_gen.valid_operator(o0,f0))
+                        return error_node();
+                    
+                    exprtk_debug(("v0 o0 (c0 o1 (c1 o2 v1))\n"));
+                    
+                    return node_type::allocate(*(expr_gen.node_allocator_),v0,c0,c1,v1,f0,f1,f2);
+                }
+                
+                static inline std::string id(expression_generator<Type>& expr_gen,
+                                             const details::operator_type o0,
+                                             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))");
+                }
+            };
+            
+            struct synthesize_vovovov_expression2
+            {
+                typedef typename vovovov_t::type2 node_type;
+                typedef typename vovovov_t::sf4_type sf4_type;
+                typedef typename node_type::T0 T0;
+                typedef typename node_type::T1 T1;
+                typedef typename node_type::T2 T2;
+                typedef typename node_type::T3 T3;
+                
+                static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                          const details::operator_type& operation,
+                                                          expression_node_ptr (&branch)[2])
+                {
+                    // v0 o0 ((v1 o1 v2) o2 v3)
+                    typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t;
+                    
+                    const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]);
+                    const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
+                    const Type& v1 = vovov->t0();
+                    const Type& v2 = vovov->t1();
+                    const Type& v3 = vovov->t2();
+                    const details::operator_type o0 = operation;
+                    const details::operator_type o1 = expr_gen.get_operator(vovov->f0());
+                    const details::operator_type o2 = expr_gen.get_operator(vovov->f1());
+                    
+                    binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+                    binary_functor_t f1 = vovov->f0();
+                    binary_functor_t f2 = vovov->f1();
+                    
+                    details::free_node(*(expr_gen.node_allocator_),branch[1]);
+                    
+                    expression_node_ptr result = error_node();
+                    
+                    if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,v3,result))
+                        return result;
+                    else if (!expr_gen.valid_operator(o0,f0))
+                        return error_node();
+                    
+                    exprtk_debug(("v0 o0 ((v1 o1 v2) o2 v3)\n"));
+                    
+                    return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,v3,f0,f1,f2);
+                }
+                
+                static inline std::string id(expression_generator<Type>& expr_gen,
+                                             const details::operator_type o0,
+                                             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)");
+                }
+            };
+            
+            struct synthesize_vovovoc_expression2
+            {
+                typedef typename vovovoc_t::type2 node_type;
+                typedef typename vovovoc_t::sf4_type sf4_type;
+                typedef typename node_type::T0 T0;
+                typedef typename node_type::T1 T1;
+                typedef typename node_type::T2 T2;
+                typedef typename node_type::T3 T3;
+                
+                static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                          const details::operator_type& operation,
+                                                          expression_node_ptr (&branch)[2])
+                {
+                    // v0 o0 ((v1 o1 v2) o2 c)
+                    typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t;
+                    
+                    const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]);
+                    const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
+                    const Type& v1 = vovoc->t0();
+                    const Type& v2 = vovoc->t1();
+                    const Type   c = vovoc->t2();
+                    const details::operator_type o0 = operation;
+                    const details::operator_type o1 = expr_gen.get_operator(vovoc->f0());
+                    const details::operator_type o2 = expr_gen.get_operator(vovoc->f1());
+                    
+                    binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+                    binary_functor_t f1 = vovoc->f0();
+                    binary_functor_t f2 = vovoc->f1();
+                    
+                    details::free_node(*(expr_gen.node_allocator_),branch[1]);
+                    
+                    expression_node_ptr result = error_node();
+                    
+                    if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,c,result))
+                        return result;
+                    else if (!expr_gen.valid_operator(o0,f0))
+                        return error_node();
+                    
+                    exprtk_debug(("v0 o0 ((v1 o1 v2) o2 c)\n"));
+                    
+                    return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,c,f0,f1,f2);
+                }
+                
+                static inline std::string id(expression_generator<Type>& expr_gen,
+                                             const details::operator_type o0,
+                                             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)");
+                }
+            };
+            
+            struct synthesize_vovocov_expression2
+            {
+                typedef typename vovocov_t::type2 node_type;
+                typedef typename vovocov_t::sf4_type sf4_type;
+                typedef typename node_type::T0 T0;
+                typedef typename node_type::T1 T1;
+                typedef typename node_type::T2 T2;
+                typedef typename node_type::T3 T3;
+                
+                static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                          const details::operator_type& operation,
+                                                          expression_node_ptr (&branch)[2])
+                {
+                    // v0 o0 ((v1 o1 c) o2 v2)
+                    typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t;
+                    
+                    const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]);
+                    const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
+                    const Type& v1 = vocov->t0();
+                    const Type   c = vocov->t1();
+                    const Type& v2 = vocov->t2();
+                    const details::operator_type o0 = operation;
+                    const details::operator_type o1 = expr_gen.get_operator(vocov->f0());
+                    const details::operator_type o2 = expr_gen.get_operator(vocov->f1());
+                    
+                    binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+                    binary_functor_t f1 = vocov->f0();
+                    binary_functor_t f2 = vocov->f1();
+                    
+                    details::free_node(*(expr_gen.node_allocator_),branch[1]);
+                    
+                    expression_node_ptr result = error_node();
+                    
+                    if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,c,v2,result))
+                        return result;
+                    else if (!expr_gen.valid_operator(o0,f0))
+                        return error_node();
+                    
+                    exprtk_debug(("v0 o0 ((v1 o1 c) o2 v2)\n"));
+                    
+                    return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,c,v2,f0,f1,f2);
+                }
+                
+                static inline std::string id(expression_generator<Type>& expr_gen,
+                                             const details::operator_type o0,
+                                             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)");
+                }
+            };
+            
+            struct synthesize_vocovov_expression2
+            {
+                typedef typename vocovov_t::type2 node_type;
+                typedef typename vocovov_t::sf4_type sf4_type;
+                typedef typename node_type::T0 T0;
+                typedef typename node_type::T1 T1;
+                typedef typename node_type::T2 T2;
+                typedef typename node_type::T3 T3;
+                
+                static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                          const details::operator_type& operation,
+                                                          expression_node_ptr (&branch)[2])
+                {
+                    // v0 o0 ((c o1 v1) o2 v2)
+                    typedef typename synthesize_covov_expression0::node_type lcl_covov_t;
+                    
+                    const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[1]);
+                    const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
+                    const Type   c = covov->t0();
+                    const Type& v1 = covov->t1();
+                    const Type& v2 = covov->t2();
+                    const details::operator_type o0 = operation;
+                    const details::operator_type o1 = expr_gen.get_operator(covov->f0());
+                    const details::operator_type o2 = expr_gen.get_operator(covov->f1());
+                    
+                    binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+                    binary_functor_t f1 = covov->f0();
+                    binary_functor_t f2 = covov->f1();
+                    
+                    details::free_node(*(expr_gen.node_allocator_),branch[1]);
+                    
+                    expression_node_ptr result = error_node();
+                    
+                    if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c,v1,v2,result))
+                        return result;
+                    else if (!expr_gen.valid_operator(o0,f0))
+                        return error_node();
+                    
+                    exprtk_debug(("v0 o0 ((c o1 v1) o2 v2)\n"));
+                    
+                    return node_type::allocate(*(expr_gen.node_allocator_),v0,c,v1,v2,f0,f1,f2);
+                }
+                
+                static inline std::string id(expression_generator<Type>& expr_gen,
+                                             const details::operator_type o0,
+                                             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)");
+                }
+            };
+            
+            struct synthesize_covovov_expression2
+            {
+                typedef typename covovov_t::type2 node_type;
+                typedef typename covovov_t::sf4_type sf4_type;
+                typedef typename node_type::T0 T0;
+                typedef typename node_type::T1 T1;
+                typedef typename node_type::T2 T2;
+                typedef typename node_type::T3 T3;
+                
+                static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                          const details::operator_type& operation,
+                                                          expression_node_ptr (&branch)[2])
+                {
+                    // c o0 ((v1 o1 v2) o2 v3)
+                    typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t;
+                    
+                    const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]);
+                    const Type   c = static_cast<details::literal_node<Type>*>(branch[0])->value();
+                    const Type& v0 = vovov->t0();
+                    const Type& v1 = vovov->t1();
+                    const Type& v2 = vovov->t2();
+                    const details::operator_type o0 = operation;
+                    const details::operator_type o1 = expr_gen.get_operator(vovov->f0());
+                    const details::operator_type o2 = expr_gen.get_operator(vovov->f1());
+                    
+                    binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+                    binary_functor_t f1 = vovov->f0();
+                    binary_functor_t f2 = vovov->f1();
+                    
+                    details::free_node(*(expr_gen.node_allocator_),branch[0]);
+                    details::free_node(*(expr_gen.node_allocator_),branch[1]);
+                    
+                    expression_node_ptr result = error_node();
+                    
+                    if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c,v0,v1,v2,result))
+                        return result;
+                    else if (!expr_gen.valid_operator(o0,f0))
+                        return error_node();
+                    
+                    exprtk_debug(("c o0 ((v1 o1 v2) o2 v3)\n"));
+                    
+                    return node_type::allocate(*(expr_gen.node_allocator_),c,v0,v1,v2,f0,f1,f2);
+                }
+                
+                static inline std::string id(expression_generator<Type>& expr_gen,
+                                             const details::operator_type o0,
+                                             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)");
+                }
+            };
+            
+            struct synthesize_covocov_expression2
+            {
+                typedef typename covocov_t::type2 node_type;
+                typedef typename covocov_t::sf4_type sf4_type;
+                typedef typename node_type::T0 T0;
+                typedef typename node_type::T1 T1;
+                typedef typename node_type::T2 T2;
+                typedef typename node_type::T3 T3;
+                
+                static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                          const details::operator_type& operation,
+                                                          expression_node_ptr (&branch)[2])
+                {
+                    // c0 o0 ((v0 o1 c1) o2 v1)
+                    typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t;
+                    
+                    const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]);
+                    const Type  c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
+                    const Type& v0 = vocov->t0();
+                    const Type  c1 = vocov->t1();
+                    const Type& v1 = vocov->t2();
+                    const details::operator_type o0 = operation;
+                    const details::operator_type o1 = expr_gen.get_operator(vocov->f0());
+                    const details::operator_type o2 = expr_gen.get_operator(vocov->f1());
+                    
+                    binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+                    binary_functor_t f1 = vocov->f0();
+                    binary_functor_t f2 = vocov->f1();
+                    
+                    details::free_node(*(expr_gen.node_allocator_),branch[0]);
+                    details::free_node(*(expr_gen.node_allocator_),branch[1]);
+                    
+                    expression_node_ptr result = error_node();
+                    
+                    if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,c1,v1,result))
+                        return result;
+                    else if (!expr_gen.valid_operator(o0,f0))
+                        return error_node();
+                    
+                    exprtk_debug(("c0 o0 ((v0 o1 c1) o2 v1)\n"));
+                    
+                    return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,c1,v1,f0,f1,f2);
+                }
+                
+                static inline std::string id(expression_generator<Type>& expr_gen,
+                                             const details::operator_type o0,
+                                             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)");
+                }
+            };
+            
+            struct synthesize_vocovoc_expression2
+            {
+                typedef typename vocovoc_t::type2 node_type;
+                typedef typename vocovoc_t::sf4_type sf4_type;
+                typedef typename node_type::T0 T0;
+                typedef typename node_type::T1 T1;
+                typedef typename node_type::T2 T2;
+                typedef typename node_type::T3 T3;
+                
+                static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                          const details::operator_type& operation,
+                                                          expression_node_ptr (&branch)[2])
+                {
+                    // v0 o0 ((c0 o1 v1) o2 c1)
+                    typedef typename synthesize_covoc_expression0::node_type lcl_covoc_t;
+                    
+                    const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[1]);
+                    const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
+                    const Type  c0 = covoc->t0();
+                    const Type& v1 = covoc->t1();
+                    const Type  c1 = covoc->t2();
+                    const details::operator_type o0 = operation;
+                    const details::operator_type o1 = expr_gen.get_operator(covoc->f0());
+                    const details::operator_type o2 = expr_gen.get_operator(covoc->f1());
+                    
+                    binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+                    binary_functor_t f1 = covoc->f0();
+                    binary_functor_t f2 = covoc->f1();
+                    
+                    details::free_node(*(expr_gen.node_allocator_),branch[1]);
+                    
+                    expression_node_ptr result = error_node();
+                    
+                    if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c0,v1,c1,result))
+                        return result;
+                    else if (!expr_gen.valid_operator(o0,f0))
+                        return error_node();
+                    
+                    exprtk_debug(("v0 o0 ((c0 o1 v1) o2 c1)\n"));
+                    
+                    return node_type::allocate(*(expr_gen.node_allocator_),v0,c0,v1,c1,f0,f1,f2);
+                }
+                
+                static inline std::string id(expression_generator<Type>& expr_gen,
+                                             const details::operator_type o0,
+                                             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)");
+                }
+            };
+            
+            struct synthesize_covovoc_expression2
+            {
+                typedef typename covovoc_t::type2 node_type;
+                typedef typename covovoc_t::sf4_type sf4_type;
+                typedef typename node_type::T0 T0;
+                typedef typename node_type::T1 T1;
+                typedef typename node_type::T2 T2;
+                typedef typename node_type::T3 T3;
+                
+                static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                          const details::operator_type& operation,
+                                                          expression_node_ptr (&branch)[2])
+                {
+                    // c0 o0 ((v0 o1 v1) o2 c1)
+                    typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t;
+                    
+                    const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]);
+                    const Type  c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
+                    const Type& v0 = vovoc->t0();
+                    const Type& v1 = vovoc->t1();
+                    const Type  c1 = vovoc->t2();
+                    const details::operator_type o0 = operation;
+                    const details::operator_type o1 = expr_gen.get_operator(vovoc->f0());
+                    const details::operator_type o2 = expr_gen.get_operator(vovoc->f1());
+                    
+                    binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+                    binary_functor_t f1 = vovoc->f0();
+                    binary_functor_t f2 = vovoc->f1();
+                    
+                    details::free_node(*(expr_gen.node_allocator_),branch[0]);
+                    details::free_node(*(expr_gen.node_allocator_),branch[1]);
+                    
+                    expression_node_ptr result = error_node();
+                    
+                    if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,v1,c1,result))
+                        return result;
+                    else if (!expr_gen.valid_operator(o0,f0))
+                        return error_node();
+                    
+                    exprtk_debug(("c0 o0 ((v0 o1 v1) o2 c1)\n"));
+                    
+                    return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,v1,c1,f0,f1,f2);
+                }
+                
+                static inline std::string id(expression_generator<Type>& expr_gen,
+                                             const details::operator_type o0,
+                                             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)");
+                }
+            };
+            
+            struct synthesize_vococov_expression2
+            {
+                typedef typename vococov_t::type2 node_type;
+                static inline expression_node_ptr process(expression_generator<Type>&, const details::operator_type&, expression_node_ptr (&)[2])
+                {
+                    // v0 o0 ((c0 o1 c1) o2 v1) - Not possible
+                    exprtk_debug(("v0 o0 ((c0 o1 c1) o2 v1) - Not possible\n"));
+                    return error_node();
+                }
+                
+                static inline std::string id(expression_generator<Type>&,
+                                             const details::operator_type, const details::operator_type, const details::operator_type)
+                {
+                    return "INVALID";
+                }
+            };
+            
+            struct synthesize_vovovov_expression3
+            {
+                typedef typename vovovov_t::type3 node_type;
+                typedef typename vovovov_t::sf4_type sf4_type;
+                typedef typename node_type::T0 T0;
+                typedef typename node_type::T1 T1;
+                typedef typename node_type::T2 T2;
+                typedef typename node_type::T3 T3;
+                
+                static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                          const details::operator_type& operation,
+                                                          expression_node_ptr (&branch)[2])
+                {
+                    // ((v0 o0 v1) o1 v2) o2 v3
+                    typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t;
+                    
+                    const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]);
+                    const Type& v0 = vovov->t0();
+                    const Type& v1 = vovov->t1();
+                    const Type& v2 = vovov->t2();
+                    const Type& v3 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
+                    const details::operator_type o0 = expr_gen.get_operator(vovov->f0());
+                    const details::operator_type o1 = expr_gen.get_operator(vovov->f1());
+                    const details::operator_type o2 = operation;
+                    
+                    binary_functor_t f0 = vovov->f0();
+                    binary_functor_t f1 = vovov->f1();
+                    binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
+                    
+                    details::free_node(*(expr_gen.node_allocator_),branch[0]);
+                    
+                    expression_node_ptr result = error_node();
+                    
+                    if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,v3,result))
+                        return result;
+                    else if (!expr_gen.valid_operator(o2,f2))
+                        return error_node();
+                    
+                    exprtk_debug(("((v0 o0 v1) o1 v2) o2 v3\n"));
+                    
+                    return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,v3,f0,f1,f2);
+                }
+                
+                static inline std::string id(expression_generator<Type>& expr_gen,
+                                             const details::operator_type o0,
+                                             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");
+                }
+            };
+            
+            struct synthesize_vovovoc_expression3
+            {
+                typedef typename vovovoc_t::type3 node_type;
+                typedef typename vovovoc_t::sf4_type sf4_type;
+                typedef typename node_type::T0 T0;
+                typedef typename node_type::T1 T1;
+                typedef typename node_type::T2 T2;
+                typedef typename node_type::T3 T3;
+                
+                static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                          const details::operator_type& operation,
+                                                          expression_node_ptr (&branch)[2])
+                {
+                    // ((v0 o0 v1) o1 v2) o2 c
+                    typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t;
+                    
+                    const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]);
+                    const Type& v0 = vovov->t0();
+                    const Type& v1 = vovov->t1();
+                    const Type& v2 = vovov->t2();
+                    const Type   c = static_cast<details::literal_node<Type>*>(branch[1])->value();
+                    const details::operator_type o0 = expr_gen.get_operator(vovov->f0());
+                    const details::operator_type o1 = expr_gen.get_operator(vovov->f1());
+                    const details::operator_type o2 = operation;
+                    
+                    binary_functor_t f0 = vovov->f0();
+                    binary_functor_t f1 = vovov->f1();
+                    binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
+                    
+                    details::free_node(*(expr_gen.node_allocator_),branch[0]);
+                    details::free_node(*(expr_gen.node_allocator_),branch[1]);
+                    
+                    expression_node_ptr result = error_node();
+                    
+                    if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,c,result))
+                        return result;
+                    else if (!expr_gen.valid_operator(o2,f2))
+                        return error_node();
+                    
+                    exprtk_debug(("((v0 o0 v1) o1 v2) o2 c\n"));
+                    
+                    return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,c,f0,f1,f2);
+                }
+                
+                static inline std::string id(expression_generator<Type>& expr_gen,
+                                             const details::operator_type o0,
+                                             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");
+                }
+            };
+            
+            struct synthesize_vovocov_expression3
+            {
+                typedef typename vovocov_t::type3 node_type;
+                typedef typename vovocov_t::sf4_type sf4_type;
+                typedef typename node_type::T0 T0;
+                typedef typename node_type::T1 T1;
+                typedef typename node_type::T2 T2;
+                typedef typename node_type::T3 T3;
+                
+                static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                          const details::operator_type& operation,
+                                                          expression_node_ptr (&branch)[2])
+                {
+                    // ((v0 o0 v1) o1 c) o2 v2
+                    typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t;
+                    
+                    const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[0]);
+                    const Type& v0 = vovoc->t0();
+                    const Type& v1 = vovoc->t1();
+                    const Type   c = vovoc->t2();
+                    const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
+                    const details::operator_type o0 = expr_gen.get_operator(vovoc->f0());
+                    const details::operator_type o1 = expr_gen.get_operator(vovoc->f1());
+                    const details::operator_type o2 = operation;
+                    
+                    binary_functor_t f0 = vovoc->f0();
+                    binary_functor_t f1 = vovoc->f1();
+                    binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
+                    
+                    details::free_node(*(expr_gen.node_allocator_),branch[0]);
+                    
+                    expression_node_ptr result = error_node();
+                    
+                    if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,c,v2,result))
+                        return result;
+                    else if (!expr_gen.valid_operator(o2,f2))
+                        return error_node();
+                    
+                    exprtk_debug(("((v0 o0 v1) o1 c) o2 v2\n"));
+                    
+                    return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,c,v2,f0,f1,f2);
+                }
+                
+                static inline std::string id(expression_generator<Type>& expr_gen,
+                                             const details::operator_type o0,
+                                             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");
+                }
+            };
+            
+            struct synthesize_vocovov_expression3
+            {
+                typedef typename vocovov_t::type3 node_type;
+                typedef typename vocovov_t::sf4_type sf4_type;
+                typedef typename node_type::T0 T0;
+                typedef typename node_type::T1 T1;
+                typedef typename node_type::T2 T2;
+                typedef typename node_type::T3 T3;
+                
+                static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                          const details::operator_type& operation,
+                                                          expression_node_ptr (&branch)[2])
+                {
+                    // ((v0 o0 c) o1 v1) o2 v2
+                    typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t;
+                    
+                    const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]);
+                    const Type& v0 = vocov->t0();
+                    const Type   c = vocov->t1();
+                    const Type& v1 = vocov->t2();
+                    const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
+                    const details::operator_type o0 = expr_gen.get_operator(vocov->f0());
+                    const details::operator_type o1 = expr_gen.get_operator(vocov->f1());
+                    const details::operator_type o2 = operation;
+                    
+                    binary_functor_t f0 = vocov->f0();
+                    binary_functor_t f1 = vocov->f1();
+                    binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
+                    
+                    details::free_node(*(expr_gen.node_allocator_),branch[0]);
+                    
+                    expression_node_ptr result = error_node();
+                    
+                    if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c,v1,v2,result))
+                        return result;
+                    else if (!expr_gen.valid_operator(o2,f2))
+                        return error_node();
+                    
+                    exprtk_debug(("((v0 o0 c) o1 v1) o2 v2\n"));
+                    
+                    return node_type::allocate(*(expr_gen.node_allocator_),v0,c,v1,v2,f0,f1,f2);
+                }
+                
+                static inline std::string id(expression_generator<Type>& expr_gen,
+                                             const details::operator_type o0,
+                                             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");
+                }
+            };
+            
+            struct synthesize_covovov_expression3
+            {
+                typedef typename covovov_t::type3 node_type;
+                typedef typename covovov_t::sf4_type sf4_type;
+                typedef typename node_type::T0 T0;
+                typedef typename node_type::T1 T1;
+                typedef typename node_type::T2 T2;
+                typedef typename node_type::T3 T3;
+                
+                static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                          const details::operator_type& operation,
+                                                          expression_node_ptr (&branch)[2])
+                {
+                    // ((c o0 v0) o1 v1) o2 v2
+                    typedef typename synthesize_covov_expression0::node_type lcl_covov_t;
+                    
+                    const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]);
+                    const Type   c = covov->t0();
+                    const Type& v0 = covov->t1();
+                    const Type& v1 = covov->t2();
+                    const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
+                    const details::operator_type o0 = expr_gen.get_operator(covov->f0());
+                    const details::operator_type o1 = expr_gen.get_operator(covov->f1());
+                    const details::operator_type o2 = operation;
+                    
+                    binary_functor_t f0 = covov->f0();
+                    binary_functor_t f1 = covov->f1();
+                    binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
+                    
+                    details::free_node(*(expr_gen.node_allocator_),branch[0]);
+                    
+                    expression_node_ptr result = error_node();
+                    
+                    if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c,v0,v1,v2,result))
+                        return result;
+                    else if (!expr_gen.valid_operator(o2,f2))
+                        return error_node();
+                    
+                    exprtk_debug(("((c o0 v0) o1 v1) o2 v2\n"));
+                    
+                    return node_type::allocate(*(expr_gen.node_allocator_),c,v0,v1,v2,f0,f1,f2);
+                }
+                
+                static inline std::string id(expression_generator<Type>& expr_gen,
+                                             const details::operator_type o0,
+                                             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");
+                }
+            };
+            
+            struct synthesize_covocov_expression3
+            {
+                typedef typename covocov_t::type3 node_type;
+                typedef typename covocov_t::sf4_type sf4_type;
+                typedef typename node_type::T0 T0;
+                typedef typename node_type::T1 T1;
+                typedef typename node_type::T2 T2;
+                typedef typename node_type::T3 T3;
+                
+                static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                          const details::operator_type& operation,
+                                                          expression_node_ptr (&branch)[2])
+                {
+                    // ((c0 o0 v0) o1 c1) o2 v1
+                    typedef typename synthesize_covoc_expression0::node_type lcl_covoc_t;
+                    
+                    const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[0]);
+                    const Type  c0 = covoc->t0();
+                    const Type& v0 = covoc->t1();
+                    const Type  c1 = covoc->t2();
+                    const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
+                    const details::operator_type o0 = expr_gen.get_operator(covoc->f0());
+                    const details::operator_type o1 = expr_gen.get_operator(covoc->f1());
+                    const details::operator_type o2 = operation;
+                    
+                    binary_functor_t f0 = covoc->f0();
+                    binary_functor_t f1 = covoc->f1();
+                    binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
+                    
+                    details::free_node(*(expr_gen.node_allocator_),branch[0]);
+                    
+                    expression_node_ptr result = error_node();
+                    
+                    if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,c1,v1,result))
+                        return result;
+                    else if (!expr_gen.valid_operator(o2,f2))
+                        return error_node();
+                    
+                    exprtk_debug(("((c0 o0 v0) o1 c1) o2 v1\n"));
+                    
+                    return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,c1,v1,f0,f1,f2);
+                }
+                
+                static inline std::string id(expression_generator<Type>& expr_gen,
+                                             const details::operator_type o0,
+                                             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");
+                }
+            };
+            
+            struct synthesize_vocovoc_expression3
+            {
+                typedef typename vocovoc_t::type3 node_type;
+                typedef typename vocovoc_t::sf4_type sf4_type;
+                typedef typename node_type::T0 T0;
+                typedef typename node_type::T1 T1;
+                typedef typename node_type::T2 T2;
+                typedef typename node_type::T3 T3;
+                
+                static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                          const details::operator_type& operation,
+                                                          expression_node_ptr (&branch)[2])
+                {
+                    // ((v0 o0 c0) o1 v1) o2 c1
+                    typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t;
+                    
+                    const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]);
+                    const Type& v0 = vocov->t0();
+                    const Type  c0 = vocov->t1();
+                    const Type& v1 = vocov->t2();
+                    const Type  c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
+                    const details::operator_type o0 = expr_gen.get_operator(vocov->f0());
+                    const details::operator_type o1 = expr_gen.get_operator(vocov->f1());
+                    const details::operator_type o2 = operation;
+                    
+                    binary_functor_t f0 = vocov->f0();
+                    binary_functor_t f1 = vocov->f1();
+                    binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
+                    
+                    details::free_node(*(expr_gen.node_allocator_),branch[0]);
+                    details::free_node(*(expr_gen.node_allocator_),branch[1]);
+                    
+                    expression_node_ptr result = error_node();
+                    
+                    if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c0,v1,c1,result))
+                        return result;
+                    else if (!expr_gen.valid_operator(o2,f2))
+                        return error_node();
+                    
+                    exprtk_debug(("((v0 o0 c0) o1 v1) o2 c1\n"));
+                    
+                    return node_type::allocate(*(expr_gen.node_allocator_),v0,c0,v1,c1,f0,f1,f2);
+                }
+                
+                static inline std::string id(expression_generator<Type>& expr_gen,
+                                             const details::operator_type o0,
+                                             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");
+                }
+            };
+            
+            struct synthesize_covovoc_expression3
+            {
+                typedef typename covovoc_t::type3 node_type;
+                typedef typename covovoc_t::sf4_type sf4_type;
+                typedef typename node_type::T0 T0;
+                typedef typename node_type::T1 T1;
+                typedef typename node_type::T2 T2;
+                typedef typename node_type::T3 T3;
+                
+                static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                          const details::operator_type& operation,
+                                                          expression_node_ptr (&branch)[2])
+                {
+                    // ((c0 o0 v0) o1 v1) o2 c1
+                    typedef typename synthesize_covov_expression0::node_type lcl_covov_t;
+                    
+                    const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]);
+                    const Type  c0 = covov->t0();
+                    const Type& v0 = covov->t1();
+                    const Type& v1 = covov->t2();
+                    const Type  c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
+                    const details::operator_type o0 = expr_gen.get_operator(covov->f0());
+                    const details::operator_type o1 = expr_gen.get_operator(covov->f1());
+                    const details::operator_type o2 = operation;
+                    
+                    binary_functor_t f0 = covov->f0();
+                    binary_functor_t f1 = covov->f1();
+                    binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
+                    
+                    details::free_node(*(expr_gen.node_allocator_),branch[0]);
+                    details::free_node(*(expr_gen.node_allocator_),branch[1]);
+                    
+                    expression_node_ptr result = error_node();
+                    
+                    if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,v1,c1,result))
+                        return result;
+                    else if (!expr_gen.valid_operator(o2,f2))
+                        return error_node();
+                    
+                    exprtk_debug(("((c0 o0 v0) o1 v1) o2 c1\n"));
+                    
+                    return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,v1,c1,f0,f1,f2);
+                }
+                
+                static inline std::string id(expression_generator<Type>& expr_gen,
+                                             const details::operator_type o0,
+                                             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");
+                }
+            };
+            
+            struct synthesize_vococov_expression3
+            {
+                typedef typename vococov_t::type3 node_type;
+                typedef typename vococov_t::sf4_type sf4_type;
+                typedef typename node_type::T0 T0;
+                typedef typename node_type::T1 T1;
+                typedef typename node_type::T2 T2;
+                typedef typename node_type::T3 T3;
+                
+                static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                          const details::operator_type& operation,
+                                                          expression_node_ptr (&branch)[2])
+                {
+                    // ((v0 o0 c0) o1 c1) o2 v1
+                    typedef typename synthesize_vococ_expression0::node_type lcl_vococ_t;
+                    
+                    const lcl_vococ_t* vococ = static_cast<const lcl_vococ_t*>(branch[0]);
+                    const Type& v0 = vococ->t0();
+                    const Type  c0 = vococ->t1();
+                    const Type  c1 = vococ->t2();
+                    const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
+                    const details::operator_type o0 = expr_gen.get_operator(vococ->f0());
+                    const details::operator_type o1 = expr_gen.get_operator(vococ->f1());
+                    const details::operator_type o2 = operation;
+                    
+                    binary_functor_t f0 = vococ->f0();
+                    binary_functor_t f1 = vococ->f1();
+                    binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
+                    
+                    details::free_node(*(expr_gen.node_allocator_),branch[0]);
+                    
+                    expression_node_ptr result = error_node();
+                    
+                    if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c0,c1,v1,result))
+                        return result;
+                    else if (!expr_gen.valid_operator(o2,f2))
+                        return error_node();
+                    
+                    exprtk_debug(("((v0 o0 c0) o1 c1) o2 v1\n"));
+                    
+                    return node_type::allocate(*(expr_gen.node_allocator_),v0,c0,c1,v1,f0,f1,f2);
+                }
+                
+                static inline std::string id(expression_generator<Type>& expr_gen,
+                                             const details::operator_type o0,
+                                             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");
+                }
+            };
+            
+            struct synthesize_vovovov_expression4
+            {
+                typedef typename vovovov_t::type4 node_type;
+                typedef typename vovovov_t::sf4_type sf4_type;
+                typedef typename node_type::T0 T0;
+                typedef typename node_type::T1 T1;
+                typedef typename node_type::T2 T2;
+                typedef typename node_type::T3 T3;
+                
+                static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                          const details::operator_type& operation,
+                                                          expression_node_ptr (&branch)[2])
+                {
+                    // (v0 o0 (v1 o1 v2)) o2 v3
+                    typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t;
+                    
+                    const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]);
+                    const Type& v0 = vovov->t0();
+                    const Type& v1 = vovov->t1();
+                    const Type& v2 = vovov->t2();
+                    const Type& v3 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
+                    const details::operator_type o0 = expr_gen.get_operator(vovov->f0());
+                    const details::operator_type o1 = expr_gen.get_operator(vovov->f1());
+                    const details::operator_type o2 = operation;
+                    
+                    binary_functor_t f0 = vovov->f0();
+                    binary_functor_t f1 = vovov->f1();
+                    binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
+                    
+                    details::free_node(*(expr_gen.node_allocator_),branch[0]);
+                    
+                    expression_node_ptr result = error_node();
+                    
+                    if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,v3,result))
+                        return result;
+                    else if (!expr_gen.valid_operator(o2,f2))
+                        return error_node();
+                    
+                    exprtk_debug(("(v0 o0 (v1 o1 v2)) o2 v3\n"));
+                    
+                    return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,v3,f0,f1,f2);
+                }
+                
+                static inline std::string id(expression_generator<Type>& expr_gen,
+                                             const details::operator_type o0,
+                                             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");
+                }
+            };
+            
+            struct synthesize_vovovoc_expression4
+            {
+                typedef typename vovovoc_t::type4 node_type;
+                typedef typename vovovoc_t::sf4_type sf4_type;
+                typedef typename node_type::T0 T0;
+                typedef typename node_type::T1 T1;
+                typedef typename node_type::T2 T2;
+                typedef typename node_type::T3 T3;
+                
+                static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                          const details::operator_type& operation,
+                                                          expression_node_ptr (&branch)[2])
+                {
+                    // ((v0 o0 (v1 o1 v2)) o2 c)
+                    typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t;
+                    
+                    const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]);
+                    const Type& v0 = vovov->t0();
+                    const Type& v1 = vovov->t1();
+                    const Type& v2 = vovov->t2();
+                    const Type   c = static_cast<details::literal_node<Type>*>(branch[1])->value();
+                    const details::operator_type o0 = expr_gen.get_operator(vovov->f0());
+                    const details::operator_type o1 = expr_gen.get_operator(vovov->f1());
+                    const details::operator_type o2 = operation;
+                    
+                    binary_functor_t f0 = vovov->f0();
+                    binary_functor_t f1 = vovov->f1();
+                    binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
+                    
+                    details::free_node(*(expr_gen.node_allocator_),branch[0]);
+                    details::free_node(*(expr_gen.node_allocator_),branch[1]);
+                    
+                    expression_node_ptr result = error_node();
+                    
+                    if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,c,result))
+                        return result;
+                    else if (!expr_gen.valid_operator(o2,f2))
+                        return error_node();
+                    
+                    exprtk_debug(("((v0 o0 (v1 o1 v2)) o2 c)\n"));
+                    
+                    return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,c,f0,f1,f2);
+                }
+                
+                static inline std::string id(expression_generator<Type>& expr_gen,
+                                             const details::operator_type o0,
+                                             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");
+                }
+            };
+            
+            struct synthesize_vovocov_expression4
+            {
+                typedef typename vovocov_t::type4 node_type;
+                typedef typename vovocov_t::sf4_type sf4_type;
+                typedef typename node_type::T0 T0;
+                typedef typename node_type::T1 T1;
+                typedef typename node_type::T2 T2;
+                typedef typename node_type::T3 T3;
+                
+                static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                          const details::operator_type& operation,
+                                                          expression_node_ptr (&branch)[2])
+                {
+                    // ((v0 o0 (v1 o1 c)) o2 v1)
+                    typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t;
+                    
+                    const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[0]);
+                    const Type& v0 = vovoc->t0();
+                    const Type& v1 = vovoc->t1();
+                    const Type   c = vovoc->t2();
+                    const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
+                    const details::operator_type o0 = expr_gen.get_operator(vovoc->f0());
+                    const details::operator_type o1 = expr_gen.get_operator(vovoc->f1());
+                    const details::operator_type o2 = operation;
+                    
+                    binary_functor_t f0 = vovoc->f0();
+                    binary_functor_t f1 = vovoc->f1();
+                    binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
+                    
+                    details::free_node(*(expr_gen.node_allocator_),branch[0]);
+                    
+                    expression_node_ptr result = error_node();
+                    
+                    if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,c,v2,result))
+                        return result;
+                    else if (!expr_gen.valid_operator(o2,f2))
+                        return error_node();
+                    
+                    exprtk_debug(("((v0 o0 (v1 o1 c)) o2 v1)\n"));
+                    
+                    return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,c,v2,f0,f1,f2);
+                }
+                
+                static inline std::string id(expression_generator<Type>& expr_gen,
+                                             const details::operator_type o0,
+                                             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");
+                }
+            };
+            
+            struct synthesize_vocovov_expression4
+            {
+                typedef typename vocovov_t::type4 node_type;
+                typedef typename vocovov_t::sf4_type sf4_type;
+                typedef typename node_type::T0 T0;
+                typedef typename node_type::T1 T1;
+                typedef typename node_type::T2 T2;
+                typedef typename node_type::T3 T3;
+                
+                static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                          const details::operator_type& operation,
+                                                          expression_node_ptr (&branch)[2])
+                {
+                    // ((v0 o0 (c o1 v1)) o2 v2)
+                    typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t;
+                    
+                    const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]);
+                    const Type& v0 = vocov->t0();
+                    const Type   c = vocov->t1();
+                    const Type& v1 = vocov->t2();
+                    const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
+                    const details::operator_type o0 = expr_gen.get_operator(vocov->f0());
+                    const details::operator_type o1 = expr_gen.get_operator(vocov->f1());
+                    const details::operator_type o2 = operation;
+                    
+                    binary_functor_t f0 = vocov->f0();
+                    binary_functor_t f1 = vocov->f1();
+                    binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
+                    
+                    details::free_node(*(expr_gen.node_allocator_),branch[0]);
+                    expression_node_ptr result = error_node();
+                    
+                    if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c,v1,v2,result))
+                        return result;
+                    else if (!expr_gen.valid_operator(o2,f2))
+                        return error_node();
+                    
+                    exprtk_debug(("((v0 o0 (c o1 v1)) o2 v2)\n"));
+                    
+                    return node_type::allocate(*(expr_gen.node_allocator_),v0,c,v1,v2,f0,f1,f2);
+                }
+                
+                static inline std::string id(expression_generator<Type>& expr_gen,
+                                             const details::operator_type o0,
+                                             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");
+                }
+            };
+            
+            struct synthesize_covovov_expression4
+            {
+                typedef typename covovov_t::type4 node_type;
+                typedef typename covovov_t::sf4_type sf4_type;
+                typedef typename node_type::T0 T0;
+                typedef typename node_type::T1 T1;
+                typedef typename node_type::T2 T2;
+                typedef typename node_type::T3 T3;
+                
+                static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                          const details::operator_type& operation,
+                                                          expression_node_ptr (&branch)[2])
+                {
+                    // ((c o0 (v0 o1 v1)) o2 v2)
+                    typedef typename synthesize_covov_expression1::node_type lcl_covov_t;
+                    
+                    const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]);
+                    const Type   c = covov->t0();
+                    const Type& v0 = covov->t1();
+                    const Type& v1 = covov->t2();
+                    const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
+                    const details::operator_type o0 = expr_gen.get_operator(covov->f0());
+                    const details::operator_type o1 = expr_gen.get_operator(covov->f1());
+                    const details::operator_type o2 = operation;
+                    
+                    binary_functor_t f0 = covov->f0();
+                    binary_functor_t f1 = covov->f1();
+                    binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
+                    
+                    details::free_node(*(expr_gen.node_allocator_),branch[0]);
+                    
+                    expression_node_ptr result = error_node();
+                    
+                    if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c,v0,v1,v2,result))
+                        return result;
+                    else if (!expr_gen.valid_operator(o2,f2))
+                        return error_node();
+                    
+                    exprtk_debug(("((c o0 (v0 o1 v1)) o2 v2)\n"));
+                    
+                    return node_type::allocate(*(expr_gen.node_allocator_),c,v0,v1,v2,f0,f1,f2);
+                }
+                
+                static inline std::string id(expression_generator<Type>& expr_gen,
+                                             const details::operator_type o0,
+                                             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");
+                }
+            };
+            
+            struct synthesize_covocov_expression4
+            {
+                typedef typename covocov_t::type4 node_type;
+                typedef typename covocov_t::sf4_type sf4_type;
+                typedef typename node_type::T0 T0;
+                typedef typename node_type::T1 T1;
+                typedef typename node_type::T2 T2;
+                typedef typename node_type::T3 T3;
+                
+                static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                          const details::operator_type& operation,
+                                                          expression_node_ptr (&branch)[2])
+                {
+                    // ((c0 o0 (v0 o1 c1)) o2 v1)
+                    typedef typename synthesize_covoc_expression1::node_type lcl_covoc_t;
+                    
+                    const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[0]);
+                    const Type  c0 = covoc->t0();
+                    const Type& v0 = covoc->t1();
+                    const Type  c1 = covoc->t2();
+                    const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
+                    const details::operator_type o0 = expr_gen.get_operator(covoc->f0());
+                    const details::operator_type o1 = expr_gen.get_operator(covoc->f1());
+                    const details::operator_type o2 = operation;
+                    
+                    binary_functor_t f0 = covoc->f0();
+                    binary_functor_t f1 = covoc->f1();
+                    binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
+                    
+                    details::free_node(*(expr_gen.node_allocator_),branch[0]);
+                    
+                    expression_node_ptr result = error_node();
+                    
+                    if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,c1,v1,result))
+                        return result;
+                    else if (!expr_gen.valid_operator(o2,f2))
+                        return error_node();
+                    
+                    exprtk_debug(("((c0 o0 (v0 o1 c1)) o2 v1)\n"));
+                    
+                    return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,c1,v1,f0,f1,f2);
+                }
+                
+                static inline std::string id(expression_generator<Type>& expr_gen,
+                                             const details::operator_type o0,
+                                             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");
+                }
+            };
+            
+            struct synthesize_vocovoc_expression4
+            {
+                typedef typename vocovoc_t::type4 node_type;
+                typedef typename vocovoc_t::sf4_type sf4_type;
+                typedef typename node_type::T0 T0;
+                typedef typename node_type::T1 T1;
+                typedef typename node_type::T2 T2;
+                typedef typename node_type::T3 T3;
+                
+                static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                          const details::operator_type& operation,
+                                                          expression_node_ptr (&branch)[2])
+                {
+                    // ((v0 o0 (c0 o1 v1)) o2 c1)
+                    typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t;
+                    
+                    const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]);
+                    const Type& v0 = vocov->t0();
+                    const Type  c0 = vocov->t1();
+                    const Type& v1 = vocov->t2();
+                    const Type  c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
+                    const details::operator_type o0 = expr_gen.get_operator(vocov->f0());
+                    const details::operator_type o1 = expr_gen.get_operator(vocov->f1());
+                    const details::operator_type o2 = operation;
+                    
+                    binary_functor_t f0 = vocov->f0();
+                    binary_functor_t f1 = vocov->f1();
+                    binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
+                    
+                    details::free_node(*(expr_gen.node_allocator_),branch[0]);
+                    details::free_node(*(expr_gen.node_allocator_),branch[1]);
+                    
+                    expression_node_ptr result = error_node();
+                    
+                    if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c0,v1,c1,result))
+                        return result;
+                    else if (!expr_gen.valid_operator(o2,f2))
+                        return error_node();
+                    
+                    exprtk_debug(("((v0 o0 (c0 o1 v1)) o2 c1)\n"));
+                    
+                    return node_type::allocate(*(expr_gen.node_allocator_),v0,c0,v1,c1,f0,f1,f2);
+                }
+                
+                static inline std::string id(expression_generator<Type>& expr_gen,
+                                             const details::operator_type o0,
+                                             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");
+                }
+            };
+            
+            struct synthesize_covovoc_expression4
+            {
+                typedef typename covovoc_t::type4 node_type;
+                typedef typename covovoc_t::sf4_type sf4_type;
+                typedef typename node_type::T0 T0;
+                typedef typename node_type::T1 T1;
+                typedef typename node_type::T2 T2;
+                typedef typename node_type::T3 T3;
+                
+                static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                          const details::operator_type& operation,
+                                                          expression_node_ptr (&branch)[2])
+                {
+                    // ((c0 o0 (v0 o1 v1)) o2 c1)
+                    typedef typename synthesize_covov_expression1::node_type lcl_covov_t;
+                    
+                    const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]);
+                    const Type  c0 = covov->t0();
+                    const Type& v0 = covov->t1();
+                    const Type& v1 = covov->t2();
+                    const Type  c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
+                    const details::operator_type o0 = expr_gen.get_operator(covov->f0());
+                    const details::operator_type o1 = expr_gen.get_operator(covov->f1());
+                    const details::operator_type o2 = operation;
+                    
+                    binary_functor_t f0 = covov->f0();
+                    binary_functor_t f1 = covov->f1();
+                    binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
+                    
+                    details::free_node(*(expr_gen.node_allocator_),branch[0]);
+                    details::free_node(*(expr_gen.node_allocator_),branch[1]);
+                    
+                    expression_node_ptr result = error_node();
+                    
+                    if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,v1,c1,result))
+                        return result;
+                    else if (!expr_gen.valid_operator(o2,f2))
+                        return error_node();
+                    
+                    exprtk_debug(("((c0 o0 (v0 o1 v1)) o2 c1)\n"));
+                    
+                    return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,v1,c1,f0,f1,f2);
+                }
+                
+                static inline std::string id(expression_generator<Type>& expr_gen,
+                                             const details::operator_type o0,
+                                             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");
+                }
+            };
+            
+            struct synthesize_vococov_expression4
+            {
+                typedef typename vococov_t::type4 node_type;
+                static inline expression_node_ptr process(expression_generator<Type>&, const details::operator_type&, expression_node_ptr (&)[2])
+                {
+                    // ((v0 o0 (c0 o1 c1)) o2 v1) - Not possible
+                    exprtk_debug(("((v0 o0 (c0 o1 c1)) o2 v1) - Not possible\n"));
+                    return error_node();
+                }
+                
+                static inline std::string id(expression_generator<Type>&,
+                                             const details::operator_type, const details::operator_type, const details::operator_type)
+                {
+                    return "INVALID";
+                }
+            };
+#endif
+            
+            inline expression_node_ptr synthesize_uvouv_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
+            {
+                // Definition: uv o uv
+                details::operator_type o0 = static_cast<details::uv_base_node<Type>*>(branch[0])->operation();
+                details::operator_type o1 = static_cast<details::uv_base_node<Type>*>(branch[1])->operation();
+                const Type& v0 = static_cast<details::uv_base_node<Type>*>(branch[0])->v();
+                const Type& v1 = static_cast<details::uv_base_node<Type>*>(branch[1])->v();
+                unary_functor_t u0 = reinterpret_cast<unary_functor_t> (0);
+                unary_functor_t u1 = reinterpret_cast<unary_functor_t> (0);
+                binary_functor_t f = reinterpret_cast<binary_functor_t>(0);
+                
+                if (!valid_operator(o0,u0))
+                    return error_node();
+                else if (!valid_operator(o1,u1))
+                    return error_node();
+                else if (!valid_operator(operation,f))
+                    return error_node();
+                
+                expression_node_ptr result = error_node();
+                
+                if (
+                    (details::e_neg == o0) &&
+                    (details::e_neg == o1)
+                    )
+                {
+                    switch (operation)
+                    {
+                            // (-v0 + -v1) --> -(v0 + v1)
+                        case details::e_add : result = (*this)(details::e_neg,
+                                                               node_allocator_->
+                                                               allocate_rr<typename details::
+                                                               vov_node<Type,details::add_op<Type> > >(v0,v1));
+                            exprtk_debug(("(-v0 + -v1) --> -(v0 + v1)\n"));
+                            break;
+                            
+                            // (-v0 - -v1) --> (v1 - v0)
+                        case details::e_sub : result = node_allocator_->
+                            allocate_rr<typename details::
+                            vov_node<Type,details::sub_op<Type> > >(v1,v0);
+                            exprtk_debug(("(-v0 - -v1) --> (v1 - v0)\n"));
+                            break;
+                            
+                            // (-v0 * -v1) --> (v0 * v1)
+                        case details::e_mul : result = node_allocator_->
+                            allocate_rr<typename details::
+                            vov_node<Type,details::mul_op<Type> > >(v0,v1);
+                            exprtk_debug(("(-v0 * -v1) --> (v0 * v1)\n"));
+                            break;
+                            
+                            // (-v0 / -v1) --> (v0 / v1)
+                        case details::e_div : result = node_allocator_->
+                            allocate_rr<typename details::
+                            vov_node<Type,details::div_op<Type> > >(v0,v1);
+                            exprtk_debug(("(-v0 / -v1) --> (v0 / v1)\n"));
+                            break;
+                            
+                        default             : break;
+                    }
+                }
+                
+                if (0 == result)
+                {
+                    result = node_allocator_->
+                    allocate_rrrrr<typename details::uvouv_node<Type> >(v0,v1,u0,u1,f);
+                }
+                
+                details::free_all_nodes(*node_allocator_,branch);
+                return result;
+            }
+            
+#undef basic_opr_switch_statements
+#undef extended_opr_switch_statements
+#undef unary_opr_switch_statements
+            
+#ifndef exprtk_disable_string_capabilities
+            
+#define string_opr_switch_statements          \
+case_stmt(details::  e_lt ,details::   lt_op) \
+case_stmt(details:: e_lte ,details::  lte_op) \
+case_stmt(details::  e_gt ,details::   gt_op) \
+case_stmt(details:: e_gte ,details::  gte_op) \
+case_stmt(details::  e_eq ,details::   eq_op) \
+case_stmt(details::  e_ne ,details::   ne_op) \
+case_stmt(details::e_in   ,details::   in_op) \
+case_stmt(details::e_like ,details:: like_op) \
+case_stmt(details::e_ilike,details::ilike_op) \
+
+            template <typename T0, typename T1>
+            inline expression_node_ptr synthesize_str_xrox_expression_impl(const details::operator_type& opr,
+                                                                           T0 s0, T1 s1,
+                                                                           range_t rp0)
+            {
+                switch (opr)
+                {
+#define case_stmt(op0,op1)                                                                       \
+case op0 : return node_allocator_->                                                              \
+allocate_ttt<typename details::str_xrox_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \
+(s0,s1,rp0);                                                                    \
+
+                        string_opr_switch_statements
+#undef case_stmt
+                    default : return error_node();
+                }
+            }
+            
+            template <typename T0, typename T1>
+            inline expression_node_ptr synthesize_str_xoxr_expression_impl(const details::operator_type& opr,
+                                                                           T0 s0, T1 s1,
+                                                                           range_t rp1)
+            {
+                switch (opr)
+                {
+#define case_stmt(op0,op1)                                                                       \
+case op0 : return node_allocator_->                                                              \
+allocate_ttt<typename details::str_xoxr_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \
+(s0,s1,rp1);                                                                    \
+
+                        string_opr_switch_statements
+#undef case_stmt
+                    default : return error_node();
+                }
+            }
+            
+            template <typename T0, typename T1>
+            inline expression_node_ptr synthesize_str_xroxr_expression_impl(const details::operator_type& opr,
+                                                                            T0 s0, T1 s1,
+                                                                            range_t rp0, range_t rp1)
+            {
+                switch (opr)
+                {
+#define case_stmt(op0,op1)                                                                         \
+case op0 : return node_allocator_->                                                                \
+allocate_tttt<typename details::str_xroxr_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \
+(s0,s1,rp0,rp1);                                                                  \
+
+                        string_opr_switch_statements
+#undef case_stmt
+                    default : return error_node();
+                }
+            }
+            
+            template <typename T0, typename T1>
+            inline expression_node_ptr synthesize_sos_expression_impl(const details::operator_type& opr, T0 s0, T1 s1)
+            {
+                switch (opr)
+                {
+#define case_stmt(op0,op1)                                                                 \
+case op0 : return node_allocator_->                                                        \
+allocate_tt<typename details::sos_node<Type,T0,T1,op1<Type> >,T0,T1>(s0,s1); \
+
+                        string_opr_switch_statements
+#undef case_stmt
+                    default : return error_node();
+                }
+            }
+            
+            inline expression_node_ptr synthesize_sos_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
+            {
+                std::string& s0 = static_cast<details::stringvar_node<Type>*>(branch[0])->ref();
+                std::string& s1 = static_cast<details::stringvar_node<Type>*>(branch[1])->ref();
+                
+                return synthesize_sos_expression_impl<std::string&,std::string&>(opr,s0,s1);
+            }
+            
+            inline expression_node_ptr synthesize_sros_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
+            {
+                std::string&  s0 = static_cast<details::string_range_node<Type>*>(branch[0])->ref  ();
+                std::string&  s1 = static_cast<details::stringvar_node<Type>*>   (branch[1])->ref  ();
+                range_t      rp0 = static_cast<details::string_range_node<Type>*>(branch[0])->range();
+                
+                static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear();
+                
+                free_node(*node_allocator_,branch[0]);
+                
+                return synthesize_str_xrox_expression_impl<std::string&,std::string&>(opr,s0,s1,rp0);
+            }
+            
+            inline expression_node_ptr synthesize_sosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
+            {
+                std::string&  s0 = static_cast<details::stringvar_node<Type>*>   (branch[0])->ref  ();
+                std::string&  s1 = static_cast<details::string_range_node<Type>*>(branch[1])->ref  ();
+                range_t      rp1 = static_cast<details::string_range_node<Type>*>(branch[1])->range();
+                
+                static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear();
+                
+                free_node(*node_allocator_,branch[1]);
+                
+                return synthesize_str_xoxr_expression_impl<std::string&,std::string&>(opr,s0,s1,rp1);
+            }
+            
+            inline expression_node_ptr synthesize_socsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
+            {
+                std::string&  s0 = static_cast<details::stringvar_node<Type>*>         (branch[0])->ref  ();
+                std::string   s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str  ();
+                range_t      rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range();
+                
+                static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear();
+                
+                free_node(*node_allocator_,branch[1]);
+                
+                return synthesize_str_xoxr_expression_impl<std::string&, const std::string>(opr,s0,s1,rp1);
+            }
+            
+            inline expression_node_ptr synthesize_srosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
+            {
+                std::string&  s0 = static_cast<details::string_range_node<Type>*>(branch[0])->ref  ();
+                std::string&  s1 = static_cast<details::string_range_node<Type>*>(branch[1])->ref  ();
+                range_t      rp0 = static_cast<details::string_range_node<Type>*>(branch[0])->range();
+                range_t      rp1 = static_cast<details::string_range_node<Type>*>(branch[1])->range();
+                
+                static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear();
+                static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear();
+                
+                details::free_node(*node_allocator_,branch[0]);
+                details::free_node(*node_allocator_,branch[1]);
+                
+                return synthesize_str_xroxr_expression_impl<std::string&,std::string&>(opr,s0,s1,rp0,rp1);
+            }
+            
+            inline expression_node_ptr synthesize_socs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
+            {
+                std::string& s0 = static_cast<     details::stringvar_node<Type>*>(branch[0])->ref();
+                std::string  s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str();
+                
+                details::free_node(*node_allocator_,branch[1]);
+                
+                return synthesize_sos_expression_impl<std::string&, const std::string>(opr,s0,s1);
+            }
+            
+            inline expression_node_ptr synthesize_csos_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
+            {
+                std::string  s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
+                std::string& s1 = static_cast<     details::stringvar_node<Type>*>(branch[1])->ref();
+                
+                details::free_node(*node_allocator_,branch[0]);
+                
+                return synthesize_sos_expression_impl<const std::string,std::string&>(opr,s0,s1);
+            }
+            
+            inline expression_node_ptr synthesize_csosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
+            {
+                std::string   s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str  ();
+                std::string&  s1 = static_cast<details::string_range_node<Type>*>  (branch[1])->ref  ();
+                range_t      rp1 = static_cast<details::string_range_node<Type>*>  (branch[1])->range();
+                
+                static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear();
+                
+                details::free_node(*node_allocator_,branch[0]);
+                details::free_node(*node_allocator_,branch[1]);
+                
+                return synthesize_str_xoxr_expression_impl<const std::string,std::string&>(opr,s0,s1,rp1);
+            }
+            
+            inline expression_node_ptr synthesize_srocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
+            {
+                std::string&  s0 = static_cast<details::string_range_node<Type>*>  (branch[0])->ref  ();
+                std::string   s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str  ();
+                range_t      rp0 = static_cast<details::string_range_node<Type>*>  (branch[0])->range();
+                
+                static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear();
+                
+                details::free_node(*node_allocator_,branch[0]);
+                details::free_node(*node_allocator_,branch[1]);
+                
+                return synthesize_str_xrox_expression_impl<std::string&, const std::string>(opr,s0,s1,rp0);
+            }
+            
+            inline expression_node_ptr synthesize_srocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
+            {
+                std::string&  s0 = static_cast<details::string_range_node<Type>*>      (branch[0])->ref  ();
+                std::string   s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str  ();
+                range_t      rp0 = static_cast<details::string_range_node<Type>*>      (branch[0])->range();
+                range_t      rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range();
+                
+                static_cast<details::string_range_node<Type>*>      (branch[0])->range_ref().clear();
+                static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear();
+                
+                details::free_node(*node_allocator_,branch[0]);
+                details::free_node(*node_allocator_,branch[1]);
+                
+                return synthesize_str_xroxr_expression_impl<std::string&, const std::string>(opr,s0,s1,rp0,rp1);
+            }
+            
+            inline expression_node_ptr synthesize_csocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
+            {
+                const std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
+                const std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str();
+                
+                expression_node_ptr result = error_node();
+                
+                if (details::e_add == opr)
+                    result = node_allocator_->allocate_c<details::string_literal_node<Type> >(s0 + s1);
+                else if (details::e_in == opr)
+                    result = node_allocator_->allocate_c<details::literal_node<Type> >(details::in_op<Type>::process(s0,s1));
+                else if (details::e_like == opr)
+                    result = node_allocator_->allocate_c<details::literal_node<Type> >(details::like_op<Type>::process(s0,s1));
+                else if (details::e_ilike == opr)
+                    result = node_allocator_->allocate_c<details::literal_node<Type> >(details::ilike_op<Type>::process(s0,s1));
+                else
+                {
+                    expression_node_ptr temp = synthesize_sos_expression_impl<const std::string, const std::string>(opr,s0,s1);
+                    Type v = temp->value();
+                    details::free_node(*node_allocator_,temp);
+                    result = node_allocator_->allocate<literal_node_t>(v);
+                }
+                
+                details::free_all_nodes(*node_allocator_,branch);
+                
+                return result;
+            }
+            
+            inline expression_node_ptr synthesize_csocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
+            {
+                const std::string s0 = static_cast<details::string_literal_node<Type>*>    (branch[0])->str  ();
+                std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str  ();
+                range_t          rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range();
+                
+                static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear();
+                
+                free_node(*node_allocator_,branch[0]);
+                free_node(*node_allocator_,branch[1]);
+                
+                return synthesize_str_xoxr_expression_impl<const std::string, const std::string>(opr,s0,s1,rp1);
+            }
+            
+            inline expression_node_ptr synthesize_csros_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::stringvar_node<Type>*>         (branch[1])->ref  ();
+                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();
+                
+                free_node(*node_allocator_,branch[0]);
+                
+                return synthesize_str_xrox_expression_impl<const std::string,std::string&>(opr,s0,s1,rp0);
+            }
+            
+            inline expression_node_ptr synthesize_csrosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
+            {
+                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();
+                
+                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();
+                
+                free_node(*node_allocator_,branch[0]);
+                free_node(*node_allocator_,branch[1]);
+                
+                return synthesize_str_xroxr_expression_impl<const std::string,std::string&>(opr,s0,s1,rp0,rp1);
+            }
+            
+            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 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();
+                
+                static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear();
+                
+                details::free_all_nodes(*node_allocator_,branch);
+                
+                return synthesize_str_xrox_expression_impl<const std::string,std::string>(opr,s0,s1,rp0);
+            }
+            
+            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();
+                
+                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();
+                
+                details::free_all_nodes(*node_allocator_,branch);
+                
+                return synthesize_str_xroxr_expression_impl<const std::string, const std::string>(opr,s0,s1,rp0,rp1);
+            }
+            
+            inline expression_node_ptr synthesize_strogen_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
+            {
+                switch (opr)
+                {
+#define case_stmt(op0,op1)                                                       \
+case op0 : return node_allocator_->                                              \
+allocate_ttt<typename details::str_sogens_node<Type,op1<Type> > >  \
+(opr,branch[0],branch[1]);                                      \
+
+                        string_opr_switch_statements
+#undef case_stmt
+                    default : return error_node();
+                }
             }
-
-            clear_stack();
-
-            return (*this);
-         }
-
-         inline void pre()
-         {
-            if (stack_depth++)
-            {
-               if (!v.empty())
-               {
-                  var_t var_stack(v.size(),T(0));
-                  copy(v,var_stack);
-                  param_stack.push_back(var_stack);
-               }
-
-               if (!lv.empty())
-               {
-                  var_t local_var_stack(local_var_stack_size,T(0));
-                  copy(lv,local_var_stack);
-                  local_stack.push_back(local_var_stack);
-               }
-            }
-         }
-
-         inline void post()
-         {
-            if (--stack_depth)
-            {
-               if (!v.empty())
-               {
-                  copy(param_stack.back(),v);
-                  param_stack.pop_back();
-               }
-
-               if (!lv.empty())
-               {
-                  copy(local_stack.back(),lv);
-                  local_stack.pop_back();
-               }
+#endif
+            
+#ifndef exprtk_disable_string_capabilities
+            inline expression_node_ptr synthesize_string_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
+            {
+                if ((0 == branch[0]) || (0 == branch[1]))
+                {
+                    details::free_all_nodes(*node_allocator_,branch);
+                    
+                    return error_node();
+                }
+                
+                const bool b0_is_s   = details::is_string_node            (branch[0]);
+                const bool b0_is_cs  = details::is_const_string_node      (branch[0]);
+                const bool b0_is_sr  = details::is_string_range_node      (branch[0]);
+                const bool b0_is_csr = details::is_const_string_range_node(branch[0]);
+                
+                const bool b1_is_s   = details::is_string_node            (branch[1]);
+                const bool b1_is_cs  = details::is_const_string_node      (branch[1]);
+                const bool b1_is_sr  = details::is_string_range_node      (branch[1]);
+                const bool b1_is_csr = details::is_const_string_range_node(branch[1]);
+                
+                const bool b0_is_gen = details::is_string_assignment_node (branch[0]) ||
+                details::is_genricstring_range_node(branch[0]) ||
+                details::is_string_concat_node     (branch[0]) ||
+                details::is_string_function_node   (branch[0]) ||
+                details::is_string_condition_node  (branch[0]) ||
+                details::is_string_ccondition_node (branch[0]) ;
+                
+                const bool b1_is_gen = details::is_string_assignment_node (branch[1]) ||
+                details::is_genricstring_range_node(branch[1]) ||
+                details::is_string_concat_node     (branch[1]) ||
+                details::is_string_function_node   (branch[1]) ||
+                details::is_string_condition_node  (branch[1]) ||
+                details::is_string_ccondition_node (branch[1]) ;
+                
+                if (details::e_add == opr)
+                {
+                    if (!b0_is_cs || !b1_is_cs)
+                    {
+                        return synthesize_expression<string_concat_node_t,2>(opr,branch);
+                    }
+                }
+                
+                if (b0_is_gen || b1_is_gen)
+                {
+                    return synthesize_strogen_expression(opr,branch);
+                }
+                else if (b0_is_s)
+                {
+                    if (b1_is_s  ) return synthesize_sos_expression   (opr,branch);
+                    else if (b1_is_cs ) return synthesize_socs_expression  (opr,branch);
+                    else if (b1_is_sr ) return synthesize_sosr_expression  (opr,branch);
+                    else if (b1_is_csr) return synthesize_socsr_expression (opr,branch);
+                }
+                else if (b0_is_cs)
+                {
+                    if (b1_is_s  ) return synthesize_csos_expression  (opr,branch);
+                    else if (b1_is_cs ) return synthesize_csocs_expression (opr,branch);
+                    else if (b1_is_sr ) return synthesize_csosr_expression (opr,branch);
+                    else if (b1_is_csr) return synthesize_csocsr_expression(opr,branch);
+                }
+                else if (b0_is_sr)
+                {
+                    if (b1_is_s  ) return synthesize_sros_expression  (opr,branch);
+                    else if (b1_is_sr ) return synthesize_srosr_expression (opr,branch);
+                    else if (b1_is_cs ) return synthesize_srocs_expression (opr,branch);
+                    else if (b1_is_csr) return synthesize_srocsr_expression(opr,branch);
+                }
+                else if (b0_is_csr)
+                {
+                    if (b1_is_s  ) return synthesize_csros_expression  (opr,branch);
+                    else if (b1_is_sr ) return synthesize_csrosr_expression (opr,branch);
+                    else if (b1_is_cs ) return synthesize_csrocs_expression (opr,branch);
+                    else if (b1_is_csr) return synthesize_csrocsr_expression(opr,branch);
+                }
+                
+                return error_node();
             }
-         }
-
-         void copy(const varref_t& src_v, var_t& dest_v)
-         {
-            for (std::size_t i = 0; i < src_v.size(); ++i)
+#else
+            inline expression_node_ptr synthesize_string_expression(const details::operator_type&, expression_node_ptr (&branch)[2])
             {
-               dest_v[i] = (*src_v[i]);
+                details::free_all_nodes(*node_allocator_,branch);
+                return error_node();
             }
-         }
-
-         void copy(const var_t& src_v, varref_t& dest_v)
-         {
-            for (std::size_t i = 0; i < src_v.size(); ++i)
-            {
-               (*dest_v[i]) = src_v[i];
+#endif
+            
+#ifndef exprtk_disable_string_capabilities
+            inline expression_node_ptr synthesize_string_expression(const details::operator_type& opr, expression_node_ptr (&branch)[3])
+            {
+                if (details::e_inrange != opr)
+                    return error_node();
+                else if ((0 == branch[0]) || (0 == branch[1]) || (0 == branch[2]))
+                {
+                    details::free_all_nodes(*node_allocator_,branch);
+                    
+                    return error_node();
+                }
+                else if (
+                         details::is_const_string_node(branch[0]) &&
+                         details::is_const_string_node(branch[1]) &&
+                         details::is_const_string_node(branch[2])
+                         )
+                {
+                    const std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
+                    const std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str();
+                    const std::string s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str();
+                    
+                    Type v = (((s0 <= s1) && (s1 <= s2)) ? Type(1) : Type(0));
+                    details::free_all_nodes(*node_allocator_,branch);
+                    
+                    return node_allocator_->allocate_c<details::literal_node<Type> >(v);
+                }
+                else if (
+                         details::is_string_node(branch[0]) &&
+                         details::is_string_node(branch[1]) &&
+                         details::is_string_node(branch[2])
+                         )
+                {
+                    std::string& s0 = static_cast<details::stringvar_node<Type>*>(branch[0])->ref();
+                    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;
+                    
+                    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]) &&
+                         details::is_string_node(branch[1]) &&
+                         details::is_const_string_node(branch[2])
+                         )
+                {
+                    std::string  s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
+                    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;
+                    
+                    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);
+                }
+                else if (
+                         details::is_string_node(branch[0]) &&
+                         details::is_const_string_node(branch[1]) &&
+                         details::is_string_node(branch[2])
+                         )
+                {
+                    std::string&  s0 = static_cast<     details::stringvar_node<Type>*>(branch[0])->ref();
+                    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;
+                    
+                    details::free_node(*node_allocator_,branch[1]);
+                    
+                    return node_allocator_->allocate_type<inrange_t,std::string&,std::string,std::string&>(s0,s1,s2);
+                }
+                else if (
+                         details::is_string_node(branch[0]) &&
+                         details::is_string_node(branch[1]) &&
+                         details::is_const_string_node(branch[2])
+                         )
+                {
+                    std::string& s0 = static_cast<     details::stringvar_node<Type>*>(branch[0])->ref();
+                    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;
+                    
+                    details::free_node(*node_allocator_,branch[2]);
+                    
+                    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]) &&
+                         details::      is_string_node(branch[1]) &&
+                         details::      is_string_node(branch[2])
+                         )
+                {
+                    std::string  s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
+                    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;
+                    
+                    details::free_node(*node_allocator_,branch[0]);
+                    
+                    return node_allocator_->allocate_type<inrange_t,std::string,std::string&,std::string&>(s0,s1,s2);
+                }
+                else
+                    return error_node();
             }
-         }
-
-         void copy(const lvr_vec_t& src_v, var_t& dest_v)
-         {
-            typename var_t::iterator itr = dest_v.begin();
-
-            for (std::size_t i = 0; i < src_v.size(); ++i)
-            {
-               lvarref_t vr = src_v[i];
-
-               if (1 == vr.second)
-                  *itr++ = (*vr.first);
-               else
-               {
-                  std::copy(vr.first,vr.first + vr.second,itr);
-                  itr += vr.second;
-               }
-            }
-         }
-
-         void copy(const var_t& src_v, lvr_vec_t& dest_v)
-         {
-            typename var_t::const_iterator itr = src_v.begin();
-
-            for (std::size_t i = 0; i < src_v.size(); ++i)
-            {
-               lvarref_t vr = dest_v[i];
-
-               if (1 == vr.second)
-                  (*vr.first) = *itr++;
-               else
-               {
-                  std::copy(itr,itr + vr.second,vr.first);
-                  itr += vr.second;
-               }
-            }
-         }
-
-         inline void clear_stack()
-         {
-            for (std::size_t i = 0; i < v.size(); ++i)
+#else
+            inline expression_node_ptr synthesize_string_expression(const details::operator_type&, expression_node_ptr (&branch)[3])
             {
-               (*v[i]) = 0;
+                details::free_all_nodes(*node_allocator_,branch);
+                return error_node();
             }
-         }
-
-         expression_t expression;
-         varref_t v;
-         lvr_vec_t lv;
-         std::size_t local_var_stack_size;
-         std::size_t stack_depth;
-         std::deque<var_t> param_stack;
-         std::deque<var_t> local_stack;
-      };
-
-      typedef std::map<std::string,base_func*> funcparam_t;
-
-      struct func_0param : public base_func
-      {
-         func_0param() : base_func(0) {}
-
-         inline T operator()()
-         {
-            return base_func::expression.value();
-         }
-      };
-
-      typedef const T& type;
-
-      struct func_1param : public base_func
-      {
-         func_1param() : base_func(1) {}
-
-         inline T operator()(type v0)
-         {
-            base_func::pre();
-            base_func::update(v0);
-            T result = base_func::expression.value();
-            base_func::post();
-            return result;
-         }
-      };
-
-      struct func_2param : public base_func
-      {
-         func_2param() : base_func(2) {}
-
-         inline T operator()(type v0, type v1)
-         {
-            base_func::pre();
-            base_func::update(v0,v1);
-            T result = base_func::expression.value();
-            base_func::post();
-            return result;
-         }
-      };
-
-      struct func_3param : public base_func
-      {
-         func_3param() : base_func(3) {}
-
-         inline T operator()(type v0, type v1, type v2)
-         {
-            base_func::pre();
-            base_func::update(v0,v1,v2);
-            T result = base_func::expression.value();
-            base_func::post();
+#endif
+            
+            inline expression_node_ptr synthesize_null_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
+            {
+                /*
+                 Note: The following are the type promotion rules
+                 that relate to operations that include 'null':
+                 0. null ==/!=     null --> true false
+                 1. null operation null --> null
+                 2. x    ==/!=     null --> true/false
+                 3. null ==/!=     x    --> true/false
+                 4. x   operation  null --> x
+                 5. null operation x    --> x
+                 */
+                
+                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]);
+                
+                if (b0_null && b1_null)
+                {
+                    expression_node_ptr result = error_node();
+                    
+                    if (details::e_eq == operation)
+                        result = node_allocator_->allocate_c<literal_node_t>(T(1));
+                    else if (details::e_ne == operation)
+                        result = node_allocator_->allocate_c<literal_node_t>(T(0));
+                    
+                    if (result)
+                    {
+                        details::free_node(*node_allocator_,branch[0]);
+                        details::free_node(*node_allocator_,branch[1]);
+                        
+                        return result;
+                    }
+                    
+                    details::free_node(*node_allocator_,branch[1]);
+                    
+                    return branch[0];
+                }
+                else if (details::e_eq == operation)
+                {
+                    expression_node_ptr result = node_allocator_->
+                    allocate_rc<nulleq_node_t>(branch[b0_null ? 0 : 1],true);
+                    
+                    details::free_node(*node_allocator_,branch[b0_null ? 1 : 0]);
+                    
+                    return result;
+                }
+                else if (details::e_ne == operation)
+                {
+                    expression_node_ptr result = node_allocator_->
+                    allocate_rc<nulleq_node_t>(branch[b0_null ? 0 : 1],false);
+                    
+                    details::free_node(*node_allocator_,branch[b0_null ? 1 : 0]);
+                    
+                    return result;
+                }
+                else if (b0_null)
+                {
+                    details::free_node(*node_allocator_,branch[0]);
+                    branch[0] = branch[1];
+                    branch[1] = error_node();
+                }
+                else if (b1_null)
+                {
+                    details::free_node(*node_allocator_,branch[1]);
+                    branch[1] = error_node();
+                }
+                
+                if (
+                    (details::e_add == operation) || (details::e_sub == operation) ||
+                    (details::e_mul == operation) || (details::e_div == operation) ||
+                    (details::e_mod == operation) || (details::e_pow == operation)
+                    )
+                {
+                    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)
+                         )
+                {
+                    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> >();
+            }
+            
+            template <typename NodeType, std::size_t N>
+            inline expression_node_ptr synthesize_expression(const details::operator_type& operation, expression_node_ptr (&branch)[N])
+            {
+                if (
+                    (details::e_in    == operation) ||
+                    (details::e_like  == operation) ||
+                    (details::e_ilike == operation)
+                    )
+                    return error_node();
+                else if (!details::all_nodes_valid<N>(branch))
+                {
+                    free_all_nodes(*node_allocator_,branch);
+                    
+                    return error_node();
+                }
+                else if ((details::e_default != operation))
+                {
+                    // Attempt simple constant folding optimisation.
+                    expression_node_ptr expression_point = node_allocator_->allocate<NodeType>(operation,branch);
+                    
+                    if (is_constant_foldable<N>(branch))
+                    {
+                        Type v = expression_point->value();
+                        details::free_node(*node_allocator_,expression_point);
+                        
+                        return node_allocator_->allocate<literal_node_t>(v);
+                    }
+                    else
+                        return expression_point;
+                }
+                else
+                    return error_node();
+            }
+            
+            template <typename NodeType, std::size_t N>
+            inline expression_node_ptr synthesize_expression(F* f, expression_node_ptr (&branch)[N])
+            {
+                if (!details::all_nodes_valid<N>(branch))
+                {
+                    free_all_nodes(*node_allocator_,branch);
+                    
+                    return error_node();
+                }
+                
+                typedef typename details::function_N_node<T,ifunction_t,N> function_N_node_t;
+                
+                // Attempt simple constant folding optimisation.
+                
+                expression_node_ptr expression_point = node_allocator_->allocate<NodeType>(f);
+                function_N_node_t* func_node_ptr = dynamic_cast<function_N_node_t*>(expression_point);
+                
+                if (0 == func_node_ptr)
+                {
+                    free_all_nodes(*node_allocator_,branch);
+                    
+                    return error_node();
+                }
+                else
+                    func_node_ptr->init_branches(branch);
+                
+                if (is_constant_foldable<N>(branch) && !f->has_side_effects())
+                {
+                    Type v = expression_point->value();
+                    details::free_node(*node_allocator_,expression_point);
+                    
+                    return node_allocator_->allocate<literal_node_t>(v);
+                }
+                
+                parser_->state_.activate_side_effect("synthesize_expression(function<NT,N>)");
+                
+                return expression_point;
+            }
+            
+            bool strength_reduction_enabled_;
+            details::node_allocator* node_allocator_;
+            synthesize_map_t synthesize_map_;
+            unary_op_map_t* unary_op_map_;
+            binary_op_map_t* binary_op_map_;
+            inv_binary_op_map_t* inv_binary_op_map_;
+            sf3_map_t* sf3_map_;
+            sf4_map_t* sf4_map_;
+            parser_t* parser_;
+        };
+        
+        inline void set_error(const parser_error::type& error_type)
+        {
+            error_list_.push_back(error_type);
+        }
+        
+        inline void remove_last_error()
+        {
+            if (!error_list_.empty())
+            {
+                error_list_.pop_back();
+            }
+        }
+        
+        inline void set_synthesis_error(const std::string& synthesis_error_message)
+        {
+            if (synthesis_error_.empty())
+            {
+                synthesis_error_ = synthesis_error_message;
+            }
+        }
+        
+        inline void register_local_vars(expression<T>& e)
+        {
+            for (std::size_t i = 0; i < sem_.size(); ++i)
+            {
+                scope_element& se = sem_.get_element(i);
+                
+                if (
+                    (scope_element::e_variable == se.type) ||
+                    (scope_element::e_vecelem  == se.type)
+                    )
+                {
+                    if (se.var_node)
+                    {
+                        e.register_local_var(se.var_node);
+                    }
+                    
+                    if (se.data)
+                    {
+                        e.register_local_data(se.data,1,0);
+                    }
+                }
+                else if (scope_element::e_vector == se.type)
+                {
+                    if (se.vec_node)
+                    {
+                        e.register_local_var(se.vec_node);
+                    }
+                    
+                    if (se.data)
+                    {
+                        e.register_local_data(se.data,se.size,1);
+                    }
+                }
+#ifndef exprtk_disable_string_capabilities
+                else if (scope_element::e_string == se.type)
+                {
+                    if (se.str_node)
+                    {
+                        e.register_local_var(se.str_node);
+                    }
+                    
+                    if (se.data)
+                    {
+                        e.register_local_data(se.data,se.size,2);
+                    }
+                }
+#endif
+                
+                se.var_node  = 0;
+                se.vec_node  = 0;
+#ifndef exprtk_disable_string_capabilities
+                se.str_node  = 0;
+#endif
+                se.data      = 0;
+                se.ref_count = 0;
+                se.active    = false;
+            }
+        }
+        
+        inline void register_return_results(expression<T>& e)
+        {
+            e.register_return_results(results_context_);
+            results_context_ = 0;
+        }
+        
+        inline void load_unary_operations_map(unary_op_map_t& m)
+        {
+#define register_unary_op(Op,UnaryFunctor)             \
+m.insert(std::make_pair(Op,UnaryFunctor<T>::process)); \
+
+            register_unary_op(details::  e_abs,details::  abs_op)
+            register_unary_op(details:: e_acos,details:: acos_op)
+            register_unary_op(details::e_acosh,details::acosh_op)
+            register_unary_op(details:: e_asin,details:: asin_op)
+            register_unary_op(details::e_asinh,details::asinh_op)
+            register_unary_op(details::e_atanh,details::atanh_op)
+            register_unary_op(details:: e_ceil,details:: ceil_op)
+            register_unary_op(details::  e_cos,details::  cos_op)
+            register_unary_op(details:: e_cosh,details:: cosh_op)
+            register_unary_op(details::  e_exp,details::  exp_op)
+            register_unary_op(details::e_expm1,details::expm1_op)
+            register_unary_op(details::e_floor,details::floor_op)
+            register_unary_op(details::  e_log,details::  log_op)
+            register_unary_op(details::e_log10,details::log10_op)
+            register_unary_op(details:: e_log2,details:: log2_op)
+            register_unary_op(details::e_log1p,details::log1p_op)
+            register_unary_op(details::  e_neg,details::  neg_op)
+            register_unary_op(details::  e_pos,details::  pos_op)
+            register_unary_op(details::e_round,details::round_op)
+            register_unary_op(details::  e_sin,details::  sin_op)
+            register_unary_op(details:: e_sinc,details:: sinc_op)
+            register_unary_op(details:: e_sinh,details:: sinh_op)
+            register_unary_op(details:: e_sqrt,details:: sqrt_op)
+            register_unary_op(details::  e_tan,details::  tan_op)
+            register_unary_op(details:: e_tanh,details:: tanh_op)
+            register_unary_op(details::  e_cot,details::  cot_op)
+            register_unary_op(details::  e_sec,details::  sec_op)
+            register_unary_op(details::  e_csc,details::  csc_op)
+            register_unary_op(details::  e_r2d,details::  r2d_op)
+            register_unary_op(details::  e_d2r,details::  d2r_op)
+            register_unary_op(details::  e_d2g,details::  d2g_op)
+            register_unary_op(details::  e_g2d,details::  g2d_op)
+            register_unary_op(details:: e_notl,details:: notl_op)
+            register_unary_op(details::  e_sgn,details::  sgn_op)
+            register_unary_op(details::  e_erf,details::  erf_op)
+            register_unary_op(details:: e_erfc,details:: erfc_op)
+            register_unary_op(details:: e_ncdf,details:: ncdf_op)
+            register_unary_op(details:: e_frac,details:: frac_op)
+            register_unary_op(details::e_trunc,details::trunc_op)
+#undef register_unary_op
+        }
+        
+        inline void load_binary_operations_map(binary_op_map_t& m)
+        {
+            typedef typename binary_op_map_t::value_type value_type;
+            
+#define register_binary_op(Op,BinaryFunctor)        \
+m.insert(value_type(Op,BinaryFunctor<T>::process)); \
+
+            register_binary_op(details:: e_add,details:: add_op)
+            register_binary_op(details:: e_sub,details:: sub_op)
+            register_binary_op(details:: e_mul,details:: mul_op)
+            register_binary_op(details:: e_div,details:: div_op)
+            register_binary_op(details:: e_mod,details:: mod_op)
+            register_binary_op(details:: e_pow,details:: pow_op)
+            register_binary_op(details::  e_lt,details::  lt_op)
+            register_binary_op(details:: e_lte,details:: lte_op)
+            register_binary_op(details::  e_gt,details::  gt_op)
+            register_binary_op(details:: e_gte,details:: gte_op)
+            register_binary_op(details::  e_eq,details::  eq_op)
+            register_binary_op(details::  e_ne,details::  ne_op)
+            register_binary_op(details:: e_and,details:: and_op)
+            register_binary_op(details::e_nand,details::nand_op)
+            register_binary_op(details::  e_or,details::  or_op)
+            register_binary_op(details:: e_nor,details:: nor_op)
+            register_binary_op(details:: e_xor,details:: xor_op)
+            register_binary_op(details::e_xnor,details::xnor_op)
+#undef register_binary_op
+        }
+        
+        inline void load_inv_binary_operations_map(inv_binary_op_map_t& m)
+        {
+            typedef typename inv_binary_op_map_t::value_type value_type;
+            
+#define register_binary_op(Op,BinaryFunctor)        \
+m.insert(value_type(BinaryFunctor<T>::process,Op)); \
+
+            register_binary_op(details:: e_add,details:: add_op)
+            register_binary_op(details:: e_sub,details:: sub_op)
+            register_binary_op(details:: e_mul,details:: mul_op)
+            register_binary_op(details:: e_div,details:: div_op)
+            register_binary_op(details:: e_mod,details:: mod_op)
+            register_binary_op(details:: e_pow,details:: pow_op)
+            register_binary_op(details::  e_lt,details::  lt_op)
+            register_binary_op(details:: e_lte,details:: lte_op)
+            register_binary_op(details::  e_gt,details::  gt_op)
+            register_binary_op(details:: e_gte,details:: gte_op)
+            register_binary_op(details::  e_eq,details::  eq_op)
+            register_binary_op(details::  e_ne,details::  ne_op)
+            register_binary_op(details:: e_and,details:: and_op)
+            register_binary_op(details::e_nand,details::nand_op)
+            register_binary_op(details::  e_or,details::  or_op)
+            register_binary_op(details:: e_nor,details:: nor_op)
+            register_binary_op(details:: e_xor,details:: xor_op)
+            register_binary_op(details::e_xnor,details::xnor_op)
+#undef register_binary_op
+        }
+        
+        inline void load_sf3_map(sf3_map_t& sf3_map)
+        {
+            typedef std::pair<trinary_functor_t,details::operator_type> pair_t;
+            
+#define register_sf3(Op)                                                                             \
+sf3_map[details::sf##Op##_op<T>::id()] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \
+
+            register_sf3(00) register_sf3(01) register_sf3(02) register_sf3(03)
+            register_sf3(04) register_sf3(05) register_sf3(06) register_sf3(07)
+            register_sf3(08) register_sf3(09) register_sf3(10) register_sf3(11)
+            register_sf3(12) register_sf3(13) register_sf3(14) register_sf3(15)
+            register_sf3(16) register_sf3(17) register_sf3(18) register_sf3(19)
+            register_sf3(20) register_sf3(21) register_sf3(22) register_sf3(23)
+            register_sf3(24) register_sf3(25) register_sf3(26) register_sf3(27)
+            register_sf3(28) register_sf3(29) register_sf3(30)
+#undef register_sf3
+        }
+        
+        inline void load_sf4_map(sf4_map_t& sf4_map)
+        {
+            typedef std::pair<quaternary_functor_t,details::operator_type> pair_t;
+            
+#define register_sf4(Op)                                                                             \
+sf4_map[details::sf##Op##_op<T>::id()] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \
+
+            register_sf4(48) register_sf4(49) register_sf4(50) register_sf4(51)
+            register_sf4(52) register_sf4(53) register_sf4(54) register_sf4(55)
+            register_sf4(56) register_sf4(57) register_sf4(58) register_sf4(59)
+            register_sf4(60) register_sf4(61) register_sf4(62) register_sf4(63)
+            register_sf4(64) register_sf4(65) register_sf4(66) register_sf4(67)
+            register_sf4(68) register_sf4(69) register_sf4(70) register_sf4(71)
+            register_sf4(72) register_sf4(73) register_sf4(74) register_sf4(75)
+            register_sf4(76) register_sf4(77) register_sf4(78) register_sf4(79)
+            register_sf4(80) register_sf4(81) register_sf4(82) register_sf4(83)
+#undef register_sf4
+            
+#define register_sf4ext(Op)                                                                                    \
+sf4_map[details::sfext##Op##_op<T>::id()] = pair_t(details::sfext##Op##_op<T>::process,details::e_sf4ext##Op); \
+
+            register_sf4ext(00) register_sf4ext(01) register_sf4ext(02) register_sf4ext(03)
+            register_sf4ext(04) register_sf4ext(05) register_sf4ext(06) register_sf4ext(07)
+            register_sf4ext(08) register_sf4ext(09) register_sf4ext(10) register_sf4ext(11)
+            register_sf4ext(12) register_sf4ext(13) register_sf4ext(14) register_sf4ext(15)
+            register_sf4ext(16) register_sf4ext(17) register_sf4ext(18) register_sf4ext(19)
+            register_sf4ext(20) register_sf4ext(21) register_sf4ext(22) register_sf4ext(23)
+            register_sf4ext(24) register_sf4ext(25) register_sf4ext(26) register_sf4ext(27)
+            register_sf4ext(28) register_sf4ext(29) register_sf4ext(30) register_sf4ext(31)
+            register_sf4ext(32) register_sf4ext(33) register_sf4ext(34) register_sf4ext(35)
+            register_sf4ext(36) register_sf4ext(36) register_sf4ext(38) register_sf4ext(39)
+            register_sf4ext(40) register_sf4ext(41) register_sf4ext(42) register_sf4ext(43)
+            register_sf4ext(44) register_sf4ext(45) register_sf4ext(46) register_sf4ext(47)
+            register_sf4ext(48) register_sf4ext(49) register_sf4ext(50) register_sf4ext(51)
+            register_sf4ext(52) register_sf4ext(53) register_sf4ext(54) register_sf4ext(55)
+            register_sf4ext(56) register_sf4ext(57) register_sf4ext(58) register_sf4ext(59)
+            register_sf4ext(60)
+#undef register_sf4ext
+        }
+        
+        inline results_context_t& results_ctx()
+        {
+            if (0 == results_context_)
+            {
+                results_context_ = new results_context_t();
+            }
+            
+            return (*results_context_);
+        }
+        
+        inline void return_cleanup()
+        {
+            if (results_context_)
+            {
+                delete results_context_;
+                results_context_ = 0;
+            }
+            
+            state_.return_stmt_present = false;
+        }
+        
+    private:
+        
+        parser(const parser<T>&);
+        parser<T>& operator=(const parser<T>&);
+        
+        settings_store settings_;
+        expression_generator<T> expression_generator_;
+        details::node_allocator node_allocator_;
+        symtab_store symtab_store_;
+        dependent_entity_collector dec_;
+        std::deque<parser_error::type> error_list_;
+        std::deque<bool> brkcnt_list_;
+        parser_state state_;
+        bool resolve_unknown_symbol_;
+        results_context_t* results_context_;
+        unknown_symbol_resolver* unknown_symbol_resolver_;
+        unknown_symbol_resolver default_usr_;
+        base_ops_map_t base_ops_map_;
+        unary_op_map_t unary_op_map_;
+        binary_op_map_t binary_op_map_;
+        inv_binary_op_map_t inv_binary_op_map_;
+        sf3_map_t sf3_map_;
+        sf4_map_t sf4_map_;
+        std::string synthesis_error_;
+        scope_element_manager sem_;
+        
+        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_;
+    };
+    
+    template <typename T>
+    inline T integrate(const expression<T>& e,
+                       T& x,
+                       const T& r0, const T& r1,
+                       const std::size_t number_of_intervals = 1000000)
+    {
+        if (r0 > r1)
+            return T(0);
+        
+        T h = (r1 - r0) / (T(2) * number_of_intervals);
+        T total_area = T(0);
+        
+        for (std::size_t i = 0; i < number_of_intervals; ++i)
+        {
+            x = r0 + T(2) * i * h;
+            T y0 = e.value(); x += h;
+            T y1 = e.value(); x += h;
+            T y2 = e.value(); x += h;
+            total_area += h * (y0 + T(4) * y1 + y2) / T(3);
+        }
+        
+        return total_area;
+    }
+    
+    template <typename T>
+    inline T integrate(const expression<T>& e,
+                       const std::string& variable_name,
+                       const T& r0, const T& r1,
+                       const std::size_t number_of_intervals = 1000000)
+    {
+        const symbol_table<T>& sym_table = e.get_symbol_table();
+        
+        if (!sym_table.valid())
+            return std::numeric_limits<T>::quiet_NaN();
+        
+        details::variable_node<T>* var = sym_table.get_variable(variable_name);
+        
+        if (var)
+        {
+            T& x = var->ref();
+            T  x_original = x;
+            T result = integrate(e,x,r0,r1,number_of_intervals);
+            x = x_original;
+            
             return result;
-         }
-      };
-
-      struct func_4param : public base_func
-      {
-         func_4param() : base_func(4) {}
-
-         inline T operator()(type v0, type v1, type v2, type v3)
-         {
-            base_func::pre();
-            base_func::update(v0,v1,v2,v3);
-            T result = base_func::expression.value();
-            base_func::post();
+        }
+        else
+            return std::numeric_limits<T>::quiet_NaN();
+    }
+    
+    template <typename T>
+    inline T derivative(const expression<T>& e,
+                        T& x,
+                        const T& h = T(0.00000001))
+    {
+        T x_init = x;
+        x = x_init + T(2) * h;
+        T y0 = e.value();
+        x = x_init + h;
+        T y1 = e.value();
+        x = x_init - h;
+        T y2 = e.value();
+        x = x_init - T(2) * h;
+        T y3 = e.value();
+        x = x_init;
+        
+        return (-y0 + T(8) * (y1 - y2) + y3) / (T(12) * h);
+    }
+    
+    template <typename T>
+    inline T second_derivative(const expression<T>& e,
+                               T& x,
+                               const T& h = T(0.00001))
+    {
+        T y = e.value();
+        T x_init = x;
+        x = x_init + T(2) * h;
+        T y0 = e.value();
+        x = x_init + h;
+        T y1 = e.value();
+        x = x_init - h;
+        T y2 = e.value();
+        x = x_init - T(2) * h;
+        T y3 = e.value();
+        x = x_init;
+        
+        return (-y0 + T(16) * (y1 + y2) - T(30) * y - y3) / (T(12) * h * h);
+    }
+    
+    template <typename T>
+    inline T third_derivative(const expression<T>& e,
+                              T& x,
+                              const T& h = T(0.0001))
+    {
+        T x_init = x;
+        x = x_init + T(2) * h;
+        T y0 = e.value();
+        x = x_init + h;
+        T y1 = e.value();
+        x = x_init - h;
+        T y2 = e.value();
+        x = x_init - T(2) * h;
+        T y3 = e.value();
+        x = x_init;
+        
+        return (y0 + T(2) * (y2 - y1) - y3) / (T(2) * h * h * h);
+    }
+    
+    template <typename T>
+    inline T derivative(const expression<T>& e,
+                        const std::string& variable_name,
+                        const T& h = T(0.00000001))
+    {
+        const symbol_table<T>& sym_table = e.get_symbol_table();
+        
+        if (!sym_table.valid())
+        {
+            return std::numeric_limits<T>::quiet_NaN();
+        }
+        
+        details::variable_node<T>* var = sym_table.get_variable(variable_name);
+        
+        if (var)
+        {
+            T& x = var->ref();
+            T x_original = x;
+            T result = derivative(e,x,h);
+            x = x_original;
+            
             return result;
-         }
-      };
-
-      struct func_5param : public base_func
-      {
-         func_5param() : base_func(5) {}
-
-         inline T operator()(type v0, type v1, type v2, type v3, type v4)
-         {
-            base_func::pre();
-            base_func::update(v0,v1,v2,v3,v4);
-            T result = base_func::expression.value();
-            base_func::post();
+        }
+        else
+            return std::numeric_limits<T>::quiet_NaN();
+    }
+    
+    template <typename T>
+    inline T second_derivative(const expression<T>& e,
+                               const std::string& variable_name,
+                               const T& h = T(0.00001))
+    {
+        const symbol_table<T>& sym_table = e.get_symbol_table();
+        
+        if (!sym_table.valid())
+        {
+            return std::numeric_limits<T>::quiet_NaN();
+        }
+        
+        details::variable_node<T>* var = sym_table.get_variable(variable_name);
+        
+        if (var)
+        {
+            T& x = var->ref();
+            T x_original = x;
+            T result = second_derivative(e,x,h);
+            x = x_original;
+            
             return result;
-         }
-      };
-
-      struct func_6param : public base_func
-      {
-         func_6param() : base_func(6) {}
-
-         inline T operator()(type v0, type v1, type v2, type v3, type v4, type v5)
-         {
-            base_func::pre();
-            base_func::update(v0,v1,v2,v3,v4,v5);
-            T result = base_func::expression.value();
-            base_func::post();
+        }
+        else
+            return std::numeric_limits<T>::quiet_NaN();
+    }
+    
+    template <typename T>
+    inline T third_derivative(const expression<T>& e,
+                              const std::string& variable_name,
+                              const T& h = T(0.0001))
+    {
+        const symbol_table<T>& sym_table = e.get_symbol_table();
+        
+        if (!sym_table.valid())
+        {
+            return std::numeric_limits<T>::quiet_NaN();
+        }
+        
+        details::variable_node<T>* var = sym_table.get_variable(variable_name);
+        
+        if (var)
+        {
+            T& x = var->ref();
+            T x_original = x;
+            T result = third_derivative(e,x,h);
+            x = x_original;
+            
             return result;
-         }
-      };
-
-      template <typename Allocator,
-                template <typename,typename> class Sequence>
-      inline bool add(const std::string& name,
-                      const std::string& expression,
-                      const Sequence<std::string,Allocator>& var_list)
-      {
-         const std::size_t n = var_list.size();
-
-         if (expr_map_.end() != expr_map_.find(name))
-            return false;
-         else if (compile_expression(name,expression,var_list))
-         {
-            fp_map_[n][name]->setup(expr_map_[name]);
+        }
+        else
+            return std::numeric_limits<T>::quiet_NaN();
+    }
+    
+    /*
+     Note: The following 'compute' routines are simple helpers,
+     for quickly setting up the required pieces of code in order
+     to evaluate an expression. By virtue of how they operate
+     there will be an overhead with regards to their setup and
+     teardown and hence should not be used in time critical
+     sections of code.
+     Furthermore they only assume a small sub set of variables - no
+     string variables or user defined functions.
+     */
+    template <typename T>
+    inline bool compute(const std::string& expression_string, T& result)
+    {
+        // No variables
+        symbol_table<T> symbol_table;
+        symbol_table.add_constants();
+        
+        expression<T> expression;
+        parser<T> parser;
+        
+        if (parser.compile(expression_string,expression))
+        {
+            result = expression.value();
+            
             return true;
-         }
-         else
-            return false;
-      }
-
-   public:
-
-      function_compositor()
-      : fp_map_(7)
-      {}
-
-      function_compositor(const symbol_table_t& st)
-      : symbol_table_(st),
-        fp_map_(7)
-      {}
-
-     ~function_compositor()
-      {
-         clear();
-      }
-
-      inline symbol_table_t& symbol_table()
-      {
-         return symbol_table_;
-      }
-
-      void clear()
-      {
-         symbol_table_.clear();
-         expr_map_.clear();
-
-         for (std::size_t i = 0; i < fp_map_.size(); ++i)
-         {
-            typename funcparam_t::iterator itr = fp_map_[i].begin();
-            typename funcparam_t::iterator end = fp_map_[i].end  ();
-
-            while (itr != end)
-            {
-               delete itr->second;
-               ++itr;
-            }
-
-            fp_map_[i].clear();
-         }
-      }
-
-      inline bool add(const function& f)
-      {
-         return add(f.name_,f.expression_,f.v_);
-      }
-
-      inline bool add(const std::string& name,
-                      const std::string& expression)
-      {
-         const std::size_t n = 0;
-         std::vector<std::string> v(n);
-         return add(name,expression,v);
-      }
-
-      inline bool add(const std::string& name,
-                      const std::string& expression,
-                      const std::string& v0)
-      {
-         const std::size_t n = 1;
-         std::vector<std::string> v(n);
-         v[0] = v0;
-         return add(name,expression,v);
-      }
-
-      inline bool add(const std::string& name,
-                      const std::string& expression,
-                      const std::string& v0, const std::string& v1)
-      {
-         const std::size_t n = 2;
-         std::vector<std::string> v(n);
-         v[0] = v0; v[1] = v1;
-         return add(name,expression,v);
-      }
-
-      inline bool add(const std::string& name,
-                      const std::string& expression,
-                      const std::string& v0, const std::string& v1, const std::string& v2)
-      {
-         const std::size_t n = 3;
-         std::vector<std::string> v(n);
-         v[0] = v0; v[1] = v1; v[2] = v2;
-         return add(name,expression,v);
-      }
-
-      inline bool add(const std::string& name,
-                      const std::string& expression,
-                      const std::string& v0, const std::string& v1, const std::string& v2,
-                      const std::string& v3)
-      {
-         const std::size_t n = 4;
-         std::vector<std::string> v(n);
-         v[0] = v0; v[1] = v1;
-         v[2] = v2; v[3] = v3;
-         return add(name,expression,v);
-      }
-
-      inline bool add(const std::string& name,
-                      const std::string& expression,
-                      const std::string& v0, const std::string& v1, const std::string& v2,
-                      const std::string& v3, const std::string& v4)
-      {
-         const std::size_t n = 5;
-         std::vector<std::string> v(n);
-         v[0] = v0; v[1] = v1;
-         v[2] = v2; v[3] = v3;
-         v[4] = v4;
-         return add(name,expression,v);
-      }
-
-      inline bool add(const std::string& name,
-                      const std::string& expression,
-                      const std::string& v0, const std::string& v1, const std::string& v2,
-                      const std::string& v3, const std::string& v4, const std::string& v5)
-      {
-         const std::size_t n = 5;
-         std::vector<std::string> v(n);
-         v[0] = v0; v[1] = v1;
-         v[2] = v2; v[3] = v3;
-         v[4] = v4; v[5] = v5;
-         return add(name,expression,v);
-      }
-
-   private:
-
-      template <typename Allocator,
-                template <typename,typename> class Sequence>
-      bool compile_expression(const std::string& name,
-                              const std::string& expression,
-                              const Sequence<std::string,Allocator>& input_var_list)
-      {
-         expression_t compiled_expression;
-         symbol_table_t local_symbol_table;
-
-         local_symbol_table.load_from(symbol_table_);
-         local_symbol_table.add_constants();
-
-         if (!forward(name,input_var_list.size(),local_symbol_table))
+        }
+        else
             return false;
-
-         compiled_expression.register_symbol_table(local_symbol_table);
-
-         std::string mod_expression;
-
-         for (std::size_t i = 0; i < input_var_list.size(); ++i)
-         {
-            mod_expression += " var " + input_var_list[i] + "{};\n";
-         }
-
-         mod_expression += "~{" + expression + "};";
-
-         if (!parser_.compile(mod_expression,compiled_expression))
-         {
-            exprtk_debug(("Error: %s\n",parser_.error().c_str()));
+    }
+    
+    template <typename T>
+    inline bool compute(const std::string& expression_string,
+                        const T& x,
+                        T& result)
+    {
+        // Only 'x'
+        static const std::string x_var("x");
+        
+        symbol_table<T> symbol_table;
+        symbol_table.add_constants();
+        symbol_table.add_variable(x_var,x);
+        
+        expression<T> expression;
+        parser<T> parser;
+        
+        if (parser.compile(expression_string,expression))
+        {
+            result = expression.value();
+            
+            return true;
+        }
+        else
             return false;
-         }
-
-         expr_map_[name] = compiled_expression;
-
-         exprtk::ifunction<T>& ifunc = (*(fp_map_[input_var_list.size()])[name]);
-
-         return symbol_table_.add_function(name,ifunc);
-      }
-
-      inline bool symbol_used(const std::string& symbol)
-      {
-         return (
-                  symbol_table_.is_variable       (symbol) ||
-                  symbol_table_.is_stringvar      (symbol) ||
-                  symbol_table_.is_function       (symbol) ||
-                  symbol_table_.is_vector         (symbol) ||
-                  symbol_table_.is_vararg_function(symbol)
-                );
-      }
-
-      inline bool forward(const std::string& name, const std::size_t& arg_count, symbol_table_t& sym_table)
-      {
-         if (arg_count > 6)
+    }
+    
+    template <typename T>
+    inline bool compute(const std::string& expression_string,
+                        const T&x, const T& y,
+                        T& result)
+    {
+        // Only 'x' and 'y'
+        static const std::string x_var("x");
+        static const std::string y_var("y");
+        
+        symbol_table<T> symbol_table;
+        symbol_table.add_constants();
+        symbol_table.add_variable(x_var,x);
+        symbol_table.add_variable(y_var,y);
+        
+        expression<T> expression;
+        parser<T> parser;
+        
+        if (parser.compile(expression_string,expression))
+        {
+            result = expression.value();
+            
+            return true;
+        }
+        else
             return false;
-         else if (symbol_used(name))
+    }
+    
+    template <typename T>
+    inline bool compute(const std::string& expression_string,
+                        const T& x, const T& y, const T& z,
+                        T& result)
+    {
+        // Only 'x', 'y' or 'z'
+        static const std::string x_var("x");
+        static const std::string y_var("y");
+        static const std::string z_var("z");
+        
+        symbol_table<T> symbol_table;
+        symbol_table.add_constants();
+        symbol_table.add_variable(x_var,x);
+        symbol_table.add_variable(y_var,y);
+        symbol_table.add_variable(z_var,z);
+        
+        expression<T> expression;
+        parser<T> parser;
+        
+        if (parser.compile(expression_string,expression))
+        {
+            result = expression.value();
+            
+            return true;
+        }
+        else
             return false;
-         else
-         {
-            if (fp_map_[arg_count].end() != fp_map_[arg_count].find(name))
-               return false;
-
-            switch (arg_count)
+    }
+    
+    template <typename T, std::size_t N>
+    class polynomial : public ifunction<T>
+    {
+    private:
+        
+        template <typename Type, std::size_t NumberOfCoefficients>
+        struct poly_impl { };
+        
+        template <typename Type>
+        struct poly_impl <Type,12>
+        {
+            static inline T evaluate(const Type x,
+                                     const Type c12, const Type c11, const Type c10, const Type c9, const Type c8,
+                                     const Type  c7, const Type  c6, const Type  c5, const Type c4, const Type c3,
+                                     const Type  c2, const Type  c1, const Type  c0)
+            {
+                // p(x) = c_12x^12 + c_11x^11 + c_10x^10 + c_9x^9 + c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
+                return ((((((((((((c12 * x + c11) * x + c10) * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
+            }
+        };
+        
+        template <typename Type>
+        struct poly_impl <Type,11>
+        {
+            static inline T evaluate(const Type x,
+                                     const Type c11, const Type c10, const Type c9, const Type c8, const Type c7,
+                                     const Type c6,  const Type  c5, const Type c4, const Type c3, const Type c2,
+                                     const Type c1,  const Type  c0)
+            {
+                // p(x) = c_11x^11 + c_10x^10 + c_9x^9 + c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
+                return (((((((((((c11 * x + c10) * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
+            }
+        };
+        
+        template <typename Type>
+        struct poly_impl <Type,10>
+        {
+            static inline T evaluate(const Type x,
+                                     const Type c10, const Type c9, const Type c8, const Type c7, const Type c6,
+                                     const Type c5,  const Type c4, const Type c3, const Type c2, const Type c1,
+                                     const Type c0)
+            {
+                // p(x) = c_10x^10 + c_9x^9 + c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
+                return ((((((((((c10 * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
+            }
+        };
+        
+        template <typename Type>
+        struct poly_impl <Type,9>
+        {
+            static inline T evaluate(const Type x,
+                                     const Type c9, const Type c8, const Type c7, const Type c6, const Type c5,
+                                     const Type c4, const Type c3, const Type c2, const Type c1, const Type c0)
             {
-               case 0  : (fp_map_[arg_count])[name] = new func_0param(); break;
-               case 1  : (fp_map_[arg_count])[name] = new func_1param(); break;
-               case 2  : (fp_map_[arg_count])[name] = new func_2param(); break;
-               case 3  : (fp_map_[arg_count])[name] = new func_3param(); break;
-               case 4  : (fp_map_[arg_count])[name] = new func_4param(); break;
-               case 5  : (fp_map_[arg_count])[name] = new func_5param(); break;
-               case 6  : (fp_map_[arg_count])[name] = new func_6param(); break;
+                // p(x) = c_9x^9 + c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
+                return (((((((((c9 * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
             }
-
-            exprtk::ifunction<T>& ifunc = (*(fp_map_[arg_count])[name]);
-
-            return sym_table.add_function(name,ifunc);
-         }
-      }
-
-      template <typename Allocator,
-                template <typename,typename> class Sequence>
-      inline void remove(const std::string& name, const Sequence<std::string,Allocator>& v)
-      {
-         symbol_table_.remove_function(name);
-
-         for (std::size_t i = 0; i < v.size(); ++i)
-         {
-            symbol_table_.remove_variable(v[i]);
-         }
-
-         remove(name,v.size());
-      }
-
-      inline void remove(const std::string& name, const std::size_t& arg_count)
-      {
-         if (arg_count > 6)
-            return;
-
-         typename std::map<std::string,expression_t>::iterator em_itr = expr_map_.find(name);
-
-         if (expr_map_.end() != em_itr)
-         {
-            expr_map_.erase(em_itr);
-         }
-
-         typename funcparam_t::iterator fp_itr = fp_map_[arg_count].find(name);
-
-         if (fp_map_[arg_count].end() != fp_itr)
-            return;
-         else
-            delete fp_itr->second;
-
-         fp_map_[arg_count].erase(fp_itr);
-      }
-
-   private:
-
-      symbol_table_t symbol_table_;
-      parser_t parser_;
-      std::map<std::string,expression_t> expr_map_;
-      std::vector<funcparam_t> fp_map_;
-   };
-
-   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::size_t expression_list_size = sizeof(expression_list) / sizeof(std::string);
-
-      T  x = T(0);
-      T  y = T(0);
-      T  z = T(0);
-      T  w = T(0);
-      T xx = T(0);
-      T yy = T(0);
-      T zz = T(0);
-      T ww = T(0);
-
-      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_variable("xx",xx);
-      symbol_table.add_variable("yy",yy);
-      symbol_table.add_variable("zz",zz);
-      symbol_table.add_variable("ww",ww);
-
-      typedef typename std::deque<exprtk::expression<T> > expr_list_t;
-      expr_list_t expr_list;
-
-      const std::size_t rounds = 50;
-
-      {
-         for (std::size_t r = 0; r < rounds; ++r)
-         {
-            expr_list.clear();
-            exprtk::parser<T> parser;
-
-            for (std::size_t i = 0; i < expression_list_size; ++i)
+        };
+        
+        template <typename Type>
+        struct poly_impl <Type,8>
+        {
+            static inline T evaluate(const Type x,
+                                     const Type c8, const Type c7, const Type c6, const Type c5, const Type c4,
+                                     const Type c3, const Type c2, const Type c1, const Type c0)
             {
-               exprtk::expression<T> expression;
-               expression.register_symbol_table(symbol_table);
-
-               if (!parser.compile(expression_list[i],expression))
-               {
-                  return false;
-               }
-
-               expr_list.push_back(expression);
+                // p(x) = c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
+                return ((((((((c8 * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
+            }
+        };
+        
+        template <typename Type>
+        struct poly_impl <Type,7>
+        {
+            static inline T evaluate(const Type x,
+                                     const Type c7, const Type c6, const Type c5, const Type c4, const Type c3,
+                                     const Type c2, const Type c1, const Type c0)
+            {
+                // p(x) = c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
+                return (((((((c7 * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
+            }
+        };
+        
+        template <typename Type>
+        struct poly_impl <Type,6>
+        {
+            static inline T evaluate(const Type x,
+                                     const Type c6, const Type c5, const Type c4, const Type c3, const Type c2,
+                                     const Type c1, const Type c0)
+            {
+                // p(x) = c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
+                return ((((((c6 * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
+            }
+        };
+        
+        template <typename Type>
+        struct poly_impl <Type,5>
+        {
+            static inline T evaluate(const Type x,
+                                     const Type c5, const Type c4, const Type c3, const Type c2,
+                                     const Type c1, const Type c0)
+            {
+                // p(x) = c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
+                return (((((c5 * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
+            }
+        };
+        
+        template <typename Type>
+        struct poly_impl <Type,4>
+        {
+            static inline T evaluate(const Type x, const Type c4, const Type c3, const Type c2, const Type c1, const Type c0)
+            {
+                // p(x) = c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
+                return ((((c4 * x + c3) * x + c2) * x + c1) * x + c0);
+            }
+        };
+        
+        template <typename Type>
+        struct poly_impl <Type,3>
+        {
+            static inline T evaluate(const Type x, const Type c3, const Type c2, const Type c1, const Type c0)
+            {
+                // p(x) = c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
+                return (((c3 * x + c2) * x + c1) * x + c0);
+            }
+        };
+        
+        template <typename Type>
+        struct poly_impl <Type,2>
+        {
+            static inline T evaluate(const Type x, const Type c2, const Type c1, const Type c0)
+            {
+                // p(x) = c_2x^2 + c_1x^1 + c_0x^0
+                return ((c2 * x + c1) * x + c0);
+            }
+        };
+        
+        template <typename Type>
+        struct poly_impl <Type,1>
+        {
+            static inline T evaluate(const Type x, const Type c1, const Type c0)
+            {
+                // p(x) = c_1x^1 + c_0x^0
+                return (c1 * x + c0);
+            }
+        };
+        
+    public:
+        
+        using ifunction<T>::operator();
+        
+        polynomial()
+        : ifunction<T>((N+2 <= 20) ? (N + 2) : std::numeric_limits<std::size_t>::max())
+        {
+            disable_has_side_effects(*this);
+        }
+        
+        virtual ~polynomial()
+        {}
+        
+#define poly_rtrn(NN) \
+return (NN != N) ? std::numeric_limits<T>::quiet_NaN() :
+        
+        inline virtual T operator()(const T& x, const T& c1, const T& 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);
+        }
+        
+        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);
+        }
+        
+        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);
+        }
+        
+        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);
+        }
+        
+        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);
+        }
+        
+        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);
+        }
+        
+        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);
+        }
+        
+        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);
+        }
+        
+        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);
+        }
+        
+        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);
+        }
+        
+        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);
+        }
+        
+#undef poly_rtrn
+        
+        inline virtual T operator()()
+        {
+            return std::numeric_limits<T>::quiet_NaN();
+        }
+        
+        inline virtual T operator()(const T&)
+        {
+            return std::numeric_limits<T>::quiet_NaN();
+        }
+        
+        inline virtual T operator()(const T&, const T&)
+        {
+            return std::numeric_limits<T>::quiet_NaN();
+        }
+    };
+    
+    template <typename T>
+    class function_compositor
+    {
+    public:
+        
+        typedef exprtk::expression<T>             expression_t;
+        typedef exprtk::symbol_table<T>           symbol_table_t;
+        typedef exprtk::parser<T>                 parser_t;
+        typedef typename parser_t::settings_store settings_t;
+        
+        struct function
+        {
+            function()
+            {}
+            
+            function(const std::string& n)
+            : name_(n)
+            {}
+            
+            function(const std::string& name,
+                     const std::string& expression)
+            : name_(name),
+            expression_(expression)
+            {}
+            
+            function(const std::string& name,
+                     const std::string& expression,
+                     const std::string& v0)
+            : name_(name),
+            expression_(expression)
+            {
+                v_.push_back(v0);
+            }
+            
+            function(const std::string& name,
+                     const std::string& expression,
+                     const std::string& v0, const std::string& v1)
+            : name_(name),
+            expression_(expression)
+            {
+                v_.push_back(v0); v_.push_back(v1);
+            }
+            
+            function(const std::string& name,
+                     const std::string& expression,
+                     const std::string& v0, const std::string& v1,
+                     const std::string& v2)
+            : name_(name),
+            expression_(expression)
+            {
+                v_.push_back(v0); v_.push_back(v1);
+                v_.push_back(v2);
+            }
+            
+            function(const std::string& name,
+                     const std::string& expression,
+                     const std::string& v0, const std::string& v1,
+                     const std::string& v2, const std::string& v3)
+            : name_(name),
+            expression_(expression)
+            {
+                v_.push_back(v0); v_.push_back(v1);
+                v_.push_back(v2); v_.push_back(v3);
+            }
+            
+            function(const std::string& name,
+                     const std::string& expression,
+                     const std::string& v0, const std::string& v1,
+                     const std::string& v2, const std::string& v3,
+                     const std::string& v4)
+            : name_(name),
+            expression_(expression)
+            {
+                v_.push_back(v0); v_.push_back(v1);
+                v_.push_back(v2); v_.push_back(v3);
+                v_.push_back(v4);
+            }
+            
+            inline function& name(const std::string& n)
+            {
+                name_ = n;
+                return (*this);
+            }
+            
+            inline function& expression(const std::string& e)
+            {
+                expression_ = e;
+                return (*this);
+            }
+            
+            inline function& var(const std::string& v)
+            {
+                v_.push_back(v);
+                return (*this);
+            }
+            
+            std::string name_;
+            std::string expression_;
+            std::deque<std::string> v_;
+        };
+        
+    private:
+        
+        struct base_func : public exprtk::ifunction<T>
+        {
+            typedef const T&                       type;
+            typedef exprtk::ifunction<T>     function_t;
+            typedef std::vector<T*>            varref_t;
+            typedef std::vector<T>                var_t;
+            typedef std::pair<T*,std::size_t> lvarref_t;
+            typedef std::vector<lvarref_t>    lvr_vec_t;
+            
+            using exprtk::ifunction<T>::operator();
+            
+            base_func(const std::size_t& pc = 0)
+            : exprtk::ifunction<T>(pc),
+            local_var_stack_size(0),
+            stack_depth(0)
+            {
+                v.resize(pc);
+            }
+            
+            virtual ~base_func()
+            {}
+            
+            inline void update(const T& v0)
+            {
+                (*v[0]) = v0;
+            }
+            
+            inline void update(const T& v0, const T& v1)
+            {
+                (*v[0]) = v0; (*v[1]) = v1;
+            }
+            
+            inline void update(const T& v0, const T& v1, const T& v2)
+            {
+                (*v[0]) = v0; (*v[1]) = v1;
+                (*v[2]) = v2;
+            }
+            
+            inline void update(const T& v0, const T& v1, const T& v2, const T& v3)
+            {
+                (*v[0]) = v0; (*v[1]) = v1;
+                (*v[2]) = v2; (*v[3]) = v3;
+            }
+            
+            inline void update(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4)
+            {
+                (*v[0]) = v0; (*v[1]) = v1;
+                (*v[2]) = v2; (*v[3]) = v3;
+                (*v[4]) = v4;
+            }
+            
+            inline void update(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5)
+            {
+                (*v[0]) = v0; (*v[1]) = v1;
+                (*v[2]) = v2; (*v[3]) = v3;
+                (*v[4]) = v4; (*v[5]) = v5;
+            }
+            
+            inline function_t& setup(expression_t& expr)
+            {
+                expression = expr;
+                
+                typedef typename expression_t::control_block::local_data_list_t ldl_t;
+                
+                ldl_t ldl = expr.local_data_list();
+                
+                std::vector<std::size_t> index_list;
+                
+                for (std::size_t i = 0; i < ldl.size(); ++i)
+                {
+                    if (ldl[i].size)
+                    {
+                        index_list.push_back(i);
+                    }
+                }
+                
+                std::size_t input_param_count = 0;
+                
+                for (std::size_t i = 0; i < index_list.size(); ++i)
+                {
+                    const std::size_t index = index_list[i];
+                    
+                    if (i < (index_list.size() - v.size()))
+                    {
+                        lv.push_back(
+                                     std::make_pair(
+                                                    reinterpret_cast<T*>(ldl[index].pointer),
+                                                    ldl[index].size));
+                        
+                        local_var_stack_size += ldl[index].size;
+                    }
+                    else
+                        v[input_param_count++] = reinterpret_cast<T*>(ldl[index].pointer);
+                }
+                
+                clear_stack();
+                
+                return (*this);
+            }
+            
+            inline void pre()
+            {
+                if (stack_depth++)
+                {
+                    if (!v.empty())
+                    {
+                        var_t var_stack(v.size(),T(0));
+                        copy(v,var_stack);
+                        param_stack.push_back(var_stack);
+                    }
+                    
+                    if (!lv.empty())
+                    {
+                        var_t local_var_stack(local_var_stack_size,T(0));
+                        copy(lv,local_var_stack);
+                        local_stack.push_back(local_var_stack);
+                    }
+                }
+            }
+            
+            inline void post()
+            {
+                if (--stack_depth)
+                {
+                    if (!v.empty())
+                    {
+                        copy(param_stack.back(),v);
+                        param_stack.pop_back();
+                    }
+                    
+                    if (!lv.empty())
+                    {
+                        copy(local_stack.back(),lv);
+                        local_stack.pop_back();
+                    }
+                }
+            }
+            
+            void copy(const varref_t& src_v, var_t& dest_v)
+            {
+                for (std::size_t i = 0; i < src_v.size(); ++i)
+                {
+                    dest_v[i] = (*src_v[i]);
+                }
+            }
+            
+            void copy(const var_t& src_v, varref_t& dest_v)
+            {
+                for (std::size_t i = 0; i < src_v.size(); ++i)
+                {
+                    (*dest_v[i]) = src_v[i];
+                }
+            }
+            
+            void copy(const lvr_vec_t& src_v, var_t& dest_v)
+            {
+                typename var_t::iterator itr = dest_v.begin();
+                
+                for (std::size_t i = 0; i < src_v.size(); ++i)
+                {
+                    lvarref_t vr = src_v[i];
+                    
+                    if (1 == vr.second)
+                        *itr++ = (*vr.first);
+                    else
+                    {
+                        std::copy(vr.first,vr.first + vr.second,itr);
+                        itr += vr.second;
+                    }
+                }
+            }
+            
+            void copy(const var_t& src_v, lvr_vec_t& dest_v)
+            {
+                typename var_t::const_iterator itr = src_v.begin();
+                
+                for (std::size_t i = 0; i < src_v.size(); ++i)
+                {
+                    lvarref_t vr = dest_v[i];
+                    
+                    if (1 == vr.second)
+                        (*vr.first) = *itr++;
+                    else
+                    {
+                        std::copy(itr,itr + vr.second,vr.first);
+                        itr += vr.second;
+                    }
+                }
+            }
+            
+            inline void clear_stack()
+            {
+                for (std::size_t i = 0; i < v.size(); ++i)
+                {
+                    (*v[i]) = 0;
+                }
+            }
+            
+            inline virtual T value(expression_t& e)
+            {
+                return e.value();
+            }
+            
+            expression_t expression;
+            varref_t v;
+            lvr_vec_t lv;
+            std::size_t local_var_stack_size;
+            std::size_t stack_depth;
+            std::deque<var_t> param_stack;
+            std::deque<var_t> local_stack;
+        };
+        
+        typedef std::map<std::string,base_func*> funcparam_t;
+        
+        struct func_0param : public base_func
+        {
+            using exprtk::ifunction<T>::operator();
+            
+            func_0param() : base_func(0) {}
+            
+            inline T operator()()
+            {
+                return this->value(base_func::expression);
             }
-         }
-      }
-
-      struct execute
-      {
-         static inline T process(T& x, T& y, expression<T>& expression)
-         {
-            static const T lower_bound = T(-20);
-            static const T upper_bound = T(+20);
-
-            T delta = T(0.1);
-            T total = T(0);
-
-            for (x = lower_bound; x <= upper_bound; x += delta)
+        };
+        
+        typedef const T& type;
+        
+        template <typename BaseFuncType>
+        struct scoped_bft
+        {
+            scoped_bft(BaseFuncType& bft) : bft_(bft) { bft_.pre (); }
+            ~scoped_bft()                              { bft_.post(); }
+            
+            BaseFuncType& bft_;
+            
+        private:
+            
+            scoped_bft(scoped_bft&);
+            scoped_bft& operator=(scoped_bft&);
+        };
+        
+        struct func_1param : public base_func
+        {
+            using exprtk::ifunction<T>::operator();
+            
+            func_1param() : base_func(1) {}
+            
+            inline T operator()(type v0)
+            {
+                scoped_bft<func_1param> sb(*this);
+                base_func::update(v0);
+                T result = this->value(base_func::expression);
+                
+                return result;
+            }
+        };
+        
+        struct func_2param : public base_func
+        {
+            using exprtk::ifunction<T>::operator();
+            
+            func_2param() : base_func(2) {}
+            
+            inline T operator()(type v0, type v1)
+            {
+                scoped_bft<func_2param> sb(*this);
+                base_func::update(v0,v1);
+                T result = this->value(base_func::expression);
+                
+                return result;
+            }
+        };
+        
+        struct func_3param : public base_func
+        {
+            using exprtk::ifunction<T>::operator();
+            
+            func_3param() : base_func(3) {}
+            
+            inline T operator()(type v0, type v1, type v2)
+            {
+                scoped_bft<func_3param> sb(*this);
+                base_func::update(v0,v1,v2);
+                T result = this->value(base_func::expression);
+                
+                return result;
+            }
+        };
+        
+        struct func_4param : public base_func
+        {
+            using exprtk::ifunction<T>::operator();
+            
+            func_4param() : base_func(4) {}
+            
+            inline T operator()(type v0, type v1, type v2, type v3)
+            {
+                scoped_bft<func_4param> sb(*this);
+                base_func::update(v0,v1,v2,v3);
+                T result = this->value(base_func::expression);
+                
+                return result;
+            }
+        };
+        
+        struct func_5param : public base_func
+        {
+            using exprtk::ifunction<T>::operator();
+            
+            func_5param() : base_func(5) {}
+            
+            inline T operator()(type v0, type v1, type v2, type v3, type v4)
+            {
+                scoped_bft<func_5param> sb(*this);
+                base_func::update(v0,v1,v2,v3,v4);
+                T result = this->value(base_func::expression);
+                
+                return result;
+            }
+        };
+        
+        struct func_6param : public base_func
+        {
+            using exprtk::ifunction<T>::operator();
+            
+            func_6param() : base_func(6) {}
+            
+            inline T operator()(type v0, type v1, type v2, type v3, type v4, type v5)
+            {
+                scoped_bft<func_6param> sb(*this);
+                base_func::update(v0,v1,v2,v3,v4,v5);
+                T result = this->value(base_func::expression);
+                
+                return result;
+            }
+        };
+        
+        static T return_value(expression_t& e)
+        {
+            typedef exprtk::results_context<T> results_context_t;
+            typedef typename results_context_t::type_store_t type_t;
+            typedef typename type_t::scalar_view scalar_t;
+            
+            T result = e.value();
+            
+            if (e.return_invoked())
+            {
+                // Due to the post compilation checks, it can be safely
+                // assumed that there will be at least one parameter
+                // and that the first parameter will always be scalar.
+                return scalar_t(e.results()[0])();
+            }
+            
+            return result;
+        }
+        
+#define def_fp_retval(N)                               \
+struct func_##N##param_retval : public func_##N##param \
+{                                                      \
+inline T value(expression_t& e)                     \
+{                                                   \
+return return_value(e);                          \
+}                                                   \
+};                                                     \
+
+        def_fp_retval(0)
+        def_fp_retval(1)
+        def_fp_retval(2)
+        def_fp_retval(3)
+        def_fp_retval(4)
+        def_fp_retval(5)
+        def_fp_retval(6)
+        
+        template <typename Allocator,
+        template <typename,typename> class Sequence>
+        inline bool add(const std::string& name,
+                        const std::string& expression,
+                        const Sequence<std::string,Allocator>& var_list,
+                        const bool override = false)
+        {
+            const std::size_t n = var_list.size();
+            
+            typename std::map<std::string,expression_t>::iterator itr = expr_map_.find(name);
+            
+            if (expr_map_.end() != itr)
+            {
+                if (!override)
+                {
+                    exprtk_debug(("Compositor error(add): function '%s' already defined\n",
+                                  name.c_str()));
+                    
+                    return false;
+                }
+                
+                remove(name, var_list.size());
+            }
+            
+            if (compile_expression(name,expression,var_list))
+            {
+                fp_map_[n][name]->setup(expr_map_[name]);
+                
+                return true;
+            }
+            else
+            {
+                exprtk_debug(("Compositor error(add): Failed to compile function '%s'\n",
+                              name.c_str()));
+                
+                return false;
+            }
+        }
+        
+    public:
+        
+        function_compositor()
+        : parser_(settings_t::compile_all_opts +
+                  settings_t::e_disable_zero_return),
+        fp_map_(7)
+        {}
+        
+        function_compositor(const symbol_table_t& st)
+        : symbol_table_(st),
+        parser_(settings_t::compile_all_opts +
+                settings_t::e_disable_zero_return),
+        fp_map_(7)
+        {}
+        
+        ~function_compositor()
+        {
+            clear();
+        }
+        
+        inline symbol_table_t& symbol_table()
+        {
+            return symbol_table_;
+        }
+        
+        inline void add_auxiliary_symtab(symbol_table_t& symtab)
+        {
+            auxiliary_symtab_list_.push_back(&symtab);
+        }
+        
+        void clear()
+        {
+            symbol_table_.clear();
+            expr_map_    .clear();
+            
+            for (std::size_t i = 0; i < fp_map_.size(); ++i)
+            {
+                typename funcparam_t::iterator itr = fp_map_[i].begin();
+                typename funcparam_t::iterator end = fp_map_[i].end  ();
+                
+                while (itr != end)
+                {
+                    delete itr->second;
+                    ++itr;
+                }
+                
+                fp_map_[i].clear();
+            }
+        }
+        
+        inline bool add(const function& f, const bool override = false)
+        {
+            return add(f.name_,f.expression_,f.v_,override);
+        }
+        
+    private:
+        
+        template <typename Allocator,
+        template <typename,typename> class Sequence>
+        bool compile_expression(const std::string& name,
+                                const std::string& expression,
+                                const Sequence<std::string,Allocator>& input_var_list,
+                                bool  return_present = false)
+        {
+            expression_t compiled_expression;
+            symbol_table_t local_symbol_table;
+            
+            local_symbol_table.load_from(symbol_table_);
+            local_symbol_table.add_constants();
+            
+            if (!valid(name,input_var_list.size()))
+                return false;
+            
+            if (!forward(name,
+                         input_var_list.size(),
+                         local_symbol_table,
+                         return_present))
+                return false;
+            
+            compiled_expression.register_symbol_table(local_symbol_table);
+            
+            for (std::size_t i = 0; i < auxiliary_symtab_list_.size(); ++i)
+            {
+                compiled_expression.register_symbol_table((*auxiliary_symtab_list_[i]));
+            }
+            
+            std::string mod_expression;
+            
+            for (std::size_t i = 0; i < input_var_list.size(); ++i)
+            {
+                mod_expression += " var " + input_var_list[i] + "{};\n";
+            }
+            
+            if (
+                ('{' == details::front(expression)) &&
+                ('}' == details::back (expression))
+                )
+                mod_expression += "~" + expression + ";";
+            else
+                mod_expression += "~{" + expression + "};";
+            
+            if (!parser_.compile(mod_expression,compiled_expression))
+            {
+                exprtk_debug(("Compositor Error: %s\n",parser_.error().c_str()));
+                exprtk_debug(("Compositor modified expression: \n%s\n",mod_expression.c_str()));
+                
+                remove(name,input_var_list.size());
+                
+                return false;
+            }
+            
+            if (!return_present && parser_.dec().return_present())
+            {
+                remove(name,input_var_list.size());
+                
+                return compile_expression(name,expression,input_var_list,true);
+            }
+            
+            // Make sure every return point has a scalar as its first parameter
+            if (parser_.dec().return_present())
+            {
+                typedef std::vector<std::string> str_list_t;
+                
+                str_list_t ret_param_list = parser_.dec().return_param_type_list();
+                
+                for (std::size_t i = 0; i < ret_param_list.size(); ++i)
+                {
+                    const std::string& params = ret_param_list[i];
+                    
+                    if (params.empty() || ('T' != params[0]))
+                    {
+                        exprtk_debug(("Compositor Error: Return statement in function '%s' is invalid\n",
+                                      name.c_str()));
+                        
+                        remove(name,input_var_list.size());
+                        
+                        return false;
+                    }
+                }
+            }
+            
+            expr_map_[name] = compiled_expression;
+            
+            exprtk::ifunction<T>& ifunc = (*(fp_map_[input_var_list.size()])[name]);
+            
+            if (symbol_table_.add_function(name,ifunc))
+                return true;
+            else
             {
-               for (y = lower_bound; y <= upper_bound; y += delta)
-               {
-                  total += expression.value();
-               }
+                exprtk_debug(("Compositor Error: Failed to add function '%s' to symbol table\n",
+                              name.c_str()));
+                return false;
             }
-
-            return total;
-         }
-      };
-
-      for (std::size_t i = 0; i < expr_list.size(); ++i)
-      {
-         execute::process( x, y,expr_list[i]);
-         execute::process(xx,yy,expr_list[i]);
-      }
-
-      {
-         for (std::size_t i = 0; i < 10000; ++i)
-         {
-            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;
-            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T, 2>::result(v),details::numeric::pow(v,T( 2))))) return false;
-            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T, 3>::result(v),details::numeric::pow(v,T( 3))))) return false;
-            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T, 4>::result(v),details::numeric::pow(v,T( 4))))) return false;
-            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T, 5>::result(v),details::numeric::pow(v,T( 5))))) return false;
-            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T, 6>::result(v),details::numeric::pow(v,T( 6))))) return false;
-            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T, 7>::result(v),details::numeric::pow(v,T( 7))))) return false;
-            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T, 8>::result(v),details::numeric::pow(v,T( 8))))) return false;
-            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T, 9>::result(v),details::numeric::pow(v,T( 9))))) return false;
-            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,10>::result(v),details::numeric::pow(v,T(10))))) return false;
-            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,11>::result(v),details::numeric::pow(v,T(11))))) return false;
-            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,12>::result(v),details::numeric::pow(v,T(12))))) return false;
-            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,13>::result(v),details::numeric::pow(v,T(13))))) return false;
-            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,14>::result(v),details::numeric::pow(v,T(14))))) return false;
-            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,15>::result(v),details::numeric::pow(v,T(15))))) return false;
-            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,16>::result(v),details::numeric::pow(v,T(16))))) return false;
-            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,17>::result(v),details::numeric::pow(v,T(17))))) return false;
-            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,18>::result(v),details::numeric::pow(v,T(18))))) return false;
-            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,19>::result(v),details::numeric::pow(v,T(19))))) return false;
-            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,20>::result(v),details::numeric::pow(v,T(20))))) return false;
-            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,21>::result(v),details::numeric::pow(v,T(21))))) return false;
-            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,22>::result(v),details::numeric::pow(v,T(22))))) return false;
-            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,23>::result(v),details::numeric::pow(v,T(23))))) return false;
-            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,24>::result(v),details::numeric::pow(v,T(24))))) return false;
-            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,25>::result(v),details::numeric::pow(v,T(25))))) return false;
-            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,26>::result(v),details::numeric::pow(v,T(26))))) return false;
-            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,27>::result(v),details::numeric::pow(v,T(27))))) return false;
-            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,28>::result(v),details::numeric::pow(v,T(28))))) return false;
-            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,29>::result(v),details::numeric::pow(v,T(29))))) return false;
-            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,30>::result(v),details::numeric::pow(v,T(30))))) return false;
-            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,31>::result(v),details::numeric::pow(v,T(31))))) return false;
-            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,32>::result(v),details::numeric::pow(v,T(32))))) return false;
-            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,33>::result(v),details::numeric::pow(v,T(33))))) return false;
-            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,34>::result(v),details::numeric::pow(v,T(34))))) return false;
-            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,35>::result(v),details::numeric::pow(v,T(35))))) return false;
-            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,36>::result(v),details::numeric::pow(v,T(36))))) return false;
-            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,37>::result(v),details::numeric::pow(v,T(37))))) return false;
-            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,38>::result(v),details::numeric::pow(v,T(38))))) return false;
-            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,39>::result(v),details::numeric::pow(v,T(39))))) return false;
-            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,40>::result(v),details::numeric::pow(v,T(40))))) return false;
-            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,41>::result(v),details::numeric::pow(v,T(41))))) return false;
-            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,42>::result(v),details::numeric::pow(v,T(42))))) return false;
-            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,43>::result(v),details::numeric::pow(v,T(43))))) return false;
-            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,44>::result(v),details::numeric::pow(v,T(44))))) return false;
-            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,45>::result(v),details::numeric::pow(v,T(45))))) return false;
-            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,46>::result(v),details::numeric::pow(v,T(46))))) return false;
-            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,47>::result(v),details::numeric::pow(v,T(47))))) return false;
-            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,48>::result(v),details::numeric::pow(v,T(48))))) return false;
-            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,49>::result(v),details::numeric::pow(v,T(49))))) return false;
-            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,50>::result(v),details::numeric::pow(v,T(50))))) return false;
-            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,51>::result(v),details::numeric::pow(v,T(51))))) return false;
-            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,52>::result(v),details::numeric::pow(v,T(52))))) return false;
-            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,53>::result(v),details::numeric::pow(v,T(53))))) return false;
-            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,54>::result(v),details::numeric::pow(v,T(54))))) return false;
-            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,55>::result(v),details::numeric::pow(v,T(55))))) return false;
-            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,56>::result(v),details::numeric::pow(v,T(56))))) return false;
-            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,57>::result(v),details::numeric::pow(v,T(57))))) return false;
-            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,58>::result(v),details::numeric::pow(v,T(58))))) return false;
-            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,59>::result(v),details::numeric::pow(v,T(59))))) return false;
-            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,60>::result(v),details::numeric::pow(v,T(60))))) return false;
-         }
-      }
-
-      return true;
-   }
-
-   namespace helper
-   {
-      namespace details
-      {
-         template <typename T>
-         inline void print_type(const std::string& fmt, const T v, exprtk::details::numeric::details::real_type_tag)
-         {
-            printf(fmt.c_str(),v);
-         }
-
-         template <typename T>
-         struct print_impl
-         {
-            typedef typename igeneric_function<T>::generic_type generic_type;
-            typedef typename igeneric_function<T>::parameter_list_t parameter_list_t;
-            typedef typename generic_type::scalar_view scalar_t;
-            typedef typename generic_type::vector_view vector_t;
-            typedef typename generic_type::string_view string_t;
-
-            static void process(const std::string& scalar_format, parameter_list_t parameters)
+        }
+        
+        inline bool symbol_used(const std::string& symbol) const
+        {
+            return (
+                    symbol_table_.is_variable       (symbol) ||
+                    symbol_table_.is_stringvar      (symbol) ||
+                    symbol_table_.is_function       (symbol) ||
+                    symbol_table_.is_vector         (symbol) ||
+                    symbol_table_.is_vararg_function(symbol)
+                    );
+        }
+        
+        inline bool valid(const std::string& name,
+                          const std::size_t& arg_count) const
+        {
+            if (arg_count > 6)
+                return false;
+            else if (symbol_used(name))
+                return false;
+            else if (fp_map_[arg_count].end() != fp_map_[arg_count].find(name))
+                return false;
+            else
+                return true;
+        }
+        
+        inline bool forward(const std::string& name,
+                            const std::size_t& arg_count,
+                            symbol_table_t& sym_table,
+                            const bool ret_present = false)
+        {
+            switch (arg_count)
             {
-               for (std::size_t i = 0; i < parameters.size(); ++i)
-               {
-                  generic_type& gt = parameters[i];
-
-                  typename exprtk::details::numeric::details::number_type<T>::type num_type;
-
-                  switch (gt.type)
-                  {
-                     case generic_type::e_scalar : print_type(scalar_format.c_str(),scalar_t(gt)(),num_type);
-                                                   break;
-
-                     case generic_type::e_vector : {
-                                                      vector_t vector(gt);
+#define case_stmt(N)                                     \
+case N : (fp_map_[arg_count])[name] =                    \
+(!ret_present) ? static_cast<base_func*>        \
+(new func_##N##param) :        \
+static_cast<base_func*>        \
+(new func_##N##param_retval) ; \
+break;                                          \
 
-                                                      for (std::size_t x = 0; x < vector.size(); ++x)
-                                                      {
-                                                         print_type(scalar_format.c_str(),vector[x],num_type);
-
-                                                         if ((x + 1) < vector.size())
-                                                            printf(" ");
-                                                      }
-                                                   }
-                                                   break;
-
-                     case generic_type::e_string : printf("%s",to_str(string_t(gt)).c_str());
-                                                   break;
-
-                     default                     : continue;
-                  }
-               }
+                    case_stmt(0) case_stmt(1) case_stmt(2)
+                    case_stmt(3) case_stmt(4) case_stmt(5)
+                    case_stmt(6)
+#undef case_stmt
             }
-         };
-      }
-
-      template <typename T>
-      struct print : public exprtk::igeneric_function<T>
-      {
-         typedef typename igeneric_function<T>::parameter_list_t parameter_list_t;
-
-         print(const std::string& scalar_format = "%10.5f")
-         : scalar_format_(scalar_format)
-         {}
-
-         inline T operator()(parameter_list_t parameters)
-         {
-            details::print_impl<T>::process(scalar_format_,parameters);
-            return T(0);
-         }
-
-         std::string scalar_format_;
-      };
-
-      template <typename T>
-      struct println : public exprtk::igeneric_function<T>
-      {
-         typedef typename igeneric_function<T>::parameter_list_t parameter_list_t;
-
-         println(const std::string& scalar_format = "%10.5f")
-         : scalar_format_(scalar_format)
-         {}
-
-         inline T operator()(parameter_list_t parameters)
-         {
-            details::print_impl<T>::process(scalar_format_,parameters);
-            printf("\n");
-            return T(0);
-         }
-
-         std::string scalar_format_;
-      };
-   }
+            
+            exprtk::ifunction<T>& ifunc = (*(fp_map_[arg_count])[name]);
+            
+            return sym_table.add_function(name,ifunc);
+        }
+        
+        inline void remove(const std::string& name, const std::size_t& arg_count)
+        {
+            if (arg_count > 6)
+                return;
+            
+            typename std::map<std::string,expression_t>::iterator em_itr = expr_map_.find(name);
+            
+            if (expr_map_.end() != em_itr)
+            {
+                expr_map_.erase(em_itr);
+            }
+            
+            typename funcparam_t::iterator fp_itr = fp_map_[arg_count].find(name);
+            
+            if (fp_map_[arg_count].end() != fp_itr)
+            {
+                delete fp_itr->second;
+                fp_map_[arg_count].erase(fp_itr);
+            }
+            
+            symbol_table_.remove_function(name);
+        }
+        
+    private:
+        
+        symbol_table_t symbol_table_;
+        parser_t parser_;
+        std::map<std::string,expression_t> expr_map_;
+        std::vector<funcparam_t> fp_map_;
+        std::vector<symbol_table_t*> auxiliary_symtab_list_;
+    };
+    
+    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::size_t expression_list_size = sizeof(expression_list) / sizeof(std::string);
+        
+        T  x = T(0);
+        T  y = T(0);
+        T  z = T(0);
+        T  w = T(0);
+        T xx = T(0);
+        T yy = T(0);
+        T zz = T(0);
+        T ww = T(0);
+        
+        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_variable("xx",xx);
+        symbol_table.add_variable("yy",yy);
+        symbol_table.add_variable("zz",zz);
+        symbol_table.add_variable("ww",ww);
+        
+        typedef typename std::deque<exprtk::expression<T> > expr_list_t;
+        expr_list_t expr_list;
+        
+        const std::size_t rounds = 50;
+        
+        {
+            for (std::size_t r = 0; r < rounds; ++r)
+            {
+                expr_list.clear();
+                exprtk::parser<T> parser;
+                
+                for (std::size_t i = 0; i < expression_list_size; ++i)
+                {
+                    exprtk::expression<T> expression;
+                    expression.register_symbol_table(symbol_table);
+                    
+                    if (!parser.compile(expression_list[i],expression))
+                    {
+                        return false;
+                    }
+                    
+                    expr_list.push_back(expression);
+                }
+            }
+        }
+        
+        struct execute
+        {
+            static inline T process(T& x, T& y, expression<T>& expression)
+            {
+                static const T lower_bound = T(-20);
+                static const T upper_bound = T(+20);
+                
+                T delta = T(0.1);
+                T total = T(0);
+                
+                for (x = lower_bound; x <= upper_bound; x += delta)
+                {
+                    for (y = lower_bound; y <= upper_bound; y += delta)
+                    {
+                        total += expression.value();
+                    }
+                }
+                
+                return total;
+            }
+        };
+        
+        for (std::size_t i = 0; i < expr_list.size(); ++i)
+        {
+            execute::process( x,  y, expr_list[i]);
+            execute::process(xx, yy, expr_list[i]);
+        }
+        
+        {
+            for (std::size_t i = 0; i < 10000; ++i)
+            {
+                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;
+                
+#define else_stmt(N)                                                                                                           \
+else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,N>::result(v),details::numeric::pow(v,T(N))))) \
+return false;                                                                                                               \
+
+                else_stmt( 2) else_stmt( 3) else_stmt( 4) else_stmt( 5)
+                else_stmt( 6) else_stmt( 7) else_stmt( 8) else_stmt( 9)
+                else_stmt(10) else_stmt(11) else_stmt(12) else_stmt(13)
+                else_stmt(14) else_stmt(15) else_stmt(16) else_stmt(17)
+                else_stmt(18) else_stmt(19) else_stmt(20) else_stmt(21)
+                else_stmt(22) else_stmt(23) else_stmt(24) else_stmt(25)
+                else_stmt(26) else_stmt(27) else_stmt(28) else_stmt(29)
+                else_stmt(30) else_stmt(31) else_stmt(32) else_stmt(33)
+                else_stmt(34) else_stmt(35) else_stmt(36) else_stmt(37)
+                else_stmt(38) else_stmt(39) else_stmt(40) else_stmt(41)
+                else_stmt(42) else_stmt(43) else_stmt(44) else_stmt(45)
+                else_stmt(46) else_stmt(47) else_stmt(48) else_stmt(49)
+                else_stmt(50) else_stmt(51) else_stmt(52) else_stmt(53)
+                else_stmt(54) else_stmt(55) else_stmt(56) else_stmt(57)
+                else_stmt(58) else_stmt(59) else_stmt(60)
+            }
+        }
+        
+        return true;
+    }
 }
 
 #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
@@ -30052,116 +34998,1882 @@ namespace exprtk
 
 namespace exprtk
 {
-
-   class timer
-   {
-   public:
-
-      #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
-      timer()
-      : in_use_(false)
-      {
-         QueryPerformanceFrequency(&clock_frequency_);
-      }
-
-      inline void start()
-      {
-         in_use_ = true;
-         QueryPerformanceCounter(&start_time_);
-      }
-
-      inline void stop()
-      {
-         QueryPerformanceCounter(&stop_time_);
-         in_use_ = false;
-      }
-
-      inline double time() const
-      {
-         return (1.0 * (stop_time_.QuadPart - start_time_.QuadPart)) / (1.0 * clock_frequency_.QuadPart);
-      }
-
-      #else
-
-      timer()
-      : in_use_(false)
-      {
-         start_time_.tv_sec  = 0;
-         start_time_.tv_usec = 0;
-         stop_time_.tv_sec   = 0;
-         stop_time_.tv_usec  = 0;
-      }
-
-      inline void start()
-      {
-         in_use_ = true;
-         gettimeofday(&start_time_,0);
-      }
-
-      inline void stop()
-      {
-         gettimeofday(&stop_time_, 0);
-         in_use_ = false;
-      }
-
-      inline unsigned long long int usec_time() const
-      {
-         if (!in_use_)
-         {
-            if (stop_time_.tv_sec >= start_time_.tv_sec)
-            {
-               return 1000000 * (stop_time_.tv_sec  - start_time_.tv_sec ) +
-                                (stop_time_.tv_usec - start_time_.tv_usec);
+    class timer
+    {
+    public:
+        
+#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
+        timer()
+        : in_use_(false)
+        {
+            QueryPerformanceFrequency(&clock_frequency_);
+        }
+        
+        inline void start()
+        {
+            in_use_ = true;
+            QueryPerformanceCounter(&start_time_);
+        }
+        
+        inline void stop()
+        {
+            QueryPerformanceCounter(&stop_time_);
+            in_use_ = false;
+        }
+        
+        inline double time() const
+        {
+            return (1.0 * (stop_time_.QuadPart - start_time_.QuadPart)) / (1.0 * clock_frequency_.QuadPart);
+        }
+        
+#else
+        
+        timer()
+        : in_use_(false)
+        {
+            start_time_.tv_sec  = 0;
+            start_time_.tv_usec = 0;
+            stop_time_.tv_sec   = 0;
+            stop_time_.tv_usec  = 0;
+        }
+        
+        inline void start()
+        {
+            in_use_ = true;
+            gettimeofday(&start_time_,0);
+        }
+        
+        inline void stop()
+        {
+            gettimeofday(&stop_time_, 0);
+            in_use_ = false;
+        }
+        
+        inline unsigned long long int usec_time() const
+        {
+            if (!in_use_)
+            {
+                if (stop_time_.tv_sec >= start_time_.tv_sec)
+                {
+                    return 1000000 * (stop_time_.tv_sec  - start_time_.tv_sec ) +
+                    (stop_time_.tv_usec - start_time_.tv_usec);
+                }
+                else
+                    return std::numeric_limits<unsigned long long int>::max();
             }
             else
-               return std::numeric_limits<unsigned long long int>::max();
-         }
-         else
-            return std::numeric_limits<unsigned long long int>::max();
-      }
-
-      inline double time() const
-      {
-         return usec_time() * 0.000001;
-      }
-
-      #endif
-
-      inline bool in_use() const
-      {
-         return in_use_;
-      }
-
-   private:
-
-      bool in_use_;
-
-      #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
-         LARGE_INTEGER start_time_;
-         LARGE_INTEGER stop_time_;
-         LARGE_INTEGER clock_frequency_;
-      #else
-         struct timeval start_time_;
-         struct timeval stop_time_;
-      #endif
-   };
+                return std::numeric_limits<unsigned long long int>::max();
+        }
+        
+        inline double time() const
+        {
+            return usec_time() * 0.000001;
+        }
+        
+#endif
+        
+        inline bool in_use() const
+        {
+            return in_use_;
+        }
+        
+    private:
+        
+        bool in_use_;
+        
+#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
+        LARGE_INTEGER start_time_;
+        LARGE_INTEGER stop_time_;
+        LARGE_INTEGER clock_frequency_;
+#else
+        struct timeval start_time_;
+        struct timeval stop_time_;
+#endif
+    };
+    
+} // namespace exprtk
 
-   namespace information
-   {
-      static const char* library = "Mathematical Expression Toolkit";
-      static const char* version = "2.7182818284590452353602874713526624977572470936999595";
-      static const char* date    = "20150111";
+#ifndef exprtk_disable_rtl_io
+namespace exprtk
+{
+    namespace rtl { namespace io { namespace details
+        {
+            template <typename T>
+            inline void print_type(const std::string& fmt,
+                                   const T v,
+                                   exprtk::details::numeric::details::real_type_tag)
+            {
+                printf(fmt.c_str(),v);
+            }
+            
+            template <typename T>
+            struct print_impl
+            {
+                typedef typename igeneric_function<T>::generic_type generic_type;
+                typedef typename igeneric_function<T>::parameter_list_t parameter_list_t;
+                typedef typename generic_type::scalar_view scalar_t;
+                typedef typename generic_type::vector_view vector_t;
+                typedef typename generic_type::string_view string_t;
+                typedef typename exprtk::details::numeric::details::number_type<T>::type num_type;
+                
+                static void process(const std::string& scalar_format, parameter_list_t parameters)
+                {
+                    for (std::size_t i = 0; i < parameters.size(); ++i)
+                    {
+                        generic_type& gt = parameters[i];
+                        
+                        switch (gt.type)
+                        {
+                            case generic_type::e_scalar : print(scalar_format,scalar_t(gt));
+                                break;
+                                
+                            case generic_type::e_vector : print(scalar_format,vector_t(gt));
+                                break;
+                                
+                            case generic_type::e_string : print(string_t(gt));
+                                break;
+                                
+                            default                     : continue;
+                        }
+                    }
+                }
+                
+                static inline void print(const std::string& scalar_format, const scalar_t& s)
+                {
+                    print_type(scalar_format,s(),num_type());
+                }
+                
+                static inline void print(const std::string& scalar_format, const vector_t& v)
+                {
+                    for (std::size_t i = 0; i < v.size(); ++i)
+                    {
+                        print_type(scalar_format,v[i],num_type());
+                        
+                        if ((i + 1) < v.size())
+                            printf(" ");
+                    }
+                }
+                
+                static inline void print(const string_t& s)
+                {
+                    printf("%s",to_str(s).c_str());
+                }
+            };
+            
+        } // namespace exprtk::rtl::io::details
+        
+        template <typename T>
+        struct print : public exprtk::igeneric_function<T>
+        {
+            typedef typename igeneric_function<T>::parameter_list_t parameter_list_t;
+            
+            using exprtk::igeneric_function<T>::operator();
+            
+            print(const std::string& scalar_format = "%10.5f")
+            : scalar_format_(scalar_format)
+            {
+                exprtk::enable_zero_parameters(*this);
+            }
+            
+            inline T operator()(parameter_list_t parameters)
+            {
+                details::print_impl<T>::process(scalar_format_,parameters);
+                return T(0);
+            }
+            
+            std::string scalar_format_;
+        };
+        
+        template <typename T>
+        struct println : public exprtk::igeneric_function<T>
+        {
+            typedef typename igeneric_function<T>::parameter_list_t parameter_list_t;
+            
+            using exprtk::igeneric_function<T>::operator();
+            
+            println(const std::string& scalar_format = "%10.5f")
+            : scalar_format_(scalar_format)
+            {
+                exprtk::enable_zero_parameters(*this);
+            }
+            
+            inline T operator()(parameter_list_t parameters)
+            {
+                details::print_impl<T>::process(scalar_format_,parameters);
+                printf("\n");
+                return T(0);
+            }
+            
+            std::string scalar_format_;
+        };
+        
+        template <typename T>
+        struct package
+        {
+            print  <T> p;
+            println<T> pl;
+            
+            bool register_package(exprtk::symbol_table<T>& symtab)
+            {
+                if (!symtab.add_function("print"   ,p))
+                    return false;
+                else if (!symtab.add_function("println" ,pl))
+                    return false;
+                else
+                    return true;
+            }
+        };
+        
+    } // namespace exprtk::rtl::io
+    } // namespace exprtk::rtl
+}    // namespace exprtk
+#endif
 
-      static inline std::string data()
-      {
-         static const std::string info_str = std::string(library) +
-                                             std::string(" v") + std::string(version) +
-                                             std::string(" (") + date + std::string(")");
-         return info_str;
-      }
+#ifndef exprtk_disable_rtl_io_file
+#include <fstream>
+namespace exprtk
+{
+    namespace rtl { namespace io { namespace file { namespace details
+        {
+            enum file_mode
+            {
+                e_error = 0,
+                e_read  = 1,
+                e_write = 2,
+                e_rdwrt = 4
+            };
+            
+            struct file_descriptor
+            {
+                file_descriptor(const std::string& fname, const std::string& access)
+                : stream_ptr(0),
+                mode(get_file_mode(access)),
+                file_name(fname)
+                {}
+                
+                void*       stream_ptr;
+                file_mode   mode;
+                std::string file_name;
+                
+                bool open()
+                {
+                    if (e_read == mode)
+                    {
+                        std::ifstream* stream = new std::ifstream(file_name.c_str(),std::ios::binary);
+                        
+                        if (!(*stream))
+                        {
+                            file_name.clear();
+                            delete stream;
+                            
+                            return false;
+                        }
+                        else
+                            stream_ptr = stream;
+                        
+                        return true;
+                    }
+                    else if (e_write == mode)
+                    {
+                        std::ofstream* stream = new std::ofstream(file_name.c_str(),std::ios::binary);
+                        
+                        if (!(*stream))
+                        {
+                            file_name.clear();
+                            delete stream;
+                            
+                            return false;
+                        }
+                        else
+                            stream_ptr = stream;
+                        
+                        return true;
+                    }
+                    else if (e_rdwrt == mode)
+                    {
+                        std::fstream* stream = new std::fstream(file_name.c_str(),std::ios::binary);
+                        
+                        if (!(*stream))
+                        {
+                            file_name.clear();
+                            delete stream;
+                            
+                            return false;
+                        }
+                        else
+                            stream_ptr = stream;
+                        
+                        return true;
+                    }
+                    else
+                        return false;
+                }
+                
+                template <typename Stream, typename Ptr>
+                void close(Ptr& p)
+                {
+                    Stream* stream = reinterpret_cast<Stream*>(p);
+                    stream->close();
+                    delete stream;
+                    p = reinterpret_cast<Ptr>(0);
+                }
+                
+                bool close()
+                {
+                    switch (mode)
+                    {
+                        case e_read  : close<std::ifstream>(stream_ptr);
+                            break;
+                            
+                        case e_write : close<std::ofstream>(stream_ptr);
+                            break;
+                            
+                        case e_rdwrt : close<std::fstream> (stream_ptr);
+                            break;
+                            
+                        default      : return false;
+                    }
+                    
+                    return true;
+                }
+                
+                template <typename View>
+                bool write(const View& view, const std::size_t amount, const std::size_t offset = 0)
+                {
+                    switch (mode)
+                    {
+                        case e_write : reinterpret_cast<std::ofstream*>(stream_ptr)->
+                            write(reinterpret_cast<const char*>(view.begin() + offset), amount * sizeof(typename View::value_t));
+                            break;
+                            
+                        case e_rdwrt : reinterpret_cast<std::fstream*>(stream_ptr)->
+                            write(reinterpret_cast<const char*>(view.begin() + offset) , amount * sizeof(typename View::value_t));
+                            break;
+                            
+                        default      : return false;
+                    }
+                    
+                    return true;
+                }
+                
+                template <typename View>
+                bool read(View& view, const std::size_t amount, const std::size_t offset = 0)
+                {
+                    switch (mode)
+                    {
+                        case e_read  : reinterpret_cast<std::ifstream*>(stream_ptr)->
+                            read(reinterpret_cast<char*>(view.begin() + offset), amount * sizeof(typename View::value_t));
+                            break;
+                            
+                        case e_rdwrt : reinterpret_cast<std::fstream*>(stream_ptr)->
+                            read(reinterpret_cast<char*>(view.begin() + offset) , amount * sizeof(typename View::value_t));
+                            break;
+                            
+                        default      : return false;
+                    }
+                    
+                    return true;
+                }
+                
+                bool getline(std::string& s)
+                {
+                    switch (mode)
+                    {
+                        case e_read  : return (!!std::getline(*reinterpret_cast<std::ifstream*>(stream_ptr),s));
+                        case e_rdwrt : return (!!std::getline(*reinterpret_cast<std::fstream* >(stream_ptr),s));
+                        default      : return false;
+                    }
+                }
+                
+                bool eof()
+                {
+                    switch (mode)
+                    {
+                        case e_read  : return reinterpret_cast<std::ifstream*>(stream_ptr)->eof();
+                        case e_write : return reinterpret_cast<std::ofstream*>(stream_ptr)->eof();
+                        case e_rdwrt : return reinterpret_cast<std::fstream* >(stream_ptr)->eof();
+                        default      : return true;
+                    }
+                }
+                
+                file_mode get_file_mode(const std::string& access)
+                {
+                    std::size_t w_cnt = 0;
+                    std::size_t r_cnt = 0;
+                    
+                    for (std::size_t i = 0; i < access.size(); ++i)
+                    {
+#ifdef MODIFICATION
+                        switch (access[i])
+#else
+                        switch (std::tolower(access[i]))
+#endif
+                        {
+                            case 'r' : r_cnt++; break;
+                            case 'w' : w_cnt++; break;
+                        }
+                    }
+                    
+                    if ((0 == r_cnt) && (0 == w_cnt))
+                        return e_error;
+                    else if ((r_cnt > 1) || (w_cnt > 1))
+                        return e_error;
+                    else if ((1 == r_cnt) && (1 == w_cnt))
+                        return e_rdwrt;
+                    else if (1 == r_cnt)
+                        return e_read;
+                    else
+                        return e_write;
+                }
+            };
+            
+            template <typename T>
+            file_descriptor* make_handle(T v)
+            {
+                file_descriptor* fd = reinterpret_cast<file_descriptor*>(0);
+                
+                std::memcpy(reinterpret_cast<char*>(&fd),
+                            reinterpret_cast<const char*>(&v),
+                            sizeof(fd));
+                return fd;
+            }
+            
+            template <typename T>
+            void perform_check()
+            {
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable: 4127)
+#endif
+                if (sizeof(T) < sizeof(void*))
+                {
+                    throw std::runtime_error("exprtk::rtl::io::file - Error - pointer size larger than holder.");
+                }
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+            }
+        } // namespace exprtk::rtl::io::file::details
+        
+        template <typename T>
+        class open : public exprtk::igeneric_function<T>
+        {
+        public:
+            
+            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::string_view    string_t;
+            
+            using exprtk::igeneric_function<T>::operator();
+            
+            open()
+            : exprtk::igeneric_function<T>("S|SS")
+            { details::perform_check<T>(); }
+            
+            inline T operator()(const std::size_t& ps_index, parameter_list_t parameters)
+            {
+                std::string file_name;
+                std::string access;
+                
+                file_name = to_str(string_t(parameters[0]));
+                
+                if (file_name.empty())
+                    return T(0);
+                
+                if (0 == ps_index)
+                    access = "r";
+                else if (0 == string_t(parameters[1]).size())
+                    return T(0);
+                else
+                    access = to_str(string_t(parameters[1]));
+                
+                details::file_descriptor* fd = new details::file_descriptor(file_name,access);
+                
+                if (fd->open())
+                {
+                    T t = T(0);
+                    
+                    std::memcpy(reinterpret_cast<char*>(&t),
+                                reinterpret_cast<char*>(&fd),
+                                sizeof(fd));
+                    return t;
+                }
+                else
+                {
+                    delete fd;
+                    return T(0);
+                }
+            }
+        };
+        
+        template <typename T>
+        struct close : public exprtk::ifunction<T>
+        {
+            using exprtk::ifunction<T>::operator();
+            
+            close()
+            : exprtk::ifunction<T>(1)
+            { details::perform_check<T>(); }
+            
+            inline T operator()(const T& v)
+            {
+                details::file_descriptor* fd = details::make_handle(v);
+                
+                if (!fd->close())
+                    return T(0);
+                
+                delete fd;
+                
+                return T(1);
+            }
+        };
+        
+        template <typename T>
+        class write : public exprtk::igeneric_function<T>
+        {
+        public:
+            
+            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::string_view    string_t;
+            typedef typename generic_type::scalar_view    scalar_t;
+            typedef typename generic_type::vector_view    vector_t;
+            
+            using exprtk::igeneric_function<T>::operator();
+            
+            write()
+            : igfun_t("TS|TST|TV|TVT")
+            { details::perform_check<T>(); }
+            
+            inline T operator()(const std::size_t& ps_index, parameter_list_t parameters)
+            {
+                details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])());
+                
+                std::size_t amount = 0;
+                
+                switch (ps_index)
+                {
+                    case 0  : {
+                        string_t buffer(parameters[1]);
+                        amount = buffer.size();
+                        return T(fd->write(buffer,amount) ? 1 : 0);
+                    }
+                        
+                    case 1  : {
+                        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);
+                    }
+                        
+                    case 2  : {
+                        vector_t vec(parameters[1]);
+                        amount = vec.size();
+                        return T(fd->write(vec,amount) ? 1 : 0);
+                    }
+                        
+                    case 3  : {
+                        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(0);
+            }
+        };
+        
+        template <typename T>
+        class read : public exprtk::igeneric_function<T>
+        {
+        public:
+            
+            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::string_view    string_t;
+            typedef typename generic_type::scalar_view    scalar_t;
+            typedef typename generic_type::vector_view    vector_t;
+            
+            using exprtk::igeneric_function<T>::operator();
+            
+            read()
+            : igfun_t("TS|TST|TV|TVT")
+            { details::perform_check<T>(); }
+            
+            inline T operator()(const std::size_t& ps_index, parameter_list_t parameters)
+            {
+                details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])());
+                
+                std::size_t amount = 0;
+                
+                switch (ps_index)
+                {
+                    case 0  : {
+                        string_t buffer(parameters[1]);
+                        amount = buffer.size();
+                        return T(fd->read(buffer,amount) ? 1 : 0);
+                    }
+                        
+                    case 1  : {
+                        string_t buffer(parameters[1]);
+                        amount = std::min(buffer.size(),
+                                          static_cast<std::size_t>(scalar_t(parameters[2])()));
+                        return T(fd->read(buffer,amount) ? 1 : 0);
+                    }
+                        
+                    case 2  : {
+                        vector_t vec(parameters[1]);
+                        amount = vec.size();
+                        return T(fd->read(vec,amount) ? 1 : 0);
+                    }
+                        
+                    case 3  : {
+                        vector_t vec(parameters[1]);
+                        amount = std::min(vec.size(),
+                                          static_cast<std::size_t>(scalar_t(parameters[2])()));
+                        return T(fd->read(vec,amount) ? 1 : 0);
+                    }
+                }
+                
+                return T(0);
+            }
+        };
+        
+        template <typename T>
+        class getline : public exprtk::igeneric_function<T>
+        {
+        public:
+            
+            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::string_view    string_t;
+            typedef typename generic_type::scalar_view    scalar_t;
+            
+            using exprtk::igeneric_function<T>::operator();
+            
+            getline()
+            : igfun_t("T",igfun_t::e_rtrn_string)
+            { details::perform_check<T>(); }
+            
+            inline T operator()(std::string& result,
+                                parameter_list_t parameters)
+            {
+                details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])());
+                return T(fd->getline(result) ? 1 : 0);
+            }
+        };
+        
+        template <typename T>
+        struct eof : public exprtk::ifunction<T>
+        {
+            using exprtk::ifunction<T>::operator();
+            
+            eof()
+            : exprtk::ifunction<T>(1)
+            { details::perform_check<T>(); }
+            
+            inline T operator()(const T& v)
+            {
+                details::file_descriptor* fd = details::make_handle(v);
+                
+                return (fd->eof() ? T(1) : T(0));
+            }
+        };
+        
+        template <typename T>
+        struct package
+        {
+            open   <T> o;
+            close  <T> c;
+            write  <T> w;
+            read   <T> r;
+            getline<T> g;
+            eof    <T> e;
+            
+            bool register_package(exprtk::symbol_table<T>& symtab)
+            {
+                if (!symtab.add_function("open"   ,o))
+                    return false;
+                else if (!symtab.add_function("close"  ,c))
+                    return false;
+                else if (!symtab.add_function("write"  ,w))
+                    return false;
+                else if (!symtab.add_function("read"   ,r))
+                    return false;
+                else if (!symtab.add_function("getline",g))
+                    return false;
+                else if (!symtab.add_function("eof"    ,e))
+                    return false;
+                else
+                    return true;
+            }
+        };
+        
+    } // namespace exprtk::rtl::io::file
+    } // namespace exprtk::rtl::io
+    } // namespace exprtk::rtl
+}    // namespace exprtk
+#endif
 
-   } // namespace information
+#ifndef exprtk_disable_rtl_vecops
+namespace exprtk
+{
+    namespace rtl { namespace vecops {
+        
+        namespace helper
+        {
+            template <typename Vector>
+            inline bool invalid_range(const Vector& v, const std::size_t r0, const std::size_t r1)
+            {
+                if (r0 > (v.size() - 1))
+                    return true;
+                else if (r1 > (v.size() - 1))
+                    return true;
+                else if (r1 < r0)
+                    return true;
+                else
+                    return false;
+            }
+            
+            template <typename T>
+            struct load_vector_range
+            {
+                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::scalar_view    scalar_t;
+                typedef typename generic_type::vector_view    vector_t;
+                
+                static inline bool process(parameter_list_t& parameters,
+                                           std::size_t& r0, std::size_t& r1,
+                                           const std::size_t& r0_prmidx,
+                                           const std::size_t& r1_prmidx,
+                                           const std::size_t vec_idx = 0)
+                {
+                    if (r0_prmidx >= parameters.size())
+                        return false;
+                    
+                    if (r1_prmidx >= parameters.size())
+                        return false;
+                    
+                    if (!scalar_t(parameters[r0_prmidx]).to_uint(r0))
+                        return false;
+                    
+                    if (!scalar_t(parameters[r1_prmidx]).to_uint(r1))
+                        return false;
+                    
+                    return !invalid_range(vector_t(parameters[vec_idx]),r0,r1);
+                }
+            };
+        }
+        
+        namespace details
+        {
+            template <typename T>
+            inline void kahan_sum(T& sum, T& error, T v)
+            {
+                T x = v - error;
+                T y = sum + x;
+                error = (y - sum) - x;
+                sum = y;
+            }
+            
+        } // namespace exprtk::rtl::details
+        
+        template <typename T>
+        class all_true : public exprtk::igeneric_function<T>
+        {
+        public:
+            
+            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();
+            
+            all_true()
+            : exprtk::igeneric_function<T>("V|VTT")
+            /*
+             Overloads:
+             0. V   - vector
+             1. VTT - vector, r0, r1
+             */
+            {}
+            
+            inline T operator()(const std::size_t& ps_index, parameter_list_t parameters)
+            {
+                const vector_t& vec(parameters[0]);
+                
+                std::size_t r0 = 0;
+                std::size_t r1 = vec.size() - 1;
+                
+                if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters,r0,r1,1,2,0))
+                    return std::numeric_limits<T>::quiet_NaN();
+                
+                for (std::size_t i = r0; i <= r1; ++i)
+                {
+                    if (vec[i] == T(0))
+                    {
+                        return T(0);
+                    }
+                }
+                
+                return T(1);
+            }
+        };
+        
+        template <typename T>
+        class all_false : public exprtk::igeneric_function<T>
+        {
+        public:
+            
+            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();
+            
+            all_false()
+            : exprtk::igeneric_function<T>("V|VTT")
+            /*
+             Overloads:
+             0. V   - vector
+             1. VTT - vector, r0, r1
+             */
+            {}
+            
+            inline T operator()(const std::size_t& ps_index, parameter_list_t parameters)
+            {
+                const vector_t& vec(parameters[0]);
+                
+                std::size_t r0 = 0;
+                std::size_t r1 = vec.size() - 1;
+                
+                if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters,r0,r1,1,2,0))
+                    return std::numeric_limits<T>::quiet_NaN();
+                
+                for (std::size_t i = r0; i <= r1; ++i)
+                {
+                    if (vec[i] != T(0))
+                    {
+                        return T(0);
+                    }
+                }
+                
+                return T(1);
+            }
+        };
+        
+        template <typename T>
+        class any_true : public exprtk::igeneric_function<T>
+        {
+        public:
+            
+            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();
+            
+            any_true()
+            : exprtk::igeneric_function<T>("V|VTT")
+            /*
+             Overloads:
+             0. V   - vector
+             1. VTT - vector, r0, r1
+             */
+            {}
+            
+            inline T operator()(const std::size_t& ps_index, parameter_list_t parameters)
+            {
+                const vector_t& vec(parameters[0]);
+                
+                std::size_t r0 = 0;
+                std::size_t r1 = vec.size() - 1;
+                
+                if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters,r0,r1,1,2,0))
+                    return std::numeric_limits<T>::quiet_NaN();
+                
+                for (std::size_t i = r0; i <= r1; ++i)
+                {
+                    if (vec[i] != T(0))
+                    {
+                        return T(1);
+                    }
+                }
+                
+                return T(0);
+            }
+        };
+        
+        template <typename T>
+        class any_false : public exprtk::igeneric_function<T>
+        {
+        public:
+            
+            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();
+            
+            any_false()
+            : exprtk::igeneric_function<T>("V|VTT")
+            /*
+             Overloads:
+             0. V   - vector
+             1. VTT - vector, r0, r1
+             */
+            {}
+            
+            inline T operator()(const std::size_t& ps_index, parameter_list_t parameters)
+            {
+                const vector_t& vec(parameters[0]);
+                
+                std::size_t r0 = 0;
+                std::size_t r1 = vec.size() - 1;
+                
+                if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters,r0,r1,1,2,0))
+                    return std::numeric_limits<T>::quiet_NaN();
+                
+                for (std::size_t i = r0; i <= r1; ++i)
+                {
+                    if (vec[i] == T(0))
+                    {
+                        return T(1);
+                    }
+                }
+                
+                return T(0);
+            }
+        };
+        
+        template <typename T>
+        class count : public exprtk::igeneric_function<T>
+        {
+        public:
+            
+            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();
+            
+            count()
+            : exprtk::igeneric_function<T>("V|VTT")
+            /*
+             Overloads:
+             0. V   - vector
+             1. VTT - vector, r0, r1
+             */
+            {}
+            
+            inline T operator()(const std::size_t& ps_index, parameter_list_t parameters)
+            {
+                const vector_t& vec(parameters[0]);
+                
+                std::size_t r0 = 0;
+                std::size_t r1 = vec.size() - 1;
+                
+                if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters,r0,r1,1,2,0))
+                    return std::numeric_limits<T>::quiet_NaN();
+                
+                std::size_t cnt = 0;
+                
+                for (std::size_t i = r0; i <= r1; ++i)
+                {
+                    if (vec[i] != T(0)) ++cnt;
+                }
+                
+                return T(cnt);
+            }
+        };
+        
+        template <typename T>
+        class copy : public exprtk::igeneric_function<T>
+        {
+        public:
+            
+            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::scalar_view    scalar_t;
+            typedef typename generic_type::vector_view    vector_t;
+            
+            using exprtk::igeneric_function<T>::operator();
+            
+            copy()
+            : exprtk::igeneric_function<T>("VV|VTTVTT")
+            /*
+             Overloads:
+             0. VV     - x(vector), y(vector)
+             1. VTTVTT - x(vector), xr0, xr1, y(vector), yr0, yr1,
+             */
+            {}
+            
+            inline T operator()(const std::size_t& ps_index, parameter_list_t parameters)
+            {
+                vector_t x(parameters[0]);
+                vector_t y(parameters[(0 == ps_index) ? 1 : 3]);
+                
+                std::size_t xr0 = 0;
+                std::size_t xr1 = x.size() - 1;
+                
+                std::size_t yr0 = 0;
+                std::size_t yr1 = y.size() - 1;
+                
+                if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters,xr0,xr1,1,2,0))
+                    return T(0);
+                if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters,yr0,yr1,4,5,3))
+                    return T(0);
+                
+                const std::size_t n = std::min(xr1 - xr0 + 1, yr1 - yr0 + 1);
+                
+                std::copy(x.begin() + xr0, x.begin() + xr0 + n, y.begin() + yr0);
+                
+                return T(n);
+            }
+        };
+        
+        template <typename T>
+        class rol : public exprtk::igeneric_function<T>
+        {
+        public:
+            
+            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::scalar_view    scalar_t;
+            typedef typename generic_type::vector_view    vector_t;
+            
+            using exprtk::igeneric_function<T>::operator();
+            
+            rol()
+            : exprtk::igeneric_function<T>("VT|VTTT")
+            /*
+             Overloads:
+             0. VT   - vector, N
+             1. VTTT - vector, N, r0, r1
+             */
+            {}
+            
+            inline T operator()(const std::size_t& ps_index, parameter_list_t parameters)
+            {
+                vector_t vec(parameters[0]);
+                
+                std::size_t n  = 0;
+                std::size_t r0 = 0;
+                std::size_t r1 = vec.size() - 1;
+                
+                if (!scalar_t(parameters[1]).to_uint(n))
+                    return T(0);
+                
+                if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters,r0,r1,2,3,0))
+                    return T(0);
+                
+                std::size_t dist  = r1 - r0 + 1;
+                std::size_t shift = n % dist;
+                
+                std::rotate(vec.begin() + r0, vec.begin() + r0 + shift, vec.begin() + r1 + 1);
+                
+                return T(1);
+            }
+        };
+        
+        template <typename T>
+        class ror : public exprtk::igeneric_function<T>
+        {
+        public:
+            
+            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::scalar_view    scalar_t;
+            typedef typename generic_type::vector_view    vector_t;
+            
+            using exprtk::igeneric_function<T>::operator();
+            
+            ror()
+            : exprtk::igeneric_function<T>("VT|VTTT")
+            /*
+             Overloads:
+             0. VT   - vector, N
+             1. VTTT - vector, N, r0, r1
+             */
+            {}
+            
+            inline T operator()(const std::size_t& ps_index, parameter_list_t parameters)
+            {
+                vector_t vec(parameters[0]);
+                
+                std::size_t n  = 0;
+                std::size_t r0 = 0;
+                std::size_t r1 = vec.size() - 1;
+                
+                if (!scalar_t(parameters[1]).to_uint(n))
+                    return T(0);
+                
+                if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters,r0,r1,2,3,0))
+                    return T(0);
+                
+                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);
+                
+                return T(1);
+            }
+        };
+        
+        template <typename T>
+        class shift_left : public exprtk::igeneric_function<T>
+        {
+        public:
+            
+            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::scalar_view    scalar_t;
+            typedef typename generic_type::vector_view    vector_t;
+            
+            using exprtk::igeneric_function<T>::operator();
+            
+            shift_left()
+            : exprtk::igeneric_function<T>("VT|VTTT")
+            /*
+             Overloads:
+             0. VT   - vector, N
+             1. VTTT - vector, N, r0, r1
+             */
+            {}
+            
+            inline T operator()(const std::size_t& ps_index, parameter_list_t parameters)
+            {
+                vector_t vec(parameters[0]);
+                
+                std::size_t n  = 0;
+                std::size_t r0 = 0;
+                std::size_t r1 = vec.size() - 1;
+                
+                if (!scalar_t(parameters[1]).to_uint(n))
+                    return T(0);
+                
+                if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters,r0,r1,2,3,0))
+                    return T(0);
+                
+                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);
+                
+                for (std::size_t i = r1 - n + 1; i <= r1; ++i)
+                {
+                    vec[i] = T(0);
+                }
+                
+                return T(1);
+            }
+        };
+        
+        template <typename T>
+        class shift_right : public exprtk::igeneric_function<T>
+        {
+        public:
+            
+            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::scalar_view    scalar_t;
+            typedef typename generic_type::vector_view    vector_t;
+            
+            using exprtk::igeneric_function<T>::operator();
+            
+            shift_right()
+            : exprtk::igeneric_function<T>("VT|VTTT")
+            /*
+             Overloads:
+             0. VT   - vector, N
+             1. VTTT - vector, N, r0, r1
+             */
+            {}
+            
+            inline T operator()(const std::size_t& ps_index, parameter_list_t parameters)
+            {
+                vector_t vec(parameters[0]);
+                
+                std::size_t n  = 0;
+                std::size_t r0 = 0;
+                std::size_t r1 = vec.size() - 1;
+                
+                if (!scalar_t(parameters[1]).to_uint(n))
+                    return T(0);
+                
+                if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters,r0,r1,2,3,0))
+                    return T(0);
+                
+                std::size_t dist  = r1 - r0 + 1;
+                
+                if (n > dist)
+                    return T(0);
+                
+                std::size_t shift = (dist - (n % dist)) % dist;
+                
+                std::rotate(vec.begin() + r0, vec.begin() + r0 + shift, vec.begin() + r1 + 1);
+                
+                for (std::size_t i = r0; i < r0 + n; ++i)
+                {
+                    vec[i] = T(0);
+                }
+                
+                return T(1);
+            }
+        };
+        
+        template <typename T>
+        class sort : public exprtk::igeneric_function<T>
+        {
+        public:
+            
+            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::string_view    string_t;
+            typedef typename generic_type::vector_view    vector_t;
+            
+            using exprtk::igeneric_function<T>::operator();
+            
+            sort()
+            : exprtk::igeneric_function<T>("V|VTT|VS|VSTT")
+            /*
+             Overloads:
+             0. V    - vector
+             1. VTT  - vector, r0, r1
+             2. VS   - vector, string
+             3. VSTT - vector, string, r0, r1
+             */
+            {}
+            
+            inline T operator()(const std::size_t& ps_index, parameter_list_t parameters)
+            {
+                vector_t vec(parameters[0]);
+                
+                std::size_t r0 = 0;
+                std::size_t r1 = vec.size() - 1;
+                
+                if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters,r0,r1,1,2,0))
+                    return T(0);
+                if ((3 == ps_index) && !helper::load_vector_range<T>::process(parameters,r0,r1,2,3,0))
+                    return T(0);
+                
+                bool ascending = true;
+                
+                if ((2 == ps_index) || (3 == ps_index))
+                {
+                    if (exprtk::details::imatch(to_str(string_t(parameters[1])),"ascending"))
+                        ascending = true;
+                    else if (exprtk::details::imatch(to_str(string_t(parameters[1])),"descending"))
+                        ascending = false;
+                    else
+                        return T(0);
+                }
+                
+                if (ascending)
+                    std::sort(vec.begin() + r0, vec.begin() + r1 + 1, std::less<T>   ());
+                else
+                    std::sort(vec.begin() + r0, vec.begin() + r1 + 1, std::greater<T>());
+                
+                return T(1);
+            }
+        };
+        
+        template <typename T>
+        class nthelement : public exprtk::igeneric_function<T>
+        {
+        public:
+            
+            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::scalar_view    scalar_t;
+            typedef typename generic_type::vector_view    vector_t;
+            
+            using exprtk::igeneric_function<T>::operator();
+            
+            nthelement()
+            : exprtk::igeneric_function<T>("VT|VTTT")
+            /*
+             Overloads:
+             0. VT   - vector, nth-element
+             1. VTTT - vector, nth-element, r0, r1
+             */
+            {}
+            
+            inline T operator()(const std::size_t& ps_index, parameter_list_t parameters)
+            {
+                vector_t vec(parameters[0]);
+                
+                std::size_t n  = 0;
+                std::size_t r0 = 0;
+                std::size_t r1 = vec.size() - 1;
+                
+                if (!scalar_t(parameters[1]).to_uint(n))
+                    return T(0);
+                
+                if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters,r0,r1,2,3,0))
+                    return std::numeric_limits<T>::quiet_NaN();
+                
+                std::nth_element(vec.begin() + r0, vec.begin() + r0 + n , vec.begin() + r1 + 1);
+                
+                return T(1);
+            }
+        };
+        
+        template <typename T>
+        class iota : public exprtk::igeneric_function<T>
+        {
+        public:
+            
+            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::scalar_view    scalar_t;
+            typedef typename generic_type::vector_view    vector_t;
+            
+            using exprtk::igeneric_function<T>::operator();
+            
+            iota()
+            : exprtk::igeneric_function<T>("VT|VTT|VTTT|VTTTT")
+            /*
+             Overloads:
+             0. VT    - vector, increment
+             1. VTT   - vector, increment, base
+             2. VTTTT - vector, increment, r0, r1
+             3. VTTTT - vector, increment, base, r0, r1
+             */
+            {}
+            
+            inline T operator()(const std::size_t& ps_index, parameter_list_t parameters)
+            {
+                vector_t vec(parameters[0]);
+                
+                T increment = scalar_t(parameters[1])();
+                T base      = ((1 == ps_index) || (3 == ps_index))? scalar_t(parameters[2])() : T(0);
+                
+                std::size_t r0 = 0;
+                std::size_t r1 = vec.size() - 1;
+                
+                if ((2 == ps_index) && !helper::load_vector_range<T>::process(parameters,r0,r1,2,3,0))
+                    return std::numeric_limits<T>::quiet_NaN();
+                else if ((3 == ps_index) && !helper::load_vector_range<T>::process(parameters,r0,r1,3,4,0))
+                    return std::numeric_limits<T>::quiet_NaN();
+                else
+                {
+                    long long j = 0;
+                    
+                    for (std::size_t i = r0; i <= r1; ++i, ++j)
+                    {
+                        vec[i] = base + (increment * j);
+                    }
+                }
+                
+                return T(1);
+            }
+        };
+        
+        template <typename T>
+        class sumk : public exprtk::igeneric_function<T>
+        {
+        public:
+            
+            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();
+            
+            sumk()
+            : exprtk::igeneric_function<T>("V|VTT")
+            /*
+             Overloads:
+             0. V   - vector
+             1. VTT - vector, r0, r1
+             */
+            {}
+            
+            inline T operator()(const std::size_t& ps_index, parameter_list_t parameters)
+            {
+                vector_t vec(parameters[0]);
+                
+                std::size_t r0 = 0;
+                std::size_t r1 = vec.size() - 1;
+                
+                if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters,r0,r1,1,2,0))
+                    return std::numeric_limits<T>::quiet_NaN();
+                
+                T result = T(0);
+                T error  = T(0);
+                
+                for (std::size_t i = r0; i <= r1; ++i)
+                {
+                    details::kahan_sum(result,error,vec[i]);
+                }
+                
+                return result;
+            }
+        };
+        
+        template <typename T>
+        class axpy : public exprtk::igeneric_function<T>
+        {
+        public:
+            
+            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::scalar_view    scalar_t;
+            typedef typename generic_type::vector_view    vector_t;
+            
+            using exprtk::igeneric_function<T>::operator();
+            
+            axpy()
+            : exprtk::igeneric_function<T>("TVV|TVVTT")
+            /*
+             y <- ax + y
+             Overloads:
+             0. TVV   - a, x(vector), y(vector)
+             1. TVVTT - a, x(vector), y(vector), r0, r1
+             */
+            {}
+            
+            inline T operator()(const std::size_t& ps_index, parameter_list_t parameters)
+            {
+                vector_t x(parameters[1]);
+                vector_t y(parameters[2]);
+                
+                std::size_t r0 = 0;
+                std::size_t r1 = std::min(x.size(),y.size()) - 1;
+                
+                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))
+                    return std::numeric_limits<T>::quiet_NaN();
+                
+                T a = scalar_t(parameters[0])();
+                
+                for (std::size_t i = r0; i <= r1; ++i)
+                {
+                    y[i] = a * x[i] + y[i];
+                }
+                
+                return T(1);
+            }
+        };
+        
+        template <typename T>
+        class axpby : public exprtk::igeneric_function<T>
+        {
+        public:
+            
+            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::scalar_view    scalar_t;
+            typedef typename generic_type::vector_view    vector_t;
+            
+            using exprtk::igeneric_function<T>::operator();
+            
+            axpby()
+            : exprtk::igeneric_function<T>("TVTV|TVTVTT")
+            /*
+             y <- ax + by
+             Overloads:
+             0. TVTV   - a, x(vector), b, y(vector)
+             1. TVTVTT - a, x(vector), b, y(vector), r0, r1
+             */
+            {}
+            
+            inline T operator()(const std::size_t& ps_index, parameter_list_t parameters)
+            {
+                vector_t x(parameters[1]);
+                vector_t y(parameters[3]);
+                
+                std::size_t r0 = 0;
+                std::size_t r1 = std::min(x.size(),y.size()) - 1;
+                
+                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))
+                    return std::numeric_limits<T>::quiet_NaN();
+                
+                const T a = scalar_t(parameters[0])();
+                const T b = scalar_t(parameters[2])();
+                
+                for (std::size_t i = r0; i <= r1; ++i)
+                {
+                    y[i] = (a * x[i]) + (b * y[i]);
+                }
+                
+                return T(1);
+            }
+        };
+        
+        template <typename T>
+        class axpyz : public exprtk::igeneric_function<T>
+        {
+        public:
+            
+            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::scalar_view    scalar_t;
+            typedef typename generic_type::vector_view    vector_t;
+            
+            using exprtk::igeneric_function<T>::operator();
+            
+            axpyz()
+            : exprtk::igeneric_function<T>("TVVV|TVVVTT")
+            /*
+             z <- ax + y
+             Overloads:
+             0. TVVV   - a, x(vector), y(vector), z(vector)
+             1. TVVVTT - a, x(vector), y(vector), z(vector), r0, r1
+             */
+            {}
+            
+            inline T operator()(const std::size_t& ps_index, parameter_list_t parameters)
+            {
+                vector_t x(parameters[1]);
+                vector_t y(parameters[2]);
+                vector_t z(parameters[3]);
+                
+                std::size_t r0 = 0;
+                std::size_t r1 = std::min(x.size(),y.size()) - 1;
+                
+                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))
+                    return std::numeric_limits<T>::quiet_NaN();
+                else if (helper::invalid_range(z,r0,r1))
+                    return std::numeric_limits<T>::quiet_NaN();
+                
+                T a = scalar_t(parameters[0])();
+                
+                for (std::size_t i = r0; i <= r1; ++i)
+                {
+                    z[i] = a * x[i] + y[i];
+                }
+                
+                return T(1);
+            }
+        };
+        
+        template <typename T>
+        class axpbyz : public exprtk::igeneric_function<T>
+        {
+        public:
+            
+            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::scalar_view    scalar_t;
+            typedef typename generic_type::vector_view    vector_t;
+            
+            using exprtk::igeneric_function<T>::operator();
+            
+            axpbyz()
+            : exprtk::igeneric_function<T>("TVTVV|TVTVVTT")
+            /*
+             z <- ax + by
+             Overloads:
+             0. TVTVV   - a, x(vector), b, y(vector), z(vector)
+             1. TVTVVTT - a, x(vector), b, y(vector), z(vector), r0, r1
+             */
+            {}
+            
+            inline T operator()(const std::size_t& ps_index, parameter_list_t parameters)
+            {
+                vector_t x(parameters[1]);
+                vector_t y(parameters[3]);
+                vector_t z(parameters[4]);
+                
+                std::size_t r0 = 0;
+                std::size_t r1 = std::min(x.size(),y.size()) - 1;
+                
+                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))
+                    return std::numeric_limits<T>::quiet_NaN();
+                else if (helper::invalid_range(z,r0,r1))
+                    return std::numeric_limits<T>::quiet_NaN();
+                
+                const T a = scalar_t(parameters[0])();
+                const T b = scalar_t(parameters[2])();
+                
+                for (std::size_t i = r0; i <= r1; ++i)
+                {
+                    z[i] = (a * x[i]) + (b * y[i]);
+                }
+                
+                return T(1);
+            }
+        };
+        
+        template <typename T>
+        class axpbz : public exprtk::igeneric_function<T>
+        {
+        public:
+            
+            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::scalar_view    scalar_t;
+            typedef typename generic_type::vector_view    vector_t;
+            
+            using exprtk::igeneric_function<T>::operator();
+            
+            axpbz()
+            : exprtk::igeneric_function<T>("TVTV|TVTVTT")
+            /*
+             z <- ax + b
+             Overloads:
+             0. TVTV   - a, x(vector), b, z(vector)
+             1. TVTVTT - a, x(vector), b, z(vector), r0, r1
+             */
+            {}
+            
+            inline T operator()(const std::size_t& ps_index, parameter_list_t parameters)
+            {
+                vector_t x(parameters[1]);
+                vector_t z(parameters[3]);
+                
+                std::size_t r0 = 0;
+                std::size_t r1 = x.size() - 1;
+                
+                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))
+                    return std::numeric_limits<T>::quiet_NaN();
+                
+                const T a = scalar_t(parameters[0])();
+                const T b = scalar_t(parameters[2])();
+                
+                for (std::size_t i = r0; i <= r1; ++i)
+                {
+                    z[i] = a * x[i] + b;
+                }
+                
+                return T(1);
+            }
+        };
+        
+        template <typename T>
+        class dot : public exprtk::igeneric_function<T>
+        {
+        public:
+            
+            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::scalar_view    scalar_t;
+            typedef typename generic_type::vector_view    vector_t;
+            
+            using exprtk::igeneric_function<T>::operator();
+            
+            dot()
+            : exprtk::igeneric_function<T>("VV|VVTT")
+            /*
+             Overloads:
+             0. VV   - x(vector), y(vector)
+             1. VVTT - x(vector), y(vector), r0, r1
+             */
+            {}
+            
+            inline T operator()(const std::size_t& ps_index, parameter_list_t parameters)
+            {
+                vector_t x(parameters[0]);
+                vector_t y(parameters[1]);
+                
+                std::size_t r0 = 0;
+                std::size_t r1 = std::min(x.size(),y.size()) - 1;
+                
+                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))
+                    return std::numeric_limits<T>::quiet_NaN();
+                
+                T result = T(0);
+                
+                for (std::size_t i = r0; i <= r1; ++i)
+                {
+                    result += (x[i] * y[i]);
+                }
+                
+                return result;
+            }
+        };
+        
+        template <typename T>
+        class dotk : public exprtk::igeneric_function<T>
+        {
+        public:
+            
+            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::scalar_view    scalar_t;
+            typedef typename generic_type::vector_view    vector_t;
+            
+            using exprtk::igeneric_function<T>::operator();
+            
+            dotk()
+            : exprtk::igeneric_function<T>("VV|VVTT")
+            /*
+             Overloads:
+             0. VV   - x(vector), y(vector)
+             1. VVTT - x(vector), y(vector), r0, r1
+             */
+            {}
+            
+            inline T operator()(const std::size_t& ps_index, parameter_list_t parameters)
+            {
+                vector_t x(parameters[0]);
+                vector_t y(parameters[1]);
+                
+                std::size_t r0 = 0;
+                std::size_t r1 = std::min(x.size(),y.size()) - 1;
+                
+                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))
+                    return std::numeric_limits<T>::quiet_NaN();
+                
+                T result = T(0);
+                T error  = T(0);
+                
+                for (std::size_t i = r0; i <= r1; ++i)
+                {
+                    details::kahan_sum(result,error,(x[i] * y[i]));
+                }
+                
+                return result;
+            }
+        };
+        
+        template <typename T>
+        struct package
+        {
+            all_true   <T> at;
+            all_false  <T> af;
+            any_true   <T> nt;
+            any_false  <T> nf;
+            count      <T>  c;
+            copy       <T> cp;
+            rol        <T> rl;
+            ror        <T> rr;
+            shift_left <T> sl;
+            shift_right<T> sr;
+            sort       <T> st;
+            nthelement <T> ne;
+            iota       <T> ia;
+            sumk       <T> sk;
+            axpy       <T> b1_axpy;
+            axpby      <T> b1_axpby;
+            axpyz      <T> b1_axpyz;
+            axpbyz     <T> b1_axpbyz;
+            axpbz      <T> b1_axpbz;
+            dot        <T> dt;
+            dotk       <T> dtk;
+            
+            bool register_package(exprtk::symbol_table<T>& symtab)
+            {
+                if (!symtab.add_function("all_true"     ,at))
+                    return false;
+                else if (!symtab.add_function("all_false"    ,af))
+                    return false;
+                else if (!symtab.add_function("any_true"     ,nt))
+                    return false;
+                else if (!symtab.add_function("any_false"    ,nf))
+                    return false;
+                else if (!symtab.add_function("count"        , c))
+                    return false;
+                else if (!symtab.add_function("copy"        , cp))
+                    return false;
+                else if (!symtab.add_function("rotate_left"  ,rl))
+                    return false;
+                else if (!symtab.add_function("rol"          ,rl))
+                    return false;
+                else if (!symtab.add_function("rotate_right" ,rr))
+                    return false;
+                else if (!symtab.add_function("ror"          ,rr))
+                    return false;
+                else if (!symtab.add_function("shftl"        ,sl))
+                    return false;
+                else if (!symtab.add_function("shftr"        ,sr))
+                    return false;
+                else if (!symtab.add_function("sort"         ,st))
+                    return false;
+                else if (!symtab.add_function("nth_element"  ,ne))
+                    return false;
+                else if (!symtab.add_function("iota"         ,ia))
+                    return false;
+                else if (!symtab.add_function("sumk"         ,sk))
+                    return false;
+                else if (!symtab.add_function("axpy"    ,b1_axpy))
+                    return false;
+                else if (!symtab.add_function("axpby"  ,b1_axpby))
+                    return false;
+                else if (!symtab.add_function("axpyz"  ,b1_axpyz))
+                    return false;
+                else if (!symtab.add_function("axpbyz",b1_axpbyz))
+                    return false;
+                else if (!symtab.add_function("axpbz"  ,b1_axpbz))
+                    return false;
+                else if (!symtab.add_function("dot"          ,dt))
+                    return false;
+                else if (!symtab.add_function("dotk"        ,dtk))
+                    return false;
+                else
+                    return true;
+            }
+        };
+        
+    } // namespace exprtk::rtl::vecops
+    } // namespace exprtk::rtl
+}    // namespace exprtk
+#endif
 
+namespace exprtk
+{
+    namespace information
+    {
+        static const char* library = "Mathematical Expression Toolkit";
+        static const char* version = "2.71828182845904523536028747135266249775"
+        "7247093699959574966967627724076630353547";
+        static const char* date    = "20161010";
+        
+        static inline std::string data()
+        {
+            static const std::string info_str = std::string(library) +
+            std::string(" v") + std::string(version) +
+            std::string(" (") + date + std::string(")");
+            return info_str;
+        }
+        
+    } // namespace information
+    
 } // namespace exprtk
 
 #endif
diff --git a/src/generator/JaniNextStateGenerator.cpp b/src/generator/JaniNextStateGenerator.cpp
index 539e01d9f..ac5fe202c 100644
--- a/src/generator/JaniNextStateGenerator.cpp
+++ b/src/generator/JaniNextStateGenerator.cpp
@@ -390,9 +390,6 @@ namespace storm {
             // Iterate over all automata.
             uint64_t automatonIndex = 0;
             
-            std::cout << "getting silent choices of state" << std::endl;
-            std::cout << unpackStateIntoValuation(state, this->variableInformation, *this->expressionManager).toString(true) << std::endl;
-            
             for (auto const& automaton : model.getAutomata()) {
                 uint64_t location = locations[automatonIndex];
                 
@@ -405,10 +402,8 @@ namespace storm {
                     
                     // Skip the command, if it is not enabled.
                     if (!this->evaluator->asBool(edge.getGuard())) {
-                        std::cout << "guard " << edge.getGuard() << " evaluates to false" << std::endl;
                         continue;
                     }
-                    std::cout << "guard " << edge.getGuard() << " evaluates to true" << std::endl;
                     
                     // Determine the exit rate if it's a Markovian edge.
                     boost::optional<ValueType> exitRate = boost::none;
@@ -427,7 +422,6 @@ namespace storm {
                         if (probability != storm::utility::zero<ValueType>()) {
                             // Obtain target state index and add it to the list of known states. If it has not yet been
                             // seen, we also add it to the set of states that have yet to be explored.
-                            std::cout << "got new state " << unpackStateIntoValuation(applyUpdate(state, destination, this->variableInformation.locationVariables[automatonIndex]), this->variableInformation, *this->expressionManager).toString(true) << std::endl;
                             StateType stateIndex = stateToIdCallback(applyUpdate(state, destination, this->variableInformation.locationVariables[automatonIndex]));
                             
                             // Update the choice by adding the probability/target state to it.
@@ -459,9 +453,6 @@ namespace storm {
         std::vector<Choice<ValueType>> JaniNextStateGenerator<ValueType, StateType>::getNonsilentActionChoices(std::vector<uint64_t> const& locations, CompressedState const& state, StateToIdCallback stateToIdCallback) {
             std::vector<Choice<ValueType>> result;
             
-            std::cout << "getting nonsilent choices of state" << std::endl;
-            std::cout << unpackStateIntoValuation(state, this->variableInformation, *this->expressionManager).toString(true) << std::endl;
-            
             for (uint64_t actionIndex : model.getNonsilentActionIndices()) {
                 std::vector<std::vector<storm::jani::Edge const*>> enabledEdges = getEnabledEdges(locations, actionIndex);
                 
@@ -539,8 +530,6 @@ namespace storm {
                         // Add the probabilities/rates to the newly created choice.
                         ValueType probabilitySum = storm::utility::zero<ValueType>();
                         for (auto const& stateProbabilityPair : *newTargetStates) {
-                            std::cout << "got new state (sync)" << std::endl;
-                            std::cout << unpackStateIntoValuation(stateProbabilityPair.first, this->variableInformation, *this->expressionManager).toString(true) << std::endl;
                             StateType actualIndex = stateToIdCallback(stateProbabilityPair.first);
                             choice.addProbability(actualIndex, stateProbabilityPair.second);
                             
diff --git a/src/storage/expressions/ExprtkExpressionEvaluator.cpp b/src/storage/expressions/ExprtkExpressionEvaluator.cpp
index b1cc76c9d..38ba16dee 100755
--- a/src/storage/expressions/ExprtkExpressionEvaluator.cpp
+++ b/src/storage/expressions/ExprtkExpressionEvaluator.cpp
@@ -20,7 +20,6 @@ namespace storm {
                     symbolTable.add_variable(variableTypePair.first.getName(), this->rationalValues[variableTypePair.first.getOffset()]);
                 }
             }
-            symbolTable.add_constants();
         }
         
         template<typename RationalType>