www.mooseframework.org
ExpressionBuilder.h
Go to the documentation of this file.
1 /****************************************************************/
2 /* MOOSE - Multiphysics Object Oriented Simulation Environment */
3 /* */
4 /* All contents are licensed under LGPL V2.1 */
5 /* See LICENSE for full restrictions */
6 /****************************************************************/
7 #ifndef EXPRESSIONBUILDER_H
8 #define EXPRESSIONBUILDER_H
9 
10 #include <vector>
11 #include <ostream>
12 #include <sstream>
13 #include <iomanip>
14 
15 #include "MooseError.h"
16 #include "libmesh/libmesh_common.h"
17 
18 using namespace libMesh;
19 
46 {
47 public:
49 
50  // forward delcarations
51  class EBTerm;
52  class EBTermNode;
53  class EBFunction;
55  typedef std::vector<EBTerm> EBTermList;
56  typedef std::vector<EBTermNode *> EBTermNodeList;
57  typedef std::vector<const EBSubstitutionRule *> EBSubstitutionRuleList;
58 
60  class EBTermNode
61  {
62  public:
63  virtual ~EBTermNode(){};
64  virtual EBTermNode * clone() const = 0;
65 
66  virtual std::string stringify() const = 0;
67  virtual unsigned int substitute(const EBSubstitutionRuleList & /*rule*/) { return 0; }
68  virtual int precedence() const = 0;
69  friend std::ostream & operator<<(std::ostream & os, const EBTermNode & node)
70  {
71  return os << node.stringify();
72  }
73  };
74 
76  template <typename T>
77  class EBNumberNode : public EBTermNode
78  {
79  T _value;
80 
81  public:
82  EBNumberNode(T value) : _value(value){};
83  virtual EBNumberNode<T> * clone() const { return new EBNumberNode(_value); }
84 
85  virtual std::string stringify() const;
86  virtual int precedence() const { return 0; }
87  };
88 
90  class EBSymbolNode : public EBTermNode
91  {
92  std::string _symbol;
93 
94  public:
95  EBSymbolNode(std::string symbol) : _symbol(symbol){};
96  virtual EBSymbolNode * clone() const { return new EBSymbolNode(_symbol); }
97 
98  virtual std::string stringify() const;
99  virtual int precedence() const { return 0; }
100  };
101 
106  class EBTempIDNode : public EBTermNode
107  {
108  unsigned long _id;
109 
110  public:
111  EBTempIDNode(unsigned int id) : _id(id){};
112  virtual EBTempIDNode * clone() const { return new EBTempIDNode(_id); }
113 
114  virtual std::string stringify() const; // returns "[idnumber]"
115  virtual int precedence() const { return 0; }
116  };
117 
120  {
121  public:
122  EBUnaryTermNode(EBTermNode * subnode) : _subnode(subnode){};
123  virtual ~EBUnaryTermNode() { delete _subnode; };
124 
125  virtual unsigned int substitute(const EBSubstitutionRuleList & rule);
126  const EBTermNode * getSubnode() const { return _subnode; }
127 
128  protected:
130  };
131 
134  {
135  public:
136  enum NodeType
137  {
147  COSH
148  } _type;
149 
151  : EBUnaryTermNode(subnode), _type(type){};
152  virtual EBUnaryFuncTermNode * clone() const
153  {
154  return new EBUnaryFuncTermNode(_subnode->clone(), _type);
155  };
156 
157  virtual std::string stringify() const;
158  virtual int precedence() const { return 2; }
159  };
160 
163  {
164  public:
165  enum NodeType
166  {
168  LOGICNOT
169  } _type;
170 
172  : EBUnaryTermNode(subnode), _type(type){};
173  virtual EBUnaryOpTermNode * clone() const
174  {
175  return new EBUnaryOpTermNode(_subnode->clone(), _type);
176  };
177 
178  virtual std::string stringify() const;
179  virtual int precedence() const { return 3; }
180  };
181 
184  {
185  public:
186  EBBinaryTermNode(EBTermNode * left, EBTermNode * right) : _left(left), _right(right){};
188  {
189  delete _left;
190  delete _right;
191  };
192 
193  virtual unsigned int substitute(const EBSubstitutionRuleList & rule);
194 
195  protected:
198  };
199 
202  {
203  public:
204  enum NodeType
205  {
216  EQ,
217  NOTEQ
218  };
219 
221  : EBBinaryTermNode(left, right), _type(type){};
222  virtual EBBinaryOpTermNode * clone() const
223  {
224  return new EBBinaryOpTermNode(_left->clone(), _right->clone(), _type);
225  };
226 
227  virtual std::string stringify() const;
228  virtual int precedence() const;
229 
230  protected:
232  };
233 
236  {
237  public:
238  enum NodeType
239  {
244  PLOG
245  } _type;
246 
248  : EBBinaryTermNode(left, right), _type(type){};
249  virtual EBBinaryFuncTermNode * clone() const
250  {
251  return new EBBinaryFuncTermNode(_left->clone(), _right->clone(), _type);
252  };
253 
254  virtual std::string stringify() const;
255  virtual int precedence() const { return 2; }
256  };
257 
260  {
261  public:
263  : EBBinaryTermNode(left, right), _middle(middle){};
264  virtual ~EBTernaryTermNode() { delete _middle; };
265 
266  virtual unsigned int substitute(const EBSubstitutionRuleList & rule);
267 
268  protected:
270  };
271 
274  {
275  public:
276  enum NodeType
277  {
278  CONDITIONAL
279  } _type;
280 
282  : EBTernaryTermNode(left, middle, right), _type(type){};
283  virtual EBTernaryFuncTermNode * clone() const
284  {
285  return new EBTernaryFuncTermNode(_left->clone(), _middle->clone(), _right->clone(), _type);
286  };
287 
288  virtual std::string stringify() const;
289  virtual int precedence() const { return 2; }
290  };
291 
296  {
297  public:
298  virtual EBTermNode * apply(const EBTermNode *) const = 0;
299  virtual ~EBSubstitutionRule() {}
300  };
301 
305  template <class Node_T>
307  {
308  public:
309  virtual EBTermNode * apply(const EBTermNode *) const;
310 
311  protected:
312  // on successful substitution this returns a new node to replace the old one, otherwise it
313  // returns NULL
314  virtual EBTermNode * substitute(const Node_T &) const = 0;
315  };
316 
321  class EBTermSubstitution : public EBSubstitutionRuleTyped<EBSymbolNode>
322  {
323  public:
324  EBTermSubstitution(const EBTerm & find, const EBTerm & replace);
325  virtual ~EBTermSubstitution() { delete _replace; }
326  protected:
327  virtual EBTermNode * substitute(const EBSymbolNode &) const;
328  std::string _find;
330  };
331 
336  class EBLogPlogSubstitution : public EBSubstitutionRuleTyped<EBUnaryFuncTermNode>
337  {
338  public:
339  EBLogPlogSubstitution(const EBTerm & epsilon) : _epsilon(epsilon.cloneRoot())
340  {
341  mooseAssert(_epsilon != NULL, "Epsilon must not be an empty term in EBLogPlogSubstitution");
342  }
343  virtual ~EBLogPlogSubstitution() { delete _epsilon; }
344  protected:
345  virtual EBTermNode * substitute(const EBUnaryFuncTermNode &) const;
347  };
348 
355  class EBTerm
356  {
357  public:
358  // the default constructor assigns a temporary id node to root we use the address of the
359  // current EBTerm object as the ID. This could be problematic if we create and destroy terms,
360  // but then we should not expect the substitution to do sane things anyways.
361  EBTerm() : _root(new EBTempIDNode(reinterpret_cast<unsigned long>(this))){};
362 
363  EBTerm(const EBTerm & term) : _root(term.cloneRoot()){};
364  ~EBTerm() { delete _root; };
365 
366  private:
367  // construct a term from a node
368  EBTerm(EBTermNode * root) : _root(root){};
369 
370  public:
371  // construct from number or string
372  EBTerm(int number) : _root(new EBNumberNode<int>(number)) {}
373  EBTerm(Real number) : _root(new EBNumberNode<Real>(number)) {}
374  EBTerm(const char * symbol) : _root(new EBSymbolNode(symbol)) {}
375 
376  // concatenate terms to form a parameter list with (()) syntax (those need to be out-of-class!)
377  friend EBTermList operator,(const ExpressionBuilder::EBTerm & larg,
378  const ExpressionBuilder::EBTerm & rarg);
379  friend EBTermList operator,(const ExpressionBuilder::EBTerm & larg,
380  const ExpressionBuilder::EBTermList & rargs);
381  friend EBTermList operator,(const ExpressionBuilder::EBTermList & largs,
382  const ExpressionBuilder::EBTerm & rarg);
383 
384  // dump term as FParser expression
385  friend std::ostream & operator<<(std::ostream & os, const EBTerm & term);
386  // cast into a string
387  operator std::string() const { return _root->stringify(); }
388 
389  // assign a term
390  EBTerm & operator=(const EBTerm & term)
391  {
392  delete _root;
393  _root = term.cloneRoot();
394  return *this;
395  }
396 
397  // perform a substitution (returns substituton count)
398  unsigned int substitute(const EBSubstitutionRule & rule);
399  unsigned int substitute(const EBSubstitutionRuleList & rules);
400 
401  const EBTermNode * getRoot() const { return _root; }
402  EBTermNode * cloneRoot() const { return _root == NULL ? NULL : _root->clone(); }
403 
404  protected:
406 
407  public:
411 #define UNARY_OP_IMPLEMENT(op, OP) \
412  EBTerm operator op() const \
413  { \
414  mooseAssert(_root != NULL, "Empty term provided for unary operator " #op); \
415  return EBTerm(new EBUnaryOpTermNode(cloneRoot(), EBUnaryOpTermNode::OP)); \
416  }
417  UNARY_OP_IMPLEMENT(-, NEG)
418  UNARY_OP_IMPLEMENT(!, LOGICNOT)
419 
423  friend EBTerm sin(const EBTerm &);
424  friend EBTerm cos(const EBTerm &);
425  friend EBTerm tan(const EBTerm &);
426  friend EBTerm abs(const EBTerm &);
427  friend EBTerm log(const EBTerm &);
428  friend EBTerm log2(const EBTerm &);
429  friend EBTerm log10(const EBTerm &);
430  friend EBTerm exp(const EBTerm &);
431  friend EBTerm sinh(const EBTerm &);
432  friend EBTerm cosh(const EBTerm &);
433 
434 /*
435  * Binary operators (including number,term operations)
436  */
437 #define BINARY_OP_IMPLEMENT(op, OP) \
438  EBTerm operator op(const EBTerm & term) const \
439  { \
440  mooseAssert(_root != NULL, "Empty term provided on left side of operator " #op); \
441  mooseAssert(term._root != NULL, "Empty term provided on right side of operator " #op); \
442  return EBTerm(new EBBinaryOpTermNode(cloneRoot(), term.cloneRoot(), EBBinaryOpTermNode::OP)); \
443  } \
444  friend EBTerm operator op(int left, const EBTerm & right) \
445  { \
446  mooseAssert(right._root != NULL, "Empty term provided on right side of operator " #op); \
447  return EBTerm(new EBBinaryOpTermNode( \
448  new EBNumberNode<int>(left), right.cloneRoot(), EBBinaryOpTermNode::OP)); \
449  } \
450  friend EBTerm operator op(Real left, const EBTerm & right) \
451  { \
452  mooseAssert(right._root != NULL, "Empty term provided on right side of operator " #op); \
453  return EBTerm(new EBBinaryOpTermNode( \
454  new EBNumberNode<Real>(left), right.cloneRoot(), EBBinaryOpTermNode::OP)); \
455  } \
456  friend EBTerm operator op(const EBFunction & left, const EBTerm & right) \
457  { \
458  mooseAssert(EBTerm(left)._root != NULL, "Empty term provided on left side of operator " #op); \
459  mooseAssert(right._root != NULL, "Empty term provided on right side of operator " #op); \
460  return EBTerm(new EBBinaryOpTermNode( \
461  EBTerm(left).cloneRoot(), right.cloneRoot(), EBBinaryOpTermNode::OP)); \
462  } \
463  friend EBTerm operator op(const EBFunction & left, const EBFunction & right); \
464  friend EBTerm operator op(int left, const EBFunction & right); \
465  friend EBTerm operator op(Real left, const EBFunction & right);
466  BINARY_OP_IMPLEMENT(+, ADD)
467  BINARY_OP_IMPLEMENT(-, SUB)
468  BINARY_OP_IMPLEMENT(*, MUL)
469  BINARY_OP_IMPLEMENT(/, DIV)
470  BINARY_OP_IMPLEMENT(%, MOD)
471  BINARY_OP_IMPLEMENT(<, LESS)
472  BINARY_OP_IMPLEMENT(>, GREATER)
473  BINARY_OP_IMPLEMENT(<=, LESSEQ)
474  BINARY_OP_IMPLEMENT(>=, GREATEREQ)
475  BINARY_OP_IMPLEMENT(==, EQ)
476  BINARY_OP_IMPLEMENT(!=, NOTEQ)
477 
478 /*
479  * Compound assignment operators
480  */
481 #define BINARYCOMP_OP_IMPLEMENT(op, OP) \
482  EBTerm & operator op(const EBTerm & term) \
483  { \
484  mooseAssert(_root != NULL, "Empty term provided on left side of operator " #op); \
485  mooseAssert(term._root != NULL, "Empty term provided on right side of operator " #op); \
486  if (dynamic_cast<EBTempIDNode *>(_root)) \
487  mooseError("Using compound assignment operator on anonymous term. Set it to 0 first!"); \
488  _root = new EBBinaryOpTermNode(_root, term.cloneRoot(), EBBinaryOpTermNode::OP); \
489  return *this; \
490  }
491  BINARYCOMP_OP_IMPLEMENT(+=, ADD)
492  BINARYCOMP_OP_IMPLEMENT(-=, SUB)
493  BINARYCOMP_OP_IMPLEMENT(*=, MUL)
494  BINARYCOMP_OP_IMPLEMENT(/=, DIV)
495  BINARYCOMP_OP_IMPLEMENT(%=, MOD)
496 
501  friend EBTerm min(const EBTerm &, const EBTerm &);
502  friend EBTerm max(const EBTerm &, const EBTerm &);
503  friend EBTerm pow(const EBTerm &, const EBTerm &);
504  template <typename T>
505  friend EBTerm pow(const EBTerm &, T exponent);
506  friend EBTerm atan2(const EBTerm &, const EBTerm &);
507  friend EBTerm hypot(const EBTerm &, const EBTerm &);
508  friend EBTerm plog(const EBTerm &, const EBTerm &);
510 
514  friend EBTerm conditional(const EBTerm &, const EBTerm &, const EBTerm &);
515  };
516 
519  {
520  public:
522 
526  EBFunction & operator()(const EBTerm & arg);
527  EBFunction & operator()(const EBTermList & args);
529 
532  EBFunction & operator()(const EBTerm & a1, const EBTerm & a2) { return (*this)((a1, a2)); }
533  EBFunction & operator()(const EBTerm & a1, const EBTerm & a2, const EBTerm & a3)
534  {
535  return (*this)((a1, a2, a3));
536  }
537  EBFunction &
538  operator()(const EBTerm & a1, const EBTerm & a2, const EBTerm & a3, const EBTerm & a4)
539  {
540  return (*this)((a1, a2, a3, a4));
541  }
542  EBFunction & operator()(const EBTerm & a1,
543  const EBTerm & a2,
544  const EBTerm & a3,
545  const EBTerm & a4,
546  const EBTerm & a5)
547  {
548  return (*this)((a1, a2, a3, a4, a5));
549  }
550  EBFunction & operator()(const EBTerm & a1,
551  const EBTerm & a2,
552  const EBTerm & a3,
553  const EBTerm & a4,
554  const EBTerm & a5,
555  const EBTerm & a6)
556  {
557  return (*this)((a1, a2, a3, a4, a5, a6));
558  }
559  EBFunction & operator()(const EBTerm & a1,
560  const EBTerm & a2,
561  const EBTerm & a3,
562  const EBTerm & a4,
563  const EBTerm & a5,
564  const EBTerm & a6,
565  const EBTerm & a7)
566  {
567  return (*this)((a1, a2, a3, a4, a5, a6, a7));
568  }
569  EBFunction & operator()(const EBTerm & a1,
570  const EBTerm & a2,
571  const EBTerm & a3,
572  const EBTerm & a4,
573  const EBTerm & a5,
574  const EBTerm & a6,
575  const EBTerm & a7,
576  const EBTerm & a8)
577  {
578  return (*this)((a1, a2, a3, a4, a5, a6, a7, a8));
579  }
580  EBFunction & operator()(const EBTerm & a1,
581  const EBTerm & a2,
582  const EBTerm & a3,
583  const EBTerm & a4,
584  const EBTerm & a5,
585  const EBTerm & a6,
586  const EBTerm & a7,
587  const EBTerm & a8,
588  const EBTerm & a9)
589  {
590  return (*this)((a1, a2, a3, a4, a5, a6, a7, a8, a9));
591  }
593 
595  operator EBTerm() const;
596 
598  operator std::string() const;
599 
602  EBFunction & operator=(const EBTerm &);
603  EBFunction & operator=(const EBFunction &);
605 
607  std::string args();
608 
611  EBTerm operator-() { return -EBTerm(*this); }
612  EBTerm operator!() { return !EBTerm(*this); }
614 
615  // perform a substitution (returns substituton count)
616  unsigned int substitute(const EBSubstitutionRule & rule);
617  unsigned int substitute(const EBSubstitutionRuleList & rules);
618 
619  protected:
621  EBTermList _arguments;
623  EBTermList _eval_arguments;
624 
625  // underlying term that the _eval_arguments are substituted in
626  EBTerm _term;
627  };
628 
629 /*
630  * Binary operators
631  */
632 #define BINARYFUNC_OP_IMPLEMENT(op, OP) \
633  friend EBTerm operator op(const EBFunction & left, const EBFunction & right) \
634  { \
635  mooseAssert(EBTerm(left)._root != NULL, "Empty term provided on left side of operator " #op); \
636  mooseAssert(EBTerm(right)._root != NULL, \
637  "Empty term provided on right side of operator " #op); \
638  return EBTerm(new EBBinaryOpTermNode( \
639  EBTerm(left).cloneRoot(), EBTerm(right).cloneRoot(), EBBinaryOpTermNode::OP)); \
640  } \
641  friend EBTerm operator op(int left, const EBFunction & right) \
642  { \
643  mooseAssert(EBTerm(right)._root != NULL, \
644  "Empty term provided on right side of operator " #op); \
645  return EBTerm(new EBBinaryOpTermNode( \
646  new EBNumberNode<int>(left), EBTerm(right).cloneRoot(), EBBinaryOpTermNode::OP)); \
647  } \
648  friend EBTerm operator op(Real left, const EBFunction & right) \
649  { \
650  mooseAssert(EBTerm(right)._root != NULL, \
651  "Empty term provided on right side of operator " #op); \
652  return EBTerm(new EBBinaryOpTermNode( \
653  new EBNumberNode<Real>(left), EBTerm(right).cloneRoot(), EBBinaryOpTermNode::OP)); \
654  }
655  BINARYFUNC_OP_IMPLEMENT(+, ADD)
656  BINARYFUNC_OP_IMPLEMENT(-, SUB)
657  BINARYFUNC_OP_IMPLEMENT(*, MUL)
658  BINARYFUNC_OP_IMPLEMENT(/, DIV)
659  BINARYFUNC_OP_IMPLEMENT(%, MOD)
660  BINARYFUNC_OP_IMPLEMENT(<, LESS)
661  BINARYFUNC_OP_IMPLEMENT(>, GREATER)
662  BINARYFUNC_OP_IMPLEMENT(<=, LESSEQ)
663  BINARYFUNC_OP_IMPLEMENT(>=, GREATEREQ)
664  BINARYFUNC_OP_IMPLEMENT(==, EQ)
665  BINARYFUNC_OP_IMPLEMENT(!=, NOTEQ)
666 };
667 
668 // convenience function for numeric exponent
669 template <typename T>
670 ExpressionBuilder::EBTerm
671 pow(const ExpressionBuilder::EBTerm & left, T exponent)
672 {
674  new ExpressionBuilder::EBBinaryOpTermNode(left.cloneRoot(),
677 }
678 
679 // convert a number node into a string
680 template <typename T>
681 std::string
683 {
684  std::ostringstream s;
685  s << std::setprecision(12) << _value;
686  return s.str();
687 }
688 
689 template <class Node_T>
692  const ExpressionBuilder::EBTermNode * node) const
693 {
694  const Node_T * match_node = dynamic_cast<const Node_T *>(node);
695  if (match_node == NULL)
696  return NULL;
697  else
698  return substitute(*match_node);
699 }
700 
701 #endif // EXPRESSIONBUILDER_H
Node representing a function with three arguments.
User facing host object for an expression tree.
Base class for nodes with two sub nodes (i.e. functions or operators taking two arguments) ...
std::ostream & operator<<(std::ostream &out, const FeatureFloodCount::FeatureData &feature)
EBFunction & operator()(const EBTerm &a1, const EBTerm &a2, const EBTerm &a3, const EBTerm &a4, const EBTerm &a5, const EBTerm &a6)
Node representing a unary operator.
EBFunction & operator()(const EBTerm &a1, const EBTerm &a2, const EBTerm &a3, const EBTerm &a4)
virtual EBBinaryFuncTermNode * clone() const
Template class for leaf nodes holding anonymous IDs in the expression tree.
const EBTermNode * getSubnode() const
virtual EBUnaryOpTermNode * clone() const
Node representing a binary operator.
ExpressionBuilder::EBTermList operator,(const ExpressionBuilder::EBTerm &larg, const ExpressionBuilder::EBTerm &rarg)
Base class for nodes with a single sub node (i.e. functions or operators taking one argument) ...
virtual std::string stringify() const =0
EBTermList _eval_arguments
argument list passed in when evaluating the function
Node representing a function with two arguments.
EBFunction & operator()(const EBTerm &a1, const EBTerm &a2, const EBTerm &a3, const EBTerm &a4, const EBTerm &a5, const EBTerm &a6, const EBTerm &a7, const EBTerm &a8, const EBTerm &a9)
std::vector< EBTerm > EBTermList
ExpressionBuilder adds an interface to derived classes that enables convenient construction of FParse...
virtual EBTermNode * clone() const =0
EBFunction & operator()(const EBTerm &a1, const EBTerm &a2, const EBTerm &a3)
virtual EBTermNode * apply(const EBTermNode *) const
Substitution rule base class that applies to nodes of type Node_T.
EBBinaryTermNode(EBTermNode *left, EBTermNode *right)
Base class for nodes in the expression tree.
EBTermNode * cloneRoot() const
virtual EBNumberNode< T > * clone() const
friend std::ostream & operator<<(std::ostream &os, const EBTermNode &node)
Template class for leaf nodes holding symbols (i.e. variables) in the expression tree.
Template class for leaf nodes holding numbers in the expression tree.
virtual unsigned int substitute(const EBSubstitutionRuleList &)
Node representing a function with two arguments.
EBUnaryOpTermNode(EBTermNode *subnode, NodeType type)
EBUnaryFuncTermNode(EBTermNode *subnode, NodeType type)
Real root(std::function< Real(Real)> const &f, Real x1, Real x2, Real tol=1.0e-12)
Finds the root of a function using Brent&#39;s method.
Definition: BrentsMethod.C:58
virtual EBTernaryFuncTermNode * clone() const
virtual EBUnaryFuncTermNode * clone() const
virtual EBSymbolNode * clone() const
EBFunction & operator()(const EBTerm &a1, const EBTerm &a2)
const EBTermNode * getRoot() const
std::vector< const EBSubstitutionRule * > EBSubstitutionRuleList
ExpressionBuilder::EBTerm pow(const ExpressionBuilder::EBTerm &left, T exponent)
Substitution rule to replace all occurences of log(x) with plog(x, epsilon) with a user defined term ...
virtual EBTempIDNode * clone() const
EBFunction & operator()(const EBTerm &a1, const EBTerm &a2, const EBTerm &a3, const EBTerm &a4, const EBTerm &a5, const EBTerm &a6, const EBTerm &a7, const EBTerm &a8)
std::vector< EBTermNode * > EBTermNodeList
User facing host object for a function. This combines a term with an argument list.
EBTerm(const char *symbol)
EBTernaryFuncTermNode(EBTermNode *left, EBTermNode *middle, EBTermNode *right, NodeType type)
EBTermList _arguments
argument list the function is declared with
EBTernaryTermNode(EBTermNode *left, EBTermNode *middle, EBTermNode *right)
virtual std::string stringify() const
Generic Substitution rule to replace all occurences of a given symbol node term with a user defined t...
EBFunction & operator()(const EBTerm &a1, const EBTerm &a2, const EBTerm &a3, const EBTerm &a4, const EBTerm &a5)
EBTerm(const EBTerm &term)
Substitution rule functor base class to perform flexible term substitutions.
EBBinaryFuncTermNode(EBTermNode *left, EBTermNode *right, NodeType type)
EBFunction & operator()(const EBTerm &a1, const EBTerm &a2, const EBTerm &a3, const EBTerm &a4, const EBTerm &a5, const EBTerm &a6, const EBTerm &a7)
virtual EBBinaryOpTermNode * clone() const
EBBinaryOpTermNode(EBTermNode *left, EBTermNode *right, NodeType type)
Base class for nodes with two sub nodes (i.e. functions or operators taking two arguments) ...
EBTerm & operator=(const EBTerm &term)