#endif
#include "SGExpression.hxx"
+#include "Singleton.hxx"
+#include <algorithm>
+#include <functional>
+#include <map>
+#include <utility>
#include <string>
#include <sstream>
+#include <boost/bind.hpp>
+
#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<>
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>
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 = SGReadIExpression<T>(inputRoot, expression->getChild(i));
+ if (!inputExpression)
+ return false;
+ nary->addOperand(inputExpression);
+ }
+ return true;
}
// template<typename T>
static SGExpression<T>*
SGReadIExpression(SGPropertyNode *inputRoot, const SGPropertyNode *expression)
{
- if (!expression)
- return 0;
+ 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;
+ }
- 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;
+ return 0;
}
static SGExpression<T>*
SGReadFExpression(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);
- }
+ 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 (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] = {
+ 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;
}
SGExpression<int>*
// SGReadBoolExpression(SGPropertyNode *inputRoot,
// const SGPropertyNode *configNode)
// { return SGReadBExpression<bool>(inputRoot, configNode); }
+
+namespace simgear
+{
+namespace expression
+{
+
+class Parser {
+public:
+ void addParser(const std::string& name, exp_parser parser)
+ {
+ _parserTable.insert(std::make_pair(name, parser));
+ }
+ Expression* read(const SGPropertyNode* exp)
+ {
+ ParserMap::iterator itr = _parserTable.find(exp->getName());
+ if (itr == _parserTable.end())
+ throw ParseError(string("unknown expression ") + exp->getName());
+ exp_parser parser = itr->second;
+ return (*parser)(exp, this);
+ }
+ // XXX vector of SGSharedPtr?
+ bool readChildren(const SGPropertyNode* exp,
+ vector<Expression*>& result);
+protected:
+ typedef std::map<const std::string, exp_parser> ParserMap;
+ ParserMap _parserTable;
+};
+
+class ExpressionParser : public Parser, public Singleton<ExpressionParser>
+{
+};
+
+void addExpParser(const string& token, exp_parser parsefn)
+{
+ ExpressionParser::instance()->addParser(token, parsefn);
+}
+
+Expression* read(const SGPropertyNode* exp, Parser* parser)
+{
+ if (!parser)
+ parser = ExpressionParser::instance();
+ return parser->read(exp);
+}
+
+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;
+}
+
+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(),
+ 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
+ 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(),
+ bind(&VariableBinding::name, _1) == name);
+ if (itr != bindings.end()) {
+ result = *itr;
+ return true;
+ } else {
+ return false;
+ }
+}
+}
+}
#ifndef _SG_EXPRESSION_HXX
#define _SG_EXPRESSION_HXX 1
+#include <string>
+#include <vector>
+
#include <simgear/props/condition.hxx>
#include <simgear/props/props.hxx>
#include <simgear/math/interpolater.hxx>
#include <simgear/math/SGMath.hxx>
#include <simgear/scene/model/persparam.hxx>
+#include <simgear/structure/exception.hxx>
/// Expression tree implementation.
+namespace simgear
+{
+ namespace expression
+ {
+ enum Type {
+ BOOL = 0,
+ INT,
+ FLOAT,
+ DOUBLE
+ };
+ template<typename T> struct TypeTraits;
+ template<> struct TypeTraits<bool> {
+ static const Type typeTag = BOOL;
+ };
+ template<> struct TypeTraits<int> {
+ static const Type typeTag = INT;
+ };
+ template<> struct TypeTraits<float> {
+ static const Type typeTag = FLOAT;
+ };
+ template<> struct TypeTraits<double> {
+ static const Type typeTag = DOUBLE;
+ };
+
+ struct Value
+ {
+ Type typeTag;
+ union {
+ bool boolVal;
+ int intVal;
+ float floatVal;
+ double doubleVal;
+ } val;
+
+ Value() : typeTag(DOUBLE)
+ {
+ val.doubleVal = 0.0;
+ }
+
+ Value(bool val_) : typeTag(BOOL)
+ {
+ val.boolVal = val_;
+ }
+
+ Value(int val_) : typeTag(INT)
+ {
+ val.intVal = val_;
+ }
+
+ Value(float val_) : typeTag(FLOAT)
+ {
+ val.floatVal = val_;
+ }
+
+ Value(double val_) : typeTag(DOUBLE)
+ {
+ val.doubleVal = val_;
+ }
+
+ };
+
+ class Binding;
+ }
+
+ class Expression : public SGReferenced
+ {
+ public:
+ virtual ~Expression() {}
+ virtual expression::Type getType() const = 0;
+ };
+
+ const expression::Value eval(const Expression* exp,
+ const expression::Binding* binding = 0);
+
+}
+
template<typename T>
-class SGExpression : public SGReferenced {
+class SGExpression : public simgear::Expression {
public:
virtual ~SGExpression() {}
- virtual void eval(T&) const = 0;
+ typedef T result_type;
+ typedef T operand_type;
+ virtual void eval(T&, const simgear::expression::Binding*) const = 0;
- T getValue() const
- { T value; eval(value); return value; }
+ T getValue(const simgear::expression::Binding* binding = 0) const
+ { T value; eval(value, binding); return value; }
virtual bool isConst() const { return false; }
virtual SGExpression* simplify();
+ virtual simgear::expression::Type getType() const
+ {
+ return simgear::expression::TypeTraits<T>::typeTag;
+ }
+ virtual simgear::expression::Type getOperandType() const
+ {
+ return simgear::expression::TypeTraits<T>::typeTag;
+ }
};
/// Constant value expression
{ }
void setValue(const T& value)
{ _value = value; }
- const T& getValue() const
+ const T& getValue(const simgear::expression::Binding* binding = 0) const
{ return _value; }
- virtual void eval(T& value) const
+ virtual void eval(T& value, const simgear::expression::Binding*) const
{ value = _value; }
virtual bool isConst() const { return true; }
private:
return _expressions.size() - 1;
}
+ template<typename Iter>
+ void addOperands(Iter begin, Iter end)
+ {
+ for (Iter iter = begin; iter != end; ++iter)
+ {
+ addOperand(static_cast< ::SGExpression<T>*>(*iter));
+ }
+ }
+
virtual bool isConst() const
{
for (unsigned i = 0; i < _expressions.size(); ++i)
{ }
void setPropertyNode(const SGPropertyNode* prop)
{ _prop = prop; }
- virtual void eval(T& value) const
+ virtual void eval(T& value, const simgear::expression::Binding*) const
{ doEval(value); }
private:
void doEval(float& value) const
: SGUnaryExpression<T>(expr)
{ }
- virtual void eval(T& value) const
- { value = getOperand()->getValue(); if (value <= 0) value = -value; }
+ virtual void eval(T& value, const simgear::expression::Binding* b) const
+ { value = getOperand()->getValue(b); if (value <= 0) value = -value; }
using SGUnaryExpression<T>::getOperand;
};
: SGUnaryExpression<T>(expr)
{ }
- virtual void eval(T& value) const
- { value = acos(SGMisc<T>::clip(getOperand()->getValue(), -1, 1)); }
+ virtual void eval(T& value, const simgear::expression::Binding* b) const
+ { value = acos(SGMisc<T>::clip(getOperand()->getValue(b), -1, 1)); }
using SGUnaryExpression<T>::getOperand;
};
: SGUnaryExpression<T>(expr)
{ }
- virtual void eval(T& value) const
- { value = asin(SGMisc<T>::clip(getOperand()->getValue(), -1, 1)); }
+ virtual void eval(T& value, const simgear::expression::Binding* b) const
+ { value = asin(SGMisc<T>::clip(getOperand()->getValue(b), -1, 1)); }
using SGUnaryExpression<T>::getOperand;
};
: SGUnaryExpression<T>(expr)
{ }
- virtual void eval(T& value) const
- { value = atan(getOperand()->getValue()); }
+ virtual void eval(T& value, const simgear::expression::Binding* b) const
+ { value = atan(getOperand()->getValue(b)); }
using SGUnaryExpression<T>::getOperand;
};
: SGUnaryExpression<T>(expr)
{ }
- virtual void eval(T& value) const
- { value = ceil(getOperand()->getValue()); }
+ virtual void eval(T& value, const simgear::expression::Binding* b) const
+ { value = ceil(getOperand()->getValue(b)); }
using SGUnaryExpression<T>::getOperand;
};
: SGUnaryExpression<T>(expr)
{ }
- virtual void eval(T& value) const
- { value = cos(getOperand()->getValue()); }
+ virtual void eval(T& value, const simgear::expression::Binding* b) const
+ { value = cos(getOperand()->getValue(b)); }
using SGUnaryExpression<T>::getOperand;
};
: SGUnaryExpression<T>(expr)
{ }
- virtual void eval(T& value) const
- { value = cosh(getOperand()->getValue()); }
+ virtual void eval(T& value, const simgear::expression::Binding* b) const
+ { value = cosh(getOperand()->getValue(b)); }
using SGUnaryExpression<T>::getOperand;
};
: SGUnaryExpression<T>(expr)
{ }
- virtual void eval(T& value) const
- { value = exp(getOperand()->getValue()); }
+ virtual void eval(T& value, const simgear::expression::Binding* b) const
+ { value = exp(getOperand()->getValue(b)); }
using SGUnaryExpression<T>::getOperand;
};
: SGUnaryExpression<T>(expr)
{ }
- virtual void eval(T& value) const
- { value = floor(getOperand()->getValue()); }
+ virtual void eval(T& value, const simgear::expression::Binding* b) const
+ { value = floor(getOperand()->getValue(b)); }
using SGUnaryExpression<T>::getOperand;
};
: SGUnaryExpression<T>(expr)
{ }
- virtual void eval(T& value) const
- { value = log(getOperand()->getValue()); }
+ virtual void eval(T& value, const simgear::expression::Binding* b) const
+ { value = log(getOperand()->getValue(b)); }
using SGUnaryExpression<T>::getOperand;
};
: SGUnaryExpression<T>(expr)
{ }
- virtual void eval(T& value) const
- { value = log10(getOperand()->getValue()); }
+ virtual void eval(T& value, const simgear::expression::Binding* b) const
+ { value = log10(getOperand()->getValue(b)); }
using SGUnaryExpression<T>::getOperand;
};
: SGUnaryExpression<T>(expr)
{ }
- virtual void eval(T& value) const
- { value = sin(getOperand()->getValue()); }
+ virtual void eval(T& value, const simgear::expression::Binding* b) const
+ { value = sin(getOperand()->getValue(b)); }
using SGUnaryExpression<T>::getOperand;
};
: SGUnaryExpression<T>(expr)
{ }
- virtual void eval(T& value) const
- { value = sinh(getOperand()->getValue()); }
+ virtual void eval(T& value, const simgear::expression::Binding* b) const
+ { value = sinh(getOperand()->getValue(b)); }
using SGUnaryExpression<T>::getOperand;
};
: SGUnaryExpression<T>(expr)
{ }
- virtual void eval(T& value) const
- { value = getOperand()->getValue(); value = value*value; }
+ virtual void eval(T& value, const simgear::expression::Binding* b) const
+ { value = getOperand()->getValue(b); value = value*value; }
using SGUnaryExpression<T>::getOperand;
};
: SGUnaryExpression<T>(expr)
{ }
- virtual void eval(T& value) const
- { value = sqrt(getOperand()->getValue()); }
+ virtual void eval(T& value, const simgear::expression::Binding* b) const
+ { value = sqrt(getOperand()->getValue(b)); }
using SGUnaryExpression<T>::getOperand;
};
: SGUnaryExpression<T>(expr)
{ }
- virtual void eval(T& value) const
- { value = tan(getOperand()->getValue()); }
+ virtual void eval(T& value, const simgear::expression::Binding* b) const
+ { value = tan(getOperand()->getValue(b)); }
using SGUnaryExpression<T>::getOperand;
};
: SGUnaryExpression<T>(expr)
{ }
- virtual void eval(T& value) const
- { value = tanh(getOperand()->getValue()); }
+ virtual void eval(T& value, const simgear::expression::Binding* b) const
+ { value = tanh(getOperand()->getValue(b)); }
using SGUnaryExpression<T>::getOperand;
};
const T& getScale() const
{ return _scale; }
- virtual void eval(T& value) const
- { value = _scale * getOperand()->getValue(); }
+ virtual void eval(T& value, const simgear::expression::Binding* b) const
+ { value = _scale * getOperand()->getValue(b); }
virtual SGExpression<T>* simplify()
{
const T& getBias() const
{ return _bias; }
- virtual void eval(T& value) const
- { value = _bias + getOperand()->getValue(); }
+ virtual void eval(T& value, const simgear::expression::Binding* b) const
+ { value = _bias + getOperand()->getValue(b); }
virtual SGExpression<T>* simplify()
{
_interpTable(interpTable)
{ }
- virtual void eval(T& value) const
+ virtual void eval(T& value, const simgear::expression::Binding* b) const
{
if (_interpTable)
- value = _interpTable->interpolate(getOperand()->getValue());
+ value = _interpTable->interpolate(getOperand()->getValue(b));
}
using SGUnaryExpression<T>::getOperand;
const T& getClipMax() const
{ return _clipMax; }
- virtual void eval(T& value) const
+ virtual void eval(T& value, const simgear::expression::Binding* b) const
{
- value = SGMisc<T>::clip(getOperand()->getValue(), _clipMin, _clipMax);
+ value = SGMisc<T>::clip(getOperand()->getValue(b), _clipMin, _clipMax);
}
virtual SGExpression<T>* simplify()
const T& getScroll() const
{ return _scroll; }
- virtual void eval(T& value) const
- { value = apply_mods(getOperand()->getValue()); }
+ virtual void eval(T& value, const simgear::expression::Binding* b) const
+ { value = apply_mods(getOperand()->getValue(b)); }
using SGUnaryExpression<T>::getOperand;
void setDisabledValue(const T& disabledValue)
{ _disabledValue = disabledValue; }
- virtual void eval(T& value) const
+ virtual void eval(T& value, const simgear::expression::Binding* b) const
{
if (_enable->test())
- value = getOperand()->getValue();
+ value = getOperand()->getValue(b);
else
value = _disabledValue;
}
SGAtan2Expression(SGExpression<T>* expr0, SGExpression<T>* expr1)
: SGBinaryExpression<T>(expr0, expr1)
{ }
- virtual void eval(T& value) const
- { value = atan2(getOperand(0)->getValue(), getOperand(1)->getValue()); }
+ virtual void eval(T& value, const simgear::expression::Binding* b) const
+ { value = atan2(getOperand(0)->getValue(b), getOperand(1)->getValue(b)); }
using SGBinaryExpression<T>::getOperand;
};
SGDivExpression(SGExpression<T>* expr0, SGExpression<T>* expr1)
: SGBinaryExpression<T>(expr0, expr1)
{ }
- virtual void eval(T& value) const
- { value = getOperand(0)->getValue() / getOperand(1)->getValue(); }
+ virtual void eval(T& value, const simgear::expression::Binding* b) const
+ { value = getOperand(0)->getValue(b) / getOperand(1)->getValue(b); }
using SGBinaryExpression<T>::getOperand;
};
SGModExpression(SGExpression<T>* expr0, SGExpression<T>* expr1)
: SGBinaryExpression<T>(expr0, expr1)
{ }
- virtual void eval(T& value) const
- { value = mod(getOperand(0)->getValue(), getOperand(1)->getValue()); }
+ virtual void eval(T& value, const simgear::expression::Binding* b) const
+ { value = mod(getOperand(0)->getValue(b), getOperand(1)->getValue(b)); }
using SGBinaryExpression<T>::getOperand;
private:
int mod(const int& v0, const int& v1) const
SGPowExpression(SGExpression<T>* expr0, SGExpression<T>* expr1)
: SGBinaryExpression<T>(expr0, expr1)
{ }
- virtual void eval(T& value) const
- { value = pow(getOperand(0)->getValue(), getOperand(1)->getValue()); }
+ virtual void eval(T& value, const simgear::expression::Binding* b) const
+ { value = pow(getOperand(0)->getValue(b), getOperand(1)->getValue(b)); }
using SGBinaryExpression<T>::getOperand;
};
SGSumExpression(SGExpression<T>* expr0, SGExpression<T>* expr1)
: SGNaryExpression<T>(expr0, expr1)
{ }
- virtual void eval(T& value) const
+ virtual void eval(T& value, const simgear::expression::Binding* b) const
{
value = T(0);
unsigned sz = SGNaryExpression<T>::getNumOperands();
for (unsigned i = 0; i < sz; ++i)
- value += getOperand(i)->getValue();
+ value += getOperand(i)->getValue(b);
}
using SGNaryExpression<T>::getValue;
using SGNaryExpression<T>::getOperand;
SGProductExpression(SGExpression<T>* expr0, SGExpression<T>* expr1)
: SGNaryExpression<T>(expr0, expr1)
{ }
- virtual void eval(T& value) const
+ virtual void eval(T& value, const simgear::expression::Binding* b) const
{
value = T(1);
unsigned sz = SGNaryExpression<T>::getNumOperands();
for (unsigned i = 0; i < sz; ++i)
- value *= getOperand(i)->getValue();
+ value *= getOperand(i)->getValue(b);
}
using SGNaryExpression<T>::getValue;
using SGNaryExpression<T>::getOperand;
SGMinExpression(SGExpression<T>* expr0, SGExpression<T>* expr1)
: SGNaryExpression<T>(expr0, expr1)
{ }
- virtual void eval(T& value) const
+ virtual void eval(T& value, const simgear::expression::Binding* b) const
{
unsigned sz = SGNaryExpression<T>::getNumOperands();
if (sz < 1)
return;
- value = getOperand(0)->getValue();
+ value = getOperand(0)->getValue(b);
for (unsigned i = 1; i < sz; ++i)
- value = SGMisc<T>::min(value, getOperand(i)->getValue());
+ value = SGMisc<T>::min(value, getOperand(i)->getValue(b));
}
using SGNaryExpression<T>::getOperand;
};
SGMaxExpression(SGExpression<T>* expr0, SGExpression<T>* expr1)
: SGNaryExpression<T>(expr0, expr1)
{ }
- virtual void eval(T& value) const
+ virtual void eval(T& value, const simgear::expression::Binding* b) const
{
unsigned sz = SGNaryExpression<T>::getNumOperands();
if (sz < 1)
return;
- value = getOperand(0)->getValue();
+ value = getOperand(0)->getValue(b);
for (unsigned i = 1; i < sz; ++i)
- value = SGMisc<T>::max(value, getOperand(i)->getValue());
+ value = SGMisc<T>::max(value, getOperand(i)->getValue(b));
}
using SGNaryExpression<T>::getOperand;
};
SGReadBoolExpression(SGPropertyNode *inputRoot,
const SGPropertyNode *configNode);
+namespace simgear
+{
+ namespace expression
+ {
+ class Parser;
+ /**
+ * Function that parses a property tree, producing an expression.
+ */
+ typedef Expression* (*exp_parser)(const SGPropertyNode* exp,
+ Parser* parser);
+ void addExpParser(const std::string&, exp_parser);
+ Expression* read(const SGPropertyNode* exp, Parser* parser = 0);
+ /**
+ * Constructor for registering parser functions.
+ */
+ struct ExpParserRegistrar
+ {
+ ExpParserRegistrar(const std::string& token, exp_parser parser)
+ {
+ addExpParser(token, parser);
+ }
+ };
+
+ struct ParseError : public sg_exception
+ {
+ ParseError(const string& message = std::string())
+ : sg_exception(message) {}
+ };
+
+ // Support for binding variables around an expression.
+ class Binding
+ {
+ public:
+ virtual ~Binding() {}
+ const virtual Value* getBindings() const = 0;
+ virtual Value* getBindings() = 0;
+ };
+
+ class VariableLengthBinding : public Binding
+ {
+ public:
+ const Value* getBindings() const
+ {
+ if (_bindings.empty())
+ return 0;
+ else
+ return &_bindings[0];
+ }
+ Value* getBindings()
+ {
+ if (_bindings.empty())
+ return 0;
+ else
+ return &_bindings[0];
+ }
+ std::vector<Value> _bindings;
+ };
+
+ template<int Size> class FixedLengthBinding : public Binding
+ {
+ public:
+ Value* getBindings()
+ {
+ return &_bindings[0];
+ }
+ const Value* getBindings() const
+ {
+ return &_bindings[0];
+ }
+ Value _bindings[Size];
+ };
+
+ struct VariableBinding
+ {
+ VariableBinding() : type(expression::DOUBLE), location(-1) {}
+
+ VariableBinding(const std::string& name_, expression::Type type_,
+ int location_)
+ : name(name_), type(type_), location(location_)
+ {
+ }
+ std::string name;
+ expression::Type type;
+ int location;
+ };
+
+ class BindingLayout
+ {
+ public:
+ int addBinding(const std::string& name, expression::Type type);
+ bool findBinding(const string& name, VariableBinding& result) const;
+ protected:
+ std::vector<VariableBinding> bindings;
+ };
+ }
+
+ /**
+ * Access a variable definition. Use a location from a BindingLayout.
+ */
+ template<typename T>
+ class VariableExpression : public ::SGExpression<T> {
+ public:
+ VariableExpression(int location) : _location(location) {}
+ virtual ~VariableExpression() {}
+ virtual void eval(T& value, const simgear::expression::Binding* b) const
+ {
+ const expression::Value* values = b->getBindings();
+ value = *reinterpret_cast<const T *>(&values[_location].val);
+ }
+ protected:
+ int _location;
+
+ };
+
+ /**
+ * An n-ary expression where the types of the argument aren't the
+ * same as the return type.
+ */
+ template<typename T, typename OpType>
+ class GeneralNaryExpression : public ::SGExpression<T> {
+ public:
+ typedef OpType operand_type;
+ unsigned getNumOperands() const
+ { return _expressions.size(); }
+ const ::SGExpression<OpType>* getOperand(unsigned i) const
+ { return _expressions[i]; }
+ ::SGExpression<OpType>* getOperand(unsigned i)
+ { return _expressions[i]; }
+ unsigned addOperand(::SGExpression<OpType>* expression)
+ {
+ if (!expression)
+ return ~unsigned(0);
+ _expressions.push_back(expression);
+ return _expressions.size() - 1;
+ }
+
+ template<typename Iter>
+ void addOperands(Iter begin, Iter end)
+ {
+ for (Iter iter = begin; iter != end; ++iter)
+ {
+ addOperand(static_cast< ::SGExpression<OpType>*>(*iter));
+ }
+ }
+
+ virtual bool isConst() const
+ {
+ for (unsigned i = 0; i < _expressions.size(); ++i)
+ if (!_expressions[i]->isConst())
+ return false;
+ return true;
+ }
+ virtual ::SGExpression<T>* simplify()
+ {
+ for (unsigned i = 0; i < _expressions.size(); ++i)
+ _expressions[i] = _expressions[i]->simplify();
+ return SGExpression<T>::simplify();
+ }
+
+ simgear::expression::Type getOperandType() const
+ {
+ return simgear::expression::TypeTraits<OpType>::typeTag;
+ }
+
+ protected:
+ GeneralNaryExpression()
+ { }
+ GeneralNaryExpression(::SGExpression<OpType>* expr0,
+ ::SGExpression<OpType>* expr1)
+ { addOperand(expr0); addOperand(expr1); }
+
+ std::vector<SGSharedPtr<SGExpression<OpType> > > _expressions;
+ };
+
+ /**
+ * A predicate that wraps, for example the STL template predicate
+ * expressions like std::equal_to.
+ */
+ template<typename OpType, template<typename PredOp> class Pred>
+ class PredicateExpression : public GeneralNaryExpression<bool, OpType> {
+ public:
+ PredicateExpression()
+ {
+ }
+ PredicateExpression(::SGExpression<OpType>* expr0,
+ ::SGExpression<OpType>* expr1)
+ : GeneralNaryExpression<bool, OpType>(expr0, expr1)
+ {
+ }
+ virtual void eval(bool& value, const simgear::expression::Binding* b) const
+ {
+ unsigned sz = this->getNumOperands();
+ if (sz != 2)
+ return;
+ value = _pred(this->getOperand(0)->getValue(b),
+ this->getOperand(1)->getValue(b));
+ }
+ protected:
+ Pred<OpType> _pred;
+ };
+
+ template<template<typename OT> class Pred, typename OpType>
+ PredicateExpression<OpType, Pred>*
+ makePredicate(SGExpression<OpType>* op1, SGExpression<OpType>* op2)
+ {
+ return new PredicateExpression<OpType, Pred>(op1, op2);
+ }
+
+ template<typename OpType>
+ class EqualToExpression : public PredicateExpression<OpType, std::equal_to>
+ {
+ public:
+ EqualToExpression() {}
+ EqualToExpression(::SGExpression<OpType>* expr0,
+ ::SGExpression<OpType>* expr1)
+ : PredicateExpression<OpType, std::equal_to>(expr0, expr1)
+ {
+ }
+ };
+
+ template<typename OpType>
+ class LessExpression : public PredicateExpression<OpType, std::less>
+ {
+ public:
+ LessExpression() {}
+ LessExpression(::SGExpression<OpType>* expr0, ::SGExpression<OpType>* expr1)
+ : PredicateExpression<OpType, std::less>(expr0, expr1)
+ {
+ }
+ };
+
+ template<typename OpType>
+ class LessEqualExpression
+ : public PredicateExpression<OpType, std::less_equal>
+ {
+ public:
+ LessEqualExpression() {}
+ LessEqualExpression(::SGExpression<OpType>* expr0,
+ ::SGExpression<OpType>* expr1)
+ : PredicateExpression<OpType, std::less_equal>(expr0, expr1)
+ {
+ }
+ };
+
+ class NotExpression : public ::SGUnaryExpression<bool>
+ {
+ public:
+ NotExpression(::SGExpression<bool>* expr = 0)
+ : ::SGUnaryExpression<bool>(expr)
+ {
+ }
+ void eval(bool& value, const expression::Binding* b) const
+ {
+ value = !getOperand()->getValue(b);
+ }
+ };
+
+ class OrExpression : public ::SGNaryExpression<bool>
+ {
+ public:
+ void eval(bool& value, const expression::Binding* b) const
+ {
+ value = false;
+ for (int i = 0; i < getNumOperands(); ++i) {
+ value = value || getOperand(i)->getValue(b);
+ if (value)
+ return;
+ }
+ }
+ };
+
+ class AndExpression : public ::SGNaryExpression<bool>
+ {
+ public:
+ void eval(bool& value, const expression::Binding* b) const
+ {
+ value = true;
+ for (int i = 0; i < getNumOperands(); ++i) {
+ value = value && getOperand(i)->getValue(b);
+ if (!value)
+ return;
+ }
+ }
+ };
+
+ /**
+ * Convert an operand from OpType to T.
+ */
+ template<typename T, typename OpType>
+ class ConvertExpression : public GeneralNaryExpression<T, OpType>
+ {
+ public:
+ ConvertExpression() {}
+ ConvertExpression(::SGExpression<OpType>* expr0)
+ {
+ addOperand(expr0);
+ }
+ virtual void eval(T& value, const simgear::expression::Binding* b) const
+ {
+ typename ConvertExpression::operand_type result;
+ this->_expressions.at(0)->eval(result, b);
+ value = result;
+ }
+ };
+}
#endif // _SG_EXPRESSION_HXX