]> git.mxchange.org Git - simgear.git/blobdiff - simgear/structure/SGExpression.cxx
Fix state-machine test linkage with static libs.
[simgear.git] / simgear / structure / SGExpression.cxx
index 5a04c509ced1bdf404ffd9c50108d700f3b9b1a6..df0aa9d747d13b6a0e26d61a9a69f6459b17dd19 100644 (file)
 #endif
 
 #include "SGExpression.hxx"
+#include "Singleton.hxx"
 
+#include <algorithm>
+#include <map>
+#include <utility>
 #include <string>
 #include <sstream>
+#include <boost/bind.hpp>
+#include <cstring> // for strcmp
+
 #include <simgear/props/props.hxx>
 
+using namespace std;
+
+namespace simgear
+{
+template<typename T>
+const expression::Value evalValue(const Expression* exp,
+                                  const expression::Binding* b)
+{
+    T val;
+    static_cast<const SGExpression<T>*>(exp)->eval(val, b);
+    return expression::Value(val);
+}
+
+const expression::Value eval(const Expression* exp,
+                             const expression::Binding* b)
+{
+    using namespace expression;
+    switch (exp->getType()) {
+    case BOOL:
+        return evalValue<bool>(exp, b);
+    case INT:
+        return evalValue<int>(exp, b);
+    case FLOAT:
+        return evalValue<float>(exp, b);
+    case DOUBLE:
+        return evalValue<double>(exp, b);
+    default:
+        throw "invalid type.";
+    }
+}
+}
+
 template<typename T>
 static bool
 SGReadValueFromString(const char* str, T& value)
 {
-  if (!str) {
-    SG_LOG(SG_IO, SG_ALERT, "Cannot read string content.");
-    return false;
-  }
-  std::stringstream s;
-  s.str(std::string(str));
-  s >> value;
-  if (s.fail()) {
-    SG_LOG(SG_IO, SG_ALERT, "Cannot read string content.");
-    return false;
-  }
-  return true;
+    if (!str) {
+        SG_LOG(SG_IO, SG_ALERT, "Cannot read string content.");
+        return false;
+    }
+    std::stringstream s;
+    s.str(std::string(str));
+    s >> value;
+    if (s.fail()) {
+        SG_LOG(SG_IO, SG_ALERT, "Cannot read string content.");
+        return false;
+    }
+    return true;
 }
 
 template<>
-static bool
+bool
 SGReadValueFromString(const char* str, bool& value)
 {
-  if (!str) {
-    SG_LOG(SG_IO, SG_ALERT, "Cannot read string content.");
-    return false;
-  }
-  std::stringstream s;
-  s.str(std::string(str));
-  s >> value;
-  if (!s.fail())
-    return true;
+    if (!str) {
+        SG_LOG(SG_IO, SG_ALERT, "Cannot read string content.");
+        return false;
+    }
+    std::stringstream s;
+    s.str(std::string(str));
+    s >> value;
+    if (!s.fail())
+        return true;
 
-  std::string stdstr;
-  if (!SGReadValueFromString(str, stdstr))
-    return false;
+    std::string stdstr;
+    if (!SGReadValueFromString(str, stdstr))
+        return false;
 
-  if (stdstr == "true" || stdstr == "True" || stdstr == "TRUE") {
-    value = true;
-    return true;
-  }
-  if (stdstr == "false" || stdstr == "False" || stdstr == "FALSE") {
-    value = true;
-    return true;
-  }
-  return false;
+    if (stdstr == "true" || stdstr == "True" || stdstr == "TRUE") {
+        value = true;
+        return true;
+    }
+    if (stdstr == "false" || stdstr == "False" || stdstr == "FALSE") {
+        value = true;
+        return true;
+    }
+    return false;
 }
 
 template<typename T>
 static bool
 SGReadValueFromContent(const SGPropertyNode *node, T& value)
 {
-  if (!node)
-    return false;
-  return SGReadValueFromString(node->getStringValue(), value);
+    if (!node)
+        return false;
+    return SGReadValueFromString(node->getStringValue(), value);
 }
 
 template<typename T>
 static SGExpression<T>*
-SGReadIExpression(SGPropertyNode *inputRoot, const SGPropertyNode *expression);
+SGReadExpression(SGPropertyNode *inputRoot, const SGPropertyNode *expression);
 
 template<typename T>
 static bool
 SGReadNaryOperands(SGNaryExpression<T>* nary,
                    SGPropertyNode *inputRoot, const SGPropertyNode *expression)
 {
-  for (int i = 0; i < expression->nChildren(); ++i) {
-    SGExpression<T>* inputExpression;
-    inputExpression = SGReadIExpression<T>(inputRoot, expression->getChild(i));
-    if (!inputExpression)
-      return false;
-    nary->addOperand(inputExpression);
-  }
-  return true;
+    for (int i = 0; i < expression->nChildren(); ++i) {
+        SGExpression<T>* inputExpression;
+        inputExpression = SGReadExpression<T>(inputRoot, expression->getChild(i));
+        if (!inputExpression)
+            return false;
+        nary->addOperand(inputExpression);
+    }
+    return true;
 }
 
 // template<typename T>
@@ -126,514 +165,733 @@ SGReadNaryOperands(SGNaryExpression<T>* nary,
 
 template<typename T>
 static SGExpression<T>*
-SGReadIExpression(SGPropertyNode *inputRoot, const SGPropertyNode *expression)
-{
-  if (!expression)
-    return 0;
-
-  std::string name = expression->getName();
-  if (name == "value") {
-    T value;
-    if (!SGReadValueFromContent(expression, value)) {
-      SG_LOG(SG_IO, SG_ALERT, "Cannot read \"value\" expression.");
-      return 0;
-    }
-    return new SGConstExpression<T>(value);
-  }
-
-  if (name == "property") {
-    if (!inputRoot) {
-      SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.\n"
-             "No inputRoot argument given!");
-      return 0;
-    }
-    if (!expression->getStringValue()) {
-      SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
-      return 0;
-    }
-    SGPropertyNode* inputNode;
-    inputNode = inputRoot->getNode(expression->getStringValue(), true);
-    return new SGPropertyExpression<T>(inputNode);
-  }
-
-  if (name == "abs" || name == "fabs") {
-    if (expression->nChildren() != 1) {
-      SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
-      return 0;
-    }
-    SGSharedPtr<SGExpression<T> > inputExpression;
-    inputExpression = SGReadIExpression<T>(inputRoot, expression->getChild(0));
-    if (!inputExpression) {
-      SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
-      return 0;
-    }
-    return new SGAbsExpression<T>(inputExpression);
-  }
-
-  if (name == "sqr") {
-    if (expression->nChildren() != 1) {
-      SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
-      return 0;
-    }
-    SGSharedPtr<SGExpression<T> > inputExpression;
-    inputExpression = SGReadIExpression<T>(inputRoot, expression->getChild(0));
-    if (!inputExpression) {
-      SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
-      return 0;
-    }
-    return new SGSqrExpression<T>(inputExpression);
-  }
-
-  if (name == "clip") {
-    if (expression->nChildren() != 3) {
-      SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
-      return 0;
-    }
-    const SGPropertyNode* minProperty = expression->getChild("clipMin");
-    T clipMin;
-    if (!SGReadValueFromContent(minProperty, clipMin))
-      clipMin = SGMisc<T>::min(SGLimits<T>::min(), -SGLimits<T>::max());
-
-    const SGPropertyNode* maxProperty = expression->getChild("clipMax");
-    T clipMax;
-    if (!SGReadValueFromContent(maxProperty, clipMax))
-      clipMin = SGLimits<T>::max();
-
-    SGSharedPtr<SGExpression<T> > inputExpression;
-    for (int i = 0; !inputExpression && i < expression->nChildren(); ++i)
-      inputExpression = SGReadIExpression<T>(inputRoot, expression->getChild(i));
-    if (!inputExpression) {
-      SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
-      return 0;
-    }
-    return new SGClipExpression<T>(inputExpression, clipMin, clipMax);
-  }
-
-  if (name == "div") {
-    if (expression->nChildren() != 2) {
-      SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
-      return 0;
-    }
-    SGSharedPtr<SGExpression<T> > inputExpressions[2] = {
-      SGReadIExpression<T>(inputRoot, expression->getChild(0)),
-      SGReadIExpression<T>(inputRoot, expression->getChild(1))
-    };
-    if (!inputExpressions[0] || !inputExpressions[1]) {
-      SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
-      return 0;
-    }
-    return new SGDivExpression<T>(inputExpressions[0], inputExpressions[1]);
-  }
-  if (name == "mod") {
-    if (expression->nChildren() != 2) {
-      SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
-      return 0;
-    }
-    SGSharedPtr<SGExpression<T> > inputExpressions[2] = {
-      SGReadIExpression<T>(inputRoot, expression->getChild(0)),
-      SGReadIExpression<T>(inputRoot, expression->getChild(1))
-    };
-    if (!inputExpressions[0] || !inputExpressions[1]) {
-      SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
-      return 0;
-    }
-    return new SGModExpression<T>(inputExpressions[0], inputExpressions[1]);
-  }
-
-  if (name == "sum") {
-    if (expression->nChildren() < 1) {
-      SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
-      return 0;
-    }
-    SGSumExpression<T>* output = new SGSumExpression<T>;
-    if (!SGReadNaryOperands(output, inputRoot, expression)) {
-      delete output;
-      SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
-      return 0;
-    }
-    return output;
-  }
-  if (name == "prod" || name == "product") {
-    if (expression->nChildren() < 1) {
-      SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
-      return 0;
-    }
-    SGProductExpression<T>* output = new SGProductExpression<T>;
-    if (!SGReadNaryOperands(output, inputRoot, expression)) {
-      delete output;
-      SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
-      return 0;
-    }
-    return output;
-  }
-  if (name == "min") {
-    if (expression->nChildren() < 1) {
-      SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
-      return 0;
-    }
-    SGMinExpression<T>* output = new SGMinExpression<T>;
-    if (!SGReadNaryOperands(output, inputRoot, expression)) {
-      delete output;
-      SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
-      return 0;
-    }
-    return output;
-  }
-  if (name == "max") {
-    if (expression->nChildren() < 1) {
-      SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
-      return 0;
-    }
-    SGMaxExpression<T>* output = new SGMaxExpression<T>;
-    if (!SGReadNaryOperands(output, inputRoot, expression)) {
-      delete output;
-      SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
-      return 0;
-    }
-    return output;
-  }
-
-  return 0;
-}
-
-
-template<typename T>
-static SGExpression<T>*
-SGReadFExpression(SGPropertyNode *inputRoot, const SGPropertyNode *expression)
+SGReadExpression(SGPropertyNode *inputRoot, const SGPropertyNode *expression)
 {
-  SGExpression<T>* r = SGReadIExpression<T>(inputRoot, expression);
-  if (r)
-    return r;
-
-  if (!expression)
-    return 0;
-
-  std::string name = expression->getName();
-  if (name == "acos") {
-    if (expression->nChildren() != 1) {
-      SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
-      return 0;
-    }
-    SGSharedPtr<SGExpression<T> > inputExpression;
-    inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
-    if (!inputExpression) {
-      SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
-      return 0;
-    }
-    return new SGACosExpression<T>(inputExpression);
-  }
-
-  if (name == "asin") {
-    if (expression->nChildren() != 1) {
-      SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
-      return 0;
-    }
-    SGSharedPtr<SGExpression<T> > inputExpression;
-    inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
-    if (!inputExpression) {
-      SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
-      return 0;
-    }
-    return new SGASinExpression<T>(inputExpression);
-  }
-
-  if (name == "atan") {
-    if (expression->nChildren() != 1) {
-      SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
-      return 0;
-    }
-    SGSharedPtr<SGExpression<T> > inputExpression;
-    inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
-    if (!inputExpression) {
-      SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
-      return 0;
-    }
-    return new SGATanExpression<T>(inputExpression);
-  }
-
-  if (name == "ceil") {
-    if (expression->nChildren() != 1) {
-      SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
-      return 0;
-    }
-    SGSharedPtr<SGExpression<T> > inputExpression;
-    inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
-    if (!inputExpression) {
-      SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
-      return 0;
-    }
-    return new SGCeilExpression<T>(inputExpression);
-  }
-
-  if (name == "cos") {
-    if (expression->nChildren() != 1) {
-      SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
-      return 0;
-    }
-    SGSharedPtr<SGExpression<T> > inputExpression;
-    inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
-    if (!inputExpression) {
-      SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
-      return 0;
-    }
-    return new SGCosExpression<T>(inputExpression);
-  }
-
-  if (name == "cosh") {
-    if (expression->nChildren() != 1) {
-      SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
-      return 0;
-    }
-    SGSharedPtr<SGExpression<T> > inputExpression;
-    inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
-    if (!inputExpression) {
-      SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
-      return 0;
-    }
-    return new SGCoshExpression<T>(inputExpression);
-  }
-
-  if (name == "deg2rad") {
-    if (expression->nChildren() != 1) {
-      SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
-      return 0;
-    }
-    SGSharedPtr<SGExpression<T> > inputExpression;
-    inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
-    if (!inputExpression) {
-      SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
-      return 0;
-    }
-    return new SGScaleExpression<T>(inputExpression, SGMisc<T>::pi()/180);
-  }
-
-  if (name == "exp") {
-    if (expression->nChildren() != 1) {
-      SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
-      return 0;
-    }
-    SGSharedPtr<SGExpression<T> > inputExpression;
-    inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
-    if (!inputExpression) {
-      SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
-      return 0;
-    }
-    return new SGExpExpression<T>(inputExpression);
-  }
-
-  if (name == "floor") {
-    if (expression->nChildren() != 1) {
-      SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
-      return 0;
-    }
-    SGSharedPtr<SGExpression<T> > inputExpression;
-    inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
-    if (!inputExpression) {
-      SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
-      return 0;
-    }
-    return new SGFloorExpression<T>(inputExpression);
-  }
-
-  if (name == "log") {
-    if (expression->nChildren() != 1) {
-      SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
-      return 0;
-    }
-    SGSharedPtr<SGExpression<T> > inputExpression;
-    inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
-    if (!inputExpression) {
-      SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
-      return 0;
-    }
-    return new SGLogExpression<T>(inputExpression);
-  }
-
-  if (name == "log10") {
-    if (expression->nChildren() != 1) {
-      SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
-      return 0;
-    }
-    SGSharedPtr<SGExpression<T> > inputExpression;
-    inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
-    if (!inputExpression) {
-      SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
-      return 0;
-    }
-    return new SGLog10Expression<T>(inputExpression);
-  }
-
-  if (name == "rad2deg") {
-    if (expression->nChildren() != 1) {
-      SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
-      return 0;
-    }
-    SGSharedPtr<SGExpression<T> > inputExpression;
-    inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
-    if (!inputExpression) {
-      SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
-      return 0;
-    }
-    return new SGScaleExpression<T>(inputExpression, 180/SGMisc<T>::pi());
-  }
-
-  if (name == "sin") {
-    if (expression->nChildren() != 1) {
-      SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
-      return 0;
-    }
-    SGSharedPtr<SGExpression<T> > inputExpression;
-    inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
-    if (!inputExpression) {
-      SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
-      return 0;
-    }
-    return new SGSinExpression<T>(inputExpression);
-  }
-
-  if (name == "sinh") {
-    if (expression->nChildren() != 1) {
-      SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
-      return 0;
-    }
-    SGSharedPtr<SGExpression<T> > inputExpression;
-    inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
-    if (!inputExpression) {
-      SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
-      return 0;
-    }
-    return new SGSinhExpression<T>(inputExpression);
-  }
-
-  if (name == "sqrt") {
-    if (expression->nChildren() != 1) {
-      SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
-      return 0;
-    }
-    SGSharedPtr<SGExpression<T> > inputExpression;
-    inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
-    if (!inputExpression) {
-      SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
-      return 0;
-    }
-    return new SGSqrtExpression<T>(inputExpression);
-  }
-
-  if (name == "tan") {
-    if (expression->nChildren() != 1) {
-      SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
-      return 0;
-    }
-    SGSharedPtr<SGExpression<T> > inputExpression;
-    inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
-    if (!inputExpression) {
-      SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
-      return 0;
-    }
-    return new SGTanExpression<T>(inputExpression);
-  }
-
-  if (name == "tanh") {
-    if (expression->nChildren() != 1) {
-      SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
-      return 0;
-    }
-    SGSharedPtr<SGExpression<T> > inputExpression;
-    inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
-    if (!inputExpression) {
-      SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
-      return 0;
-    }
-    return new SGTanhExpression<T>(inputExpression);
-  }
-
-// if (name == "table") {
-// }
+    if (!expression)
+        return 0;
+
+    std::string name = expression->getName();
+
+    if (name == "value") {
+        T value;
+        if (!SGReadValueFromContent(expression, value)) {
+            SG_LOG(SG_IO, SG_ALERT, "Cannot read \"value\" expression.");
+            return 0;
+        }
+        return new SGConstExpression<T>(value);
+    }
+
+    if (name == "property") {
+        if (!inputRoot) {
+            SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.\n"
+                   "No inputRoot argument given!");
+            return 0;
+        }
+        if (!expression->getStringValue()) {
+            SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
+            return 0;
+        }
+        SGPropertyNode* inputNode;
+        inputNode = inputRoot->getNode(expression->getStringValue(), true);
+        return new SGPropertyExpression<T>(inputNode);
+    }
+
+    if (name == "abs" || name == "fabs") {
+        if (expression->nChildren() != 1) {
+            SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
+            return 0;
+        }
+        SGSharedPtr<SGExpression<T> > inputExpression;
+        inputExpression = SGReadExpression<T>(inputRoot, expression->getChild(0));
+        if (!inputExpression) {
+            SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
+            return 0;
+        }
+        return new SGAbsExpression<T>(inputExpression);
+    }
+
+    if (name == "sqr") {
+        if (expression->nChildren() != 1) {
+            SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
+            return 0;
+        }
+        SGSharedPtr<SGExpression<T> > inputExpression;
+        inputExpression = SGReadExpression<T>(inputRoot, expression->getChild(0));
+        if (!inputExpression) {
+            SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
+            return 0;
+        }
+        return new SGSqrExpression<T>(inputExpression);
+    }
+
+    if (name == "clip") {
+        if (expression->nChildren() != 3) {
+            SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
+            return 0;
+        }
+        const SGPropertyNode* minProperty = expression->getChild("clipMin");
+        T clipMin;
+        if (!SGReadValueFromContent(minProperty, clipMin))
+            clipMin = SGMisc<T>::min(SGLimits<T>::min(), -SGLimits<T>::max());
+
+        const SGPropertyNode* maxProperty = expression->getChild("clipMax");
+        T clipMax;
+        if (!SGReadValueFromContent(maxProperty, clipMax))
+            clipMin = SGLimits<T>::max();
+
+        SGSharedPtr<SGExpression<T> > inputExpression;
+        for (int i = 0; !inputExpression && i < expression->nChildren(); ++i)
+            inputExpression = SGReadExpression<T>(inputRoot, expression->getChild(i));
+        if (!inputExpression) {
+            SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
+            return 0;
+        }
+        return new SGClipExpression<T>(inputExpression, clipMin, clipMax);
+    }
+
+    if (name == "div") {
+        if (expression->nChildren() != 2) {
+            SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
+            return 0;
+        }
+        SGSharedPtr<SGExpression<T> > inputExpressions[2] = {
+            SGReadExpression<T>(inputRoot, expression->getChild(0)),
+            SGReadExpression<T>(inputRoot, expression->getChild(1))
+        };
+        if (!inputExpressions[0] || !inputExpressions[1]) {
+            SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
+            return 0;
+        }
+        return new SGDivExpression<T>(inputExpressions[0], inputExpressions[1]);
+    }
+    if (name == "mod") {
+        if (expression->nChildren() != 2) {
+            SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
+            return 0;
+        }
+        SGSharedPtr<SGExpression<T> > inputExpressions[2] = {
+            SGReadExpression<T>(inputRoot, expression->getChild(0)),
+            SGReadExpression<T>(inputRoot, expression->getChild(1))
+        };
+        if (!inputExpressions[0] || !inputExpressions[1]) {
+            SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
+            return 0;
+        }
+        return new SGModExpression<T>(inputExpressions[0], inputExpressions[1]);
+    }
+
+    if (name == "sum") {
+        if (expression->nChildren() < 1) {
+            SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
+            return 0;
+        }
+        SGSumExpression<T>* output = new SGSumExpression<T>;
+        if (!SGReadNaryOperands(output, inputRoot, expression)) {
+            delete output;
+            SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
+            return 0;
+        }
+        return output;
+    }
+
+    if (name == "difference" || name == "dif" ) {
+        if (expression->nChildren() < 1) {
+            SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
+            return 0;
+        }
+        SGDifferenceExpression<T>* output = new SGDifferenceExpression<T>;
+        if (!SGReadNaryOperands(output, inputRoot, expression)) {
+            delete output;
+            SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
+            return 0;
+        }
+        return output;
+    }
+
+    if (name == "prod" || name == "product") {
+        if (expression->nChildren() < 1) {
+            SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
+            return 0;
+        }
+        SGProductExpression<T>* output = new SGProductExpression<T>;
+        if (!SGReadNaryOperands(output, inputRoot, expression)) {
+            delete output;
+            SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
+            return 0;
+        }
+        return output;
+    }
+    if (name == "min") {
+        if (expression->nChildren() < 1) {
+            SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
+            return 0;
+        }
+        SGMinExpression<T>* output = new SGMinExpression<T>;
+        if (!SGReadNaryOperands(output, inputRoot, expression)) {
+            delete output;
+            SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
+            return 0;
+        }
+        return output;
+    }
+    if (name == "max") {
+        if (expression->nChildren() < 1) {
+            SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
+            return 0;
+        }
+        SGMaxExpression<T>* output = new SGMaxExpression<T>;
+        if (!SGReadNaryOperands(output, inputRoot, expression)) {
+            delete output;
+            SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
+            return 0;
+        }
+        return output;
+    }
+
+    if (name == "table") {
+        SGInterpTable* tab = new SGInterpTable(expression);
+        if (!tab) {
+            SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression: malformed table");
+            return 0;
+        }
+        
+        // find input expression - i.e a child not named 'entry'
+        const SGPropertyNode* inputNode = NULL;
+        for (int i=0; (i<expression->nChildren()) && !inputNode; ++i) {
+            if (strcmp(expression->getChild(i)->getName(), "entry") == 0) {
+                continue;
+            }
+            
+            inputNode = expression->getChild(i);
+        }
+        
+        if (!inputNode) {
+            SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression: no input found");
+            return 0;
+        }
+        
+        SGSharedPtr<SGExpression<T> > inputExpression;
+        inputExpression = SGReadExpression<T>(inputRoot, inputNode);
+        if (!inputExpression) {
+            SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
+            return 0;
+        }
+        
+        return new SGInterpTableExpression<T>(inputExpression, tab);
+    }
+    
+    if (name == "acos") {
+        if (expression->nChildren() != 1) {
+            SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
+            return 0;
+        }
+        SGSharedPtr<SGExpression<T> > inputExpression;
+        inputExpression = SGReadExpression<T>(inputRoot, expression->getChild(0));
+        if (!inputExpression) {
+            SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
+            return 0;
+        }
+        return new SGACosExpression<T>(inputExpression);
+    }
+
+    if (name == "asin") {
+        if (expression->nChildren() != 1) {
+            SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
+            return 0;
+        }
+        SGSharedPtr<SGExpression<T> > inputExpression;
+        inputExpression = SGReadExpression<T>(inputRoot, expression->getChild(0));
+        if (!inputExpression) {
+            SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
+            return 0;
+        }
+        return new SGASinExpression<T>(inputExpression);
+    }
+
+    if (name == "atan") {
+        if (expression->nChildren() != 1) {
+            SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
+            return 0;
+        }
+        SGSharedPtr<SGExpression<T> > inputExpression;
+        inputExpression = SGReadExpression<T>(inputRoot, expression->getChild(0));
+        if (!inputExpression) {
+            SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
+            return 0;
+        }
+        return new SGATanExpression<T>(inputExpression);
+    }
+
+    if (name == "ceil") {
+        if (expression->nChildren() != 1) {
+            SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
+            return 0;
+        }
+        SGSharedPtr<SGExpression<T> > inputExpression;
+        inputExpression = SGReadExpression<T>(inputRoot, expression->getChild(0));
+        if (!inputExpression) {
+            SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
+            return 0;
+        }
+        return new SGCeilExpression<T>(inputExpression);
+    }
+
+    if (name == "cos") {
+        if (expression->nChildren() != 1) {
+            SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
+            return 0;
+        }
+        SGSharedPtr<SGExpression<T> > inputExpression;
+        inputExpression = SGReadExpression<T>(inputRoot, expression->getChild(0));
+        if (!inputExpression) {
+            SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
+            return 0;
+        }
+        return new SGCosExpression<T>(inputExpression);
+    }
+
+    if (name == "cosh") {
+        if (expression->nChildren() != 1) {
+            SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
+            return 0;
+        }
+        SGSharedPtr<SGExpression<T> > inputExpression;
+        inputExpression = SGReadExpression<T>(inputRoot, expression->getChild(0));
+        if (!inputExpression) {
+            SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
+            return 0;
+        }
+        return new SGCoshExpression<T>(inputExpression);
+    }
+
+    if (name == "deg2rad") {
+        if (expression->nChildren() != 1) {
+            SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
+            return 0;
+        }
+        SGSharedPtr<SGExpression<T> > inputExpression;
+        inputExpression = SGReadExpression<T>(inputRoot, expression->getChild(0));
+        if (!inputExpression) {
+            SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
+            return 0;
+        }
+        return new SGScaleExpression<T>(inputExpression, SGMisc<T>::pi()/180);
+    }
+
+    if (name == "exp") {
+        if (expression->nChildren() != 1) {
+            SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
+            return 0;
+        }
+        SGSharedPtr<SGExpression<T> > inputExpression;
+        inputExpression = SGReadExpression<T>(inputRoot, expression->getChild(0));
+        if (!inputExpression) {
+            SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
+            return 0;
+        }
+        return new SGExpExpression<T>(inputExpression);
+    }
+
+    if (name == "floor") {
+        if (expression->nChildren() != 1) {
+            SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
+            return 0;
+        }
+        SGSharedPtr<SGExpression<T> > inputExpression;
+        inputExpression = SGReadExpression<T>(inputRoot, expression->getChild(0));
+        if (!inputExpression) {
+            SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
+            return 0;
+        }
+        return new SGFloorExpression<T>(inputExpression);
+    }
+
+    if (name == "log") {
+        if (expression->nChildren() != 1) {
+            SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
+            return 0;
+        }
+        SGSharedPtr<SGExpression<T> > inputExpression;
+        inputExpression = SGReadExpression<T>(inputRoot, expression->getChild(0));
+        if (!inputExpression) {
+            SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
+            return 0;
+        }
+        return new SGLogExpression<T>(inputExpression);
+    }
+
+    if (name == "log10") {
+        if (expression->nChildren() != 1) {
+            SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
+            return 0;
+        }
+        SGSharedPtr<SGExpression<T> > inputExpression;
+        inputExpression = SGReadExpression<T>(inputRoot, expression->getChild(0));
+        if (!inputExpression) {
+            SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
+            return 0;
+        }
+        return new SGLog10Expression<T>(inputExpression);
+    }
+
+    if (name == "rad2deg") {
+        if (expression->nChildren() != 1) {
+            SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
+            return 0;
+        }
+        SGSharedPtr<SGExpression<T> > inputExpression;
+        inputExpression = SGReadExpression<T>(inputRoot, expression->getChild(0));
+        if (!inputExpression) {
+            SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
+            return 0;
+        }
+        return new SGScaleExpression<T>(inputExpression, 180/SGMisc<T>::pi());
+    }
+
+    if (name == "sin") {
+        if (expression->nChildren() != 1) {
+            SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
+            return 0;
+        }
+        SGSharedPtr<SGExpression<T> > inputExpression;
+        inputExpression = SGReadExpression<T>(inputRoot, expression->getChild(0));
+        if (!inputExpression) {
+            SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
+            return 0;
+        }
+        return new SGSinExpression<T>(inputExpression);
+    }
+
+    if (name == "sinh") {
+        if (expression->nChildren() != 1) {
+            SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
+            return 0;
+        }
+        SGSharedPtr<SGExpression<T> > inputExpression;
+        inputExpression = SGReadExpression<T>(inputRoot, expression->getChild(0));
+        if (!inputExpression) {
+            SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
+            return 0;
+        }
+        return new SGSinhExpression<T>(inputExpression);
+    }
+
+    if (name == "sqrt") {
+        if (expression->nChildren() != 1) {
+            SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
+            return 0;
+        }
+        SGSharedPtr<SGExpression<T> > inputExpression;
+        inputExpression = SGReadExpression<T>(inputRoot, expression->getChild(0));
+        if (!inputExpression) {
+            SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
+            return 0;
+        }
+        return new SGSqrtExpression<T>(inputExpression);
+    }
+
+    if (name == "tan") {
+        if (expression->nChildren() != 1) {
+            SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
+            return 0;
+        }
+        SGSharedPtr<SGExpression<T> > inputExpression;
+        inputExpression = SGReadExpression<T>(inputRoot, expression->getChild(0));
+        if (!inputExpression) {
+            SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
+            return 0;
+        }
+        return new SGTanExpression<T>(inputExpression);
+    }
+
+    if (name == "tanh") {
+        if (expression->nChildren() != 1) {
+            SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
+            return 0;
+        }
+        SGSharedPtr<SGExpression<T> > inputExpression;
+        inputExpression = SGReadExpression<T>(inputRoot, expression->getChild(0));
+        if (!inputExpression) {
+            SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
+            return 0;
+        }
+        return new SGTanhExpression<T>(inputExpression);
+    }
+    
 // if (name == "step") {
 // }
 // if (name == "condition") {
 // }
 
-  if (name == "atan2") {
-    if (expression->nChildren() != 2) {
-      SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
-      return 0;
-    }
-    SGSharedPtr<SGExpression<T> > inputExpressions[2] = {
-      SGReadFExpression<T>(inputRoot, expression->getChild(0)),
-      SGReadFExpression<T>(inputRoot, expression->getChild(1))
-    };
-    if (!inputExpressions[0] || !inputExpressions[1]) {
-      SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
-      return 0;
-    }
-    return new SGAtan2Expression<T>(inputExpressions[0], inputExpressions[1]);
-  }
-  if (name == "div") {
-    if (expression->nChildren() != 2) {
-      SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
-      return 0;
-    }
-    SGSharedPtr<SGExpression<T> > inputExpressions[2] = {
-      SGReadFExpression<T>(inputRoot, expression->getChild(0)),
-      SGReadFExpression<T>(inputRoot, expression->getChild(1))
-    };
-    if (!inputExpressions[0] || !inputExpressions[1]) {
-      SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
-      return 0;
-    }
-    return new SGDivExpression<T>(inputExpressions[0], inputExpressions[1]);
-  }
-  if (name == "mod") {
-    if (expression->nChildren() != 2) {
-      SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
-      return 0;
-    }
-    SGSharedPtr<SGExpression<T> > inputExpressions[2] = {
-      SGReadFExpression<T>(inputRoot, expression->getChild(0)),
-      SGReadFExpression<T>(inputRoot, expression->getChild(1))
-    };
-    if (!inputExpressions[0] || !inputExpressions[1]) {
-      SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
-      return 0;
-    }
-    return new SGModExpression<T>(inputExpressions[0], inputExpressions[1]);
-  }
-  if (name == "pow") {
-    if (expression->nChildren() != 2) {
-      SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
-      return 0;
-    }
-    SGSharedPtr<SGExpression<T> > inputExpressions[2] = {
-      SGReadIExpression<T>(inputRoot, expression->getChild(0)),
-      SGReadIExpression<T>(inputRoot, expression->getChild(1))
-    };
-    if (!inputExpressions[0] || !inputExpressions[1]) {
-      SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
-      return 0;
-    }
-    return new SGPowExpression<T>(inputExpressions[0], inputExpressions[1]);
-  }
-
-  return 0;
+    if (name == "atan2") {
+        if (expression->nChildren() != 2) {
+            SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
+            return 0;
+        }
+        SGSharedPtr<SGExpression<T> > inputExpressions[2] = {
+            SGReadExpression<T>(inputRoot, expression->getChild(0)),
+            SGReadExpression<T>(inputRoot, expression->getChild(1))
+        };
+        if (!inputExpressions[0] || !inputExpressions[1]) {
+            SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
+            return 0;
+        }
+        return new SGAtan2Expression<T>(inputExpressions[0], inputExpressions[1]);
+    }
+    if (name == "div") {
+        if (expression->nChildren() != 2) {
+            SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
+            return 0;
+        }
+        SGSharedPtr<SGExpression<T> > inputExpressions[2] = {
+            SGReadExpression<T>(inputRoot, expression->getChild(0)),
+            SGReadExpression<T>(inputRoot, expression->getChild(1))
+        };
+        if (!inputExpressions[0] || !inputExpressions[1]) {
+            SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
+            return 0;
+        }
+        return new SGDivExpression<T>(inputExpressions[0], inputExpressions[1]);
+    }
+    if (name == "mod") {
+        if (expression->nChildren() != 2) {
+            SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
+            return 0;
+        }
+        SGSharedPtr<SGExpression<T> > inputExpressions[2] = {
+            SGReadExpression<T>(inputRoot, expression->getChild(0)),
+            SGReadExpression<T>(inputRoot, expression->getChild(1))
+        };
+        if (!inputExpressions[0] || !inputExpressions[1]) {
+            SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
+            return 0;
+        }
+        return new SGModExpression<T>(inputExpressions[0], inputExpressions[1]);
+    }
+    if (name == "pow") {
+        if (expression->nChildren() != 2) {
+            SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
+            return 0;
+        }
+        SGSharedPtr<SGExpression<T> > inputExpressions[2] = {
+            SGReadExpression<T>(inputRoot, expression->getChild(0)),
+            SGReadExpression<T>(inputRoot, expression->getChild(1))
+        };
+        if (!inputExpressions[0] || !inputExpressions[1]) {
+            SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
+            return 0;
+        }
+        return new SGPowExpression<T>(inputExpressions[0], inputExpressions[1]);
+    }
+
+    return 0;
 }
 
 SGExpression<int>*
 SGReadIntExpression(SGPropertyNode *inputRoot,
                     const SGPropertyNode *configNode)
-{ return SGReadIExpression<int>(inputRoot, configNode); }
+{ return SGReadExpression<int>(inputRoot, configNode); }
 
 SGExpression<float>*
 SGReadFloatExpression(SGPropertyNode *inputRoot,
                       const SGPropertyNode *configNode)
-{ return SGReadFExpression<float>(inputRoot, configNode); }
+{ return SGReadExpression<float>(inputRoot, configNode); }
 
 SGExpression<double>*
 SGReadDoubleExpression(SGPropertyNode *inputRoot,
                        const SGPropertyNode *configNode)
-{ return SGReadFExpression<double>(inputRoot, configNode); }
+{ return SGReadExpression<double>(inputRoot, configNode); }
 
 // SGExpression<bool>*
 // SGReadBoolExpression(SGPropertyNode *inputRoot,
 //                      const SGPropertyNode *configNode)
 // { return SGReadBExpression<bool>(inputRoot, configNode); }
+
+namespace simgear
+{
+namespace expression
+{
+
+bool Parser::readChildren(const SGPropertyNode* exp,
+                          vector<Expression*>& result)
+{
+    for (int i = 0; i < exp->nChildren(); ++i)
+        result.push_back(read(exp->getChild(i)));
+    return true;
+}
+
+void ExpressionParser::addExpParser(const string& token, exp_parser parsefn)
+{
+    ParserMapSingleton::instance()
+        ->_parserTable.insert(std::make_pair(token, parsefn));
+}
+
+Expression* valueParser(const SGPropertyNode* exp, Parser* parser)
+{
+    switch (exp->getType()) {
+    case props::BOOL:
+        return new SGConstExpression<bool>(getValue<bool>(exp));        
+    case props::INT:
+        return new SGConstExpression<int>(getValue<int>(exp));        
+    case props::FLOAT:
+        return new SGConstExpression<float>(getValue<float>(exp));
+    case props::DOUBLE:
+        return new SGConstExpression<double>(getValue<double>(exp));
+    default:
+        return 0;
+    }
+}
+
+ExpParserRegistrar valueRegistrar("value", valueParser);
+
+template<typename T, typename OpType>
+inline Expression* makeConvert(Expression* e)
+{
+    return new ConvertExpression<T,
+        OpType>(static_cast<SGExpression<OpType>*>(e));
+}
+
+Type promoteAndConvert(vector<Expression*>& exps, Type minType = BOOL)
+{
+    vector<Expression*>::iterator maxElem
+        = max_element(exps.begin(), exps.end());
+    Type maxType = (*maxElem)->getType();
+    Type resultType = minType < maxType ? maxType : minType;
+    for (vector<Expression*>::iterator itr = exps.begin(), end = exps.end();
+         itr != end;
+         ++itr) {
+        if ((*itr)->getType() != resultType) {
+            switch ((*itr)->getType()) {
+            case BOOL:
+                switch (resultType) {
+                case INT:
+                    *itr = makeConvert<int, bool>(*itr);
+                    break;
+                case FLOAT:
+                    *itr = makeConvert<float, bool>(*itr);
+                    break;
+                case DOUBLE:
+                    *itr = makeConvert<double, bool>(*itr);
+                    break;
+                default:
+                    break;
+                }
+                break;
+            case INT:
+                switch (resultType) {
+                case FLOAT:
+                    *itr = makeConvert<float, int>(*itr);
+                    break;
+                case DOUBLE:
+                    *itr = makeConvert<double, int>(*itr);
+                    break;
+                default:
+                    break;
+                }
+                break;
+            case FLOAT:
+                *itr = makeConvert<double, float>(*itr);
+                break;
+            default:
+                break;
+            }
+        }
+    }
+    return resultType;
+}
+
+template<template<typename OpType> class Expr>
+Expression* makeTypedOperandExp(Type operandType, vector<Expression*> children)
+{
+    switch (operandType) {
+    case BOOL:
+    {
+        Expr<bool> *expr = new Expr<bool>();
+        expr->addOperands(children.begin(), children.end());
+        return expr;
+    }
+    case INT:
+    {
+        Expr<int> *expr = new Expr<int>();
+        expr->addOperands(children.begin(), children.end());
+        return expr;
+    }
+    case FLOAT:
+    {
+        Expr<float> *expr = new Expr<float>();
+        expr->addOperands(children.begin(), children.end());
+        return expr;
+    }
+    case DOUBLE:
+    {
+        Expr<double> *expr = new Expr<double>();
+        expr->addOperands(children.begin(), children.end());
+        return expr;
+    }
+    default:
+        return 0;
+    }
+}
+
+template<template<typename OpType> class PredExp>
+Expression* predParser(const SGPropertyNode* exp, Parser* parser)
+{
+    vector<Expression*> children;
+    parser->readChildren(exp, children);
+    Type operandType = promoteAndConvert(children);
+    return makeTypedOperandExp<PredExp>(operandType, children);
+}
+
+ExpParserRegistrar equalRegistrar("equal", predParser<EqualToExpression>);
+ExpParserRegistrar lessRegistrar("less", predParser<LessExpression>);
+ExpParserRegistrar leRegistrar("less-equal", predParser<LessEqualExpression>);
+
+template<typename Logicop>
+Expression* logicopParser(const SGPropertyNode* exp, Parser* parser)
+{
+    using namespace boost;
+    vector<Expression*> children;
+    parser->readChildren(exp, children);
+    vector<Expression*>::iterator notBool =
+        find_if(children.begin(), children.end(),
+                boost::bind(&Expression::getType, _1) != BOOL);
+    if (notBool != children.end())
+        throw("non boolean operand to logical expression");
+    Logicop *expr = new Logicop;
+    expr->addOperands(children.begin(), children.end());
+    return expr;
+}
+
+ExpParserRegistrar andRegistrar("and", logicopParser<AndExpression>);
+ExpParserRegistrar orRegistrar("or", logicopParser<OrExpression>);
+
+int BindingLayout::addBinding(const string& name, Type type)
+{
+    //XXX error checkint
+    vector<VariableBinding>::iterator itr
+        = find_if(bindings.begin(), bindings.end(),
+                  boost::bind(&VariableBinding::name, _1) == name);
+    if (itr != bindings.end())
+        return itr->location;
+    int result = bindings.size();
+    bindings.push_back(VariableBinding(name, type, bindings.size()));
+    return result;
+}
+
+bool BindingLayout::findBinding(const std::string& name,
+                                VariableBinding& result) const
+{
+    using namespace std;
+    using namespace boost;
+    vector<VariableBinding>::const_iterator itr
+        = find_if(bindings.begin(), bindings.end(),
+                  boost::bind(&VariableBinding::name, _1) == name);
+    if (itr != bindings.end()) {
+        result = *itr;
+        return true;
+    } else {
+        return false;
+    }
+}
+}
+}