X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fstructure%2FSGExpression.cxx;h=df0aa9d747d13b6a0e26d61a9a69f6459b17dd19;hb=5b92575ed31ab0577d5ece4da42a88cfb88b4ad7;hp=5a04c509ced1bdf404ffd9c50108d700f3b9b1a6;hpb=4db643509090824a25ead50f2626ace3e1ed8ff3;p=simgear.git diff --git a/simgear/structure/SGExpression.cxx b/simgear/structure/SGExpression.cxx index 5a04c509..df0aa9d7 100644 --- a/simgear/structure/SGExpression.cxx +++ b/simgear/structure/SGExpression.cxx @@ -24,84 +24,123 @@ #endif #include "SGExpression.hxx" +#include "Singleton.hxx" +#include +#include +#include #include #include +#include +#include // for strcmp + #include +using namespace std; + +namespace simgear +{ +template +const expression::Value evalValue(const Expression* exp, + const expression::Binding* b) +{ + T val; + static_cast*>(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(exp, b); + case INT: + return evalValue(exp, b); + case FLOAT: + return evalValue(exp, b); + case DOUBLE: + return evalValue(exp, b); + default: + throw "invalid type."; + } +} +} + template 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 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 static SGExpression* -SGReadIExpression(SGPropertyNode *inputRoot, const SGPropertyNode *expression); +SGReadExpression(SGPropertyNode *inputRoot, const SGPropertyNode *expression); template static bool SGReadNaryOperands(SGNaryExpression* nary, SGPropertyNode *inputRoot, const SGPropertyNode *expression) { - for (int i = 0; i < expression->nChildren(); ++i) { - SGExpression* inputExpression; - inputExpression = SGReadIExpression(inputRoot, expression->getChild(i)); - if (!inputExpression) - return false; - nary->addOperand(inputExpression); - } - return true; + for (int i = 0; i < expression->nChildren(); ++i) { + SGExpression* inputExpression; + inputExpression = SGReadExpression(inputRoot, expression->getChild(i)); + if (!inputExpression) + return false; + nary->addOperand(inputExpression); + } + return true; } // template @@ -126,514 +165,733 @@ SGReadNaryOperands(SGNaryExpression* nary, template static SGExpression* -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(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(inputNode); - } - - if (name == "abs" || name == "fabs") { - if (expression->nChildren() != 1) { - SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); - return 0; - } - SGSharedPtr > inputExpression; - inputExpression = SGReadIExpression(inputRoot, expression->getChild(0)); - if (!inputExpression) { - SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); - return 0; - } - return new SGAbsExpression(inputExpression); - } - - if (name == "sqr") { - if (expression->nChildren() != 1) { - SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); - return 0; - } - SGSharedPtr > inputExpression; - inputExpression = SGReadIExpression(inputRoot, expression->getChild(0)); - if (!inputExpression) { - SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); - return 0; - } - return new SGSqrExpression(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::min(SGLimits::min(), -SGLimits::max()); - - const SGPropertyNode* maxProperty = expression->getChild("clipMax"); - T clipMax; - if (!SGReadValueFromContent(maxProperty, clipMax)) - clipMin = SGLimits::max(); - - SGSharedPtr > inputExpression; - for (int i = 0; !inputExpression && i < expression->nChildren(); ++i) - inputExpression = SGReadIExpression(inputRoot, expression->getChild(i)); - if (!inputExpression) { - SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); - return 0; - } - return new SGClipExpression(inputExpression, clipMin, clipMax); - } - - if (name == "div") { - if (expression->nChildren() != 2) { - SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); - return 0; - } - SGSharedPtr > inputExpressions[2] = { - SGReadIExpression(inputRoot, expression->getChild(0)), - SGReadIExpression(inputRoot, expression->getChild(1)) - }; - if (!inputExpressions[0] || !inputExpressions[1]) { - SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); - return 0; - } - return new SGDivExpression(inputExpressions[0], inputExpressions[1]); - } - if (name == "mod") { - if (expression->nChildren() != 2) { - SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); - return 0; - } - SGSharedPtr > inputExpressions[2] = { - SGReadIExpression(inputRoot, expression->getChild(0)), - SGReadIExpression(inputRoot, expression->getChild(1)) - }; - if (!inputExpressions[0] || !inputExpressions[1]) { - SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); - return 0; - } - return new SGModExpression(inputExpressions[0], inputExpressions[1]); - } - - if (name == "sum") { - if (expression->nChildren() < 1) { - SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); - return 0; - } - SGSumExpression* output = new SGSumExpression; - 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* output = new SGProductExpression; - 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* output = new SGMinExpression; - 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* output = new SGMaxExpression; - if (!SGReadNaryOperands(output, inputRoot, expression)) { - delete output; - SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); - return 0; - } - return output; - } - - return 0; -} - - -template -static SGExpression* -SGReadFExpression(SGPropertyNode *inputRoot, const SGPropertyNode *expression) +SGReadExpression(SGPropertyNode *inputRoot, const SGPropertyNode *expression) { - SGExpression* r = SGReadIExpression(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 > inputExpression; - inputExpression = SGReadFExpression(inputRoot, expression->getChild(0)); - if (!inputExpression) { - SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); - return 0; - } - return new SGACosExpression(inputExpression); - } - - if (name == "asin") { - if (expression->nChildren() != 1) { - SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); - return 0; - } - SGSharedPtr > inputExpression; - inputExpression = SGReadFExpression(inputRoot, expression->getChild(0)); - if (!inputExpression) { - SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); - return 0; - } - return new SGASinExpression(inputExpression); - } - - if (name == "atan") { - if (expression->nChildren() != 1) { - SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); - return 0; - } - SGSharedPtr > inputExpression; - inputExpression = SGReadFExpression(inputRoot, expression->getChild(0)); - if (!inputExpression) { - SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); - return 0; - } - return new SGATanExpression(inputExpression); - } - - if (name == "ceil") { - if (expression->nChildren() != 1) { - SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); - return 0; - } - SGSharedPtr > inputExpression; - inputExpression = SGReadFExpression(inputRoot, expression->getChild(0)); - if (!inputExpression) { - SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); - return 0; - } - return new SGCeilExpression(inputExpression); - } - - if (name == "cos") { - if (expression->nChildren() != 1) { - SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); - return 0; - } - SGSharedPtr > inputExpression; - inputExpression = SGReadFExpression(inputRoot, expression->getChild(0)); - if (!inputExpression) { - SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); - return 0; - } - return new SGCosExpression(inputExpression); - } - - if (name == "cosh") { - if (expression->nChildren() != 1) { - SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); - return 0; - } - SGSharedPtr > inputExpression; - inputExpression = SGReadFExpression(inputRoot, expression->getChild(0)); - if (!inputExpression) { - SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); - return 0; - } - return new SGCoshExpression(inputExpression); - } - - if (name == "deg2rad") { - if (expression->nChildren() != 1) { - SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); - return 0; - } - SGSharedPtr > inputExpression; - inputExpression = SGReadFExpression(inputRoot, expression->getChild(0)); - if (!inputExpression) { - SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); - return 0; - } - return new SGScaleExpression(inputExpression, SGMisc::pi()/180); - } - - if (name == "exp") { - if (expression->nChildren() != 1) { - SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); - return 0; - } - SGSharedPtr > inputExpression; - inputExpression = SGReadFExpression(inputRoot, expression->getChild(0)); - if (!inputExpression) { - SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); - return 0; - } - return new SGExpExpression(inputExpression); - } - - if (name == "floor") { - if (expression->nChildren() != 1) { - SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); - return 0; - } - SGSharedPtr > inputExpression; - inputExpression = SGReadFExpression(inputRoot, expression->getChild(0)); - if (!inputExpression) { - SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); - return 0; - } - return new SGFloorExpression(inputExpression); - } - - if (name == "log") { - if (expression->nChildren() != 1) { - SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); - return 0; - } - SGSharedPtr > inputExpression; - inputExpression = SGReadFExpression(inputRoot, expression->getChild(0)); - if (!inputExpression) { - SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); - return 0; - } - return new SGLogExpression(inputExpression); - } - - if (name == "log10") { - if (expression->nChildren() != 1) { - SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); - return 0; - } - SGSharedPtr > inputExpression; - inputExpression = SGReadFExpression(inputRoot, expression->getChild(0)); - if (!inputExpression) { - SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); - return 0; - } - return new SGLog10Expression(inputExpression); - } - - if (name == "rad2deg") { - if (expression->nChildren() != 1) { - SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); - return 0; - } - SGSharedPtr > inputExpression; - inputExpression = SGReadFExpression(inputRoot, expression->getChild(0)); - if (!inputExpression) { - SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); - return 0; - } - return new SGScaleExpression(inputExpression, 180/SGMisc::pi()); - } - - if (name == "sin") { - if (expression->nChildren() != 1) { - SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); - return 0; - } - SGSharedPtr > inputExpression; - inputExpression = SGReadFExpression(inputRoot, expression->getChild(0)); - if (!inputExpression) { - SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); - return 0; - } - return new SGSinExpression(inputExpression); - } - - if (name == "sinh") { - if (expression->nChildren() != 1) { - SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); - return 0; - } - SGSharedPtr > inputExpression; - inputExpression = SGReadFExpression(inputRoot, expression->getChild(0)); - if (!inputExpression) { - SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); - return 0; - } - return new SGSinhExpression(inputExpression); - } - - if (name == "sqrt") { - if (expression->nChildren() != 1) { - SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); - return 0; - } - SGSharedPtr > inputExpression; - inputExpression = SGReadFExpression(inputRoot, expression->getChild(0)); - if (!inputExpression) { - SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); - return 0; - } - return new SGSqrtExpression(inputExpression); - } - - if (name == "tan") { - if (expression->nChildren() != 1) { - SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); - return 0; - } - SGSharedPtr > inputExpression; - inputExpression = SGReadFExpression(inputRoot, expression->getChild(0)); - if (!inputExpression) { - SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); - return 0; - } - return new SGTanExpression(inputExpression); - } - - if (name == "tanh") { - if (expression->nChildren() != 1) { - SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); - return 0; - } - SGSharedPtr > inputExpression; - inputExpression = SGReadFExpression(inputRoot, expression->getChild(0)); - if (!inputExpression) { - SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); - return 0; - } - return new SGTanhExpression(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(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(inputNode); + } + + if (name == "abs" || name == "fabs") { + if (expression->nChildren() != 1) { + SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); + return 0; + } + SGSharedPtr > inputExpression; + inputExpression = SGReadExpression(inputRoot, expression->getChild(0)); + if (!inputExpression) { + SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); + return 0; + } + return new SGAbsExpression(inputExpression); + } + + if (name == "sqr") { + if (expression->nChildren() != 1) { + SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); + return 0; + } + SGSharedPtr > inputExpression; + inputExpression = SGReadExpression(inputRoot, expression->getChild(0)); + if (!inputExpression) { + SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); + return 0; + } + return new SGSqrExpression(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::min(SGLimits::min(), -SGLimits::max()); + + const SGPropertyNode* maxProperty = expression->getChild("clipMax"); + T clipMax; + if (!SGReadValueFromContent(maxProperty, clipMax)) + clipMin = SGLimits::max(); + + SGSharedPtr > inputExpression; + for (int i = 0; !inputExpression && i < expression->nChildren(); ++i) + inputExpression = SGReadExpression(inputRoot, expression->getChild(i)); + if (!inputExpression) { + SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); + return 0; + } + return new SGClipExpression(inputExpression, clipMin, clipMax); + } + + if (name == "div") { + if (expression->nChildren() != 2) { + SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); + return 0; + } + SGSharedPtr > inputExpressions[2] = { + SGReadExpression(inputRoot, expression->getChild(0)), + SGReadExpression(inputRoot, expression->getChild(1)) + }; + if (!inputExpressions[0] || !inputExpressions[1]) { + SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); + return 0; + } + return new SGDivExpression(inputExpressions[0], inputExpressions[1]); + } + if (name == "mod") { + if (expression->nChildren() != 2) { + SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); + return 0; + } + SGSharedPtr > inputExpressions[2] = { + SGReadExpression(inputRoot, expression->getChild(0)), + SGReadExpression(inputRoot, expression->getChild(1)) + }; + if (!inputExpressions[0] || !inputExpressions[1]) { + SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); + return 0; + } + return new SGModExpression(inputExpressions[0], inputExpressions[1]); + } + + if (name == "sum") { + if (expression->nChildren() < 1) { + SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); + return 0; + } + SGSumExpression* output = new SGSumExpression; + 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* output = new SGDifferenceExpression; + 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* output = new SGProductExpression; + 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* output = new SGMinExpression; + 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* output = new SGMaxExpression; + 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; (inChildren()) && !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 > inputExpression; + inputExpression = SGReadExpression(inputRoot, inputNode); + if (!inputExpression) { + SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); + return 0; + } + + return new SGInterpTableExpression(inputExpression, tab); + } + + if (name == "acos") { + if (expression->nChildren() != 1) { + SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); + return 0; + } + SGSharedPtr > inputExpression; + inputExpression = SGReadExpression(inputRoot, expression->getChild(0)); + if (!inputExpression) { + SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); + return 0; + } + return new SGACosExpression(inputExpression); + } + + if (name == "asin") { + if (expression->nChildren() != 1) { + SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); + return 0; + } + SGSharedPtr > inputExpression; + inputExpression = SGReadExpression(inputRoot, expression->getChild(0)); + if (!inputExpression) { + SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); + return 0; + } + return new SGASinExpression(inputExpression); + } + + if (name == "atan") { + if (expression->nChildren() != 1) { + SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); + return 0; + } + SGSharedPtr > inputExpression; + inputExpression = SGReadExpression(inputRoot, expression->getChild(0)); + if (!inputExpression) { + SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); + return 0; + } + return new SGATanExpression(inputExpression); + } + + if (name == "ceil") { + if (expression->nChildren() != 1) { + SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); + return 0; + } + SGSharedPtr > inputExpression; + inputExpression = SGReadExpression(inputRoot, expression->getChild(0)); + if (!inputExpression) { + SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); + return 0; + } + return new SGCeilExpression(inputExpression); + } + + if (name == "cos") { + if (expression->nChildren() != 1) { + SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); + return 0; + } + SGSharedPtr > inputExpression; + inputExpression = SGReadExpression(inputRoot, expression->getChild(0)); + if (!inputExpression) { + SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); + return 0; + } + return new SGCosExpression(inputExpression); + } + + if (name == "cosh") { + if (expression->nChildren() != 1) { + SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); + return 0; + } + SGSharedPtr > inputExpression; + inputExpression = SGReadExpression(inputRoot, expression->getChild(0)); + if (!inputExpression) { + SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); + return 0; + } + return new SGCoshExpression(inputExpression); + } + + if (name == "deg2rad") { + if (expression->nChildren() != 1) { + SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); + return 0; + } + SGSharedPtr > inputExpression; + inputExpression = SGReadExpression(inputRoot, expression->getChild(0)); + if (!inputExpression) { + SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); + return 0; + } + return new SGScaleExpression(inputExpression, SGMisc::pi()/180); + } + + if (name == "exp") { + if (expression->nChildren() != 1) { + SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); + return 0; + } + SGSharedPtr > inputExpression; + inputExpression = SGReadExpression(inputRoot, expression->getChild(0)); + if (!inputExpression) { + SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); + return 0; + } + return new SGExpExpression(inputExpression); + } + + if (name == "floor") { + if (expression->nChildren() != 1) { + SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); + return 0; + } + SGSharedPtr > inputExpression; + inputExpression = SGReadExpression(inputRoot, expression->getChild(0)); + if (!inputExpression) { + SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); + return 0; + } + return new SGFloorExpression(inputExpression); + } + + if (name == "log") { + if (expression->nChildren() != 1) { + SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); + return 0; + } + SGSharedPtr > inputExpression; + inputExpression = SGReadExpression(inputRoot, expression->getChild(0)); + if (!inputExpression) { + SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); + return 0; + } + return new SGLogExpression(inputExpression); + } + + if (name == "log10") { + if (expression->nChildren() != 1) { + SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); + return 0; + } + SGSharedPtr > inputExpression; + inputExpression = SGReadExpression(inputRoot, expression->getChild(0)); + if (!inputExpression) { + SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); + return 0; + } + return new SGLog10Expression(inputExpression); + } + + if (name == "rad2deg") { + if (expression->nChildren() != 1) { + SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); + return 0; + } + SGSharedPtr > inputExpression; + inputExpression = SGReadExpression(inputRoot, expression->getChild(0)); + if (!inputExpression) { + SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); + return 0; + } + return new SGScaleExpression(inputExpression, 180/SGMisc::pi()); + } + + if (name == "sin") { + if (expression->nChildren() != 1) { + SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); + return 0; + } + SGSharedPtr > inputExpression; + inputExpression = SGReadExpression(inputRoot, expression->getChild(0)); + if (!inputExpression) { + SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); + return 0; + } + return new SGSinExpression(inputExpression); + } + + if (name == "sinh") { + if (expression->nChildren() != 1) { + SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); + return 0; + } + SGSharedPtr > inputExpression; + inputExpression = SGReadExpression(inputRoot, expression->getChild(0)); + if (!inputExpression) { + SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); + return 0; + } + return new SGSinhExpression(inputExpression); + } + + if (name == "sqrt") { + if (expression->nChildren() != 1) { + SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); + return 0; + } + SGSharedPtr > inputExpression; + inputExpression = SGReadExpression(inputRoot, expression->getChild(0)); + if (!inputExpression) { + SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); + return 0; + } + return new SGSqrtExpression(inputExpression); + } + + if (name == "tan") { + if (expression->nChildren() != 1) { + SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); + return 0; + } + SGSharedPtr > inputExpression; + inputExpression = SGReadExpression(inputRoot, expression->getChild(0)); + if (!inputExpression) { + SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); + return 0; + } + return new SGTanExpression(inputExpression); + } + + if (name == "tanh") { + if (expression->nChildren() != 1) { + SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); + return 0; + } + SGSharedPtr > inputExpression; + inputExpression = SGReadExpression(inputRoot, expression->getChild(0)); + if (!inputExpression) { + SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); + return 0; + } + return new SGTanhExpression(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 > inputExpressions[2] = { - SGReadFExpression(inputRoot, expression->getChild(0)), - SGReadFExpression(inputRoot, expression->getChild(1)) - }; - if (!inputExpressions[0] || !inputExpressions[1]) { - SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); - return 0; - } - return new SGAtan2Expression(inputExpressions[0], inputExpressions[1]); - } - if (name == "div") { - if (expression->nChildren() != 2) { - SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); - return 0; - } - SGSharedPtr > inputExpressions[2] = { - SGReadFExpression(inputRoot, expression->getChild(0)), - SGReadFExpression(inputRoot, expression->getChild(1)) - }; - if (!inputExpressions[0] || !inputExpressions[1]) { - SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); - return 0; - } - return new SGDivExpression(inputExpressions[0], inputExpressions[1]); - } - if (name == "mod") { - if (expression->nChildren() != 2) { - SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); - return 0; - } - SGSharedPtr > inputExpressions[2] = { - SGReadFExpression(inputRoot, expression->getChild(0)), - SGReadFExpression(inputRoot, expression->getChild(1)) - }; - if (!inputExpressions[0] || !inputExpressions[1]) { - SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); - return 0; - } - return new SGModExpression(inputExpressions[0], inputExpressions[1]); - } - if (name == "pow") { - if (expression->nChildren() != 2) { - SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); - return 0; - } - SGSharedPtr > inputExpressions[2] = { - SGReadIExpression(inputRoot, expression->getChild(0)), - SGReadIExpression(inputRoot, expression->getChild(1)) - }; - if (!inputExpressions[0] || !inputExpressions[1]) { - SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); - return 0; - } - return new SGPowExpression(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 > inputExpressions[2] = { + SGReadExpression(inputRoot, expression->getChild(0)), + SGReadExpression(inputRoot, expression->getChild(1)) + }; + if (!inputExpressions[0] || !inputExpressions[1]) { + SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); + return 0; + } + return new SGAtan2Expression(inputExpressions[0], inputExpressions[1]); + } + if (name == "div") { + if (expression->nChildren() != 2) { + SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); + return 0; + } + SGSharedPtr > inputExpressions[2] = { + SGReadExpression(inputRoot, expression->getChild(0)), + SGReadExpression(inputRoot, expression->getChild(1)) + }; + if (!inputExpressions[0] || !inputExpressions[1]) { + SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); + return 0; + } + return new SGDivExpression(inputExpressions[0], inputExpressions[1]); + } + if (name == "mod") { + if (expression->nChildren() != 2) { + SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); + return 0; + } + SGSharedPtr > inputExpressions[2] = { + SGReadExpression(inputRoot, expression->getChild(0)), + SGReadExpression(inputRoot, expression->getChild(1)) + }; + if (!inputExpressions[0] || !inputExpressions[1]) { + SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); + return 0; + } + return new SGModExpression(inputExpressions[0], inputExpressions[1]); + } + if (name == "pow") { + if (expression->nChildren() != 2) { + SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); + return 0; + } + SGSharedPtr > inputExpressions[2] = { + SGReadExpression(inputRoot, expression->getChild(0)), + SGReadExpression(inputRoot, expression->getChild(1)) + }; + if (!inputExpressions[0] || !inputExpressions[1]) { + SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression."); + return 0; + } + return new SGPowExpression(inputExpressions[0], inputExpressions[1]); + } + + return 0; } SGExpression* SGReadIntExpression(SGPropertyNode *inputRoot, const SGPropertyNode *configNode) -{ return SGReadIExpression(inputRoot, configNode); } +{ return SGReadExpression(inputRoot, configNode); } SGExpression* SGReadFloatExpression(SGPropertyNode *inputRoot, const SGPropertyNode *configNode) -{ return SGReadFExpression(inputRoot, configNode); } +{ return SGReadExpression(inputRoot, configNode); } SGExpression* SGReadDoubleExpression(SGPropertyNode *inputRoot, const SGPropertyNode *configNode) -{ return SGReadFExpression(inputRoot, configNode); } +{ return SGReadExpression(inputRoot, configNode); } // SGExpression* // SGReadBoolExpression(SGPropertyNode *inputRoot, // const SGPropertyNode *configNode) // { return SGReadBExpression(inputRoot, configNode); } + +namespace simgear +{ +namespace expression +{ + +bool Parser::readChildren(const SGPropertyNode* exp, + vector& 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(getValue(exp)); + case props::INT: + return new SGConstExpression(getValue(exp)); + case props::FLOAT: + return new SGConstExpression(getValue(exp)); + case props::DOUBLE: + return new SGConstExpression(getValue(exp)); + default: + return 0; + } +} + +ExpParserRegistrar valueRegistrar("value", valueParser); + +template +inline Expression* makeConvert(Expression* e) +{ + return new ConvertExpression(static_cast*>(e)); +} + +Type promoteAndConvert(vector& exps, Type minType = BOOL) +{ + vector::iterator maxElem + = max_element(exps.begin(), exps.end()); + Type maxType = (*maxElem)->getType(); + Type resultType = minType < maxType ? maxType : minType; + for (vector::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(*itr); + break; + case FLOAT: + *itr = makeConvert(*itr); + break; + case DOUBLE: + *itr = makeConvert(*itr); + break; + default: + break; + } + break; + case INT: + switch (resultType) { + case FLOAT: + *itr = makeConvert(*itr); + break; + case DOUBLE: + *itr = makeConvert(*itr); + break; + default: + break; + } + break; + case FLOAT: + *itr = makeConvert(*itr); + break; + default: + break; + } + } + } + return resultType; +} + +template class Expr> +Expression* makeTypedOperandExp(Type operandType, vector children) +{ + switch (operandType) { + case BOOL: + { + Expr *expr = new Expr(); + expr->addOperands(children.begin(), children.end()); + return expr; + } + case INT: + { + Expr *expr = new Expr(); + expr->addOperands(children.begin(), children.end()); + return expr; + } + case FLOAT: + { + Expr *expr = new Expr(); + expr->addOperands(children.begin(), children.end()); + return expr; + } + case DOUBLE: + { + Expr *expr = new Expr(); + expr->addOperands(children.begin(), children.end()); + return expr; + } + default: + return 0; + } +} + +template class PredExp> +Expression* predParser(const SGPropertyNode* exp, Parser* parser) +{ + vector children; + parser->readChildren(exp, children); + Type operandType = promoteAndConvert(children); + return makeTypedOperandExp(operandType, children); +} + +ExpParserRegistrar equalRegistrar("equal", predParser); +ExpParserRegistrar lessRegistrar("less", predParser); +ExpParserRegistrar leRegistrar("less-equal", predParser); + +template +Expression* logicopParser(const SGPropertyNode* exp, Parser* parser) +{ + using namespace boost; + vector children; + parser->readChildren(exp, children); + vector::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); +ExpParserRegistrar orRegistrar("or", logicopParser); + +int BindingLayout::addBinding(const string& name, Type type) +{ + //XXX error checkint + vector::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::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; + } +} +} +}