Browse Source

Added 'power' as a binary operator in expression classes and expression grammar.

Former-commit-id: c58321709e
main
dehnert 11 years ago
parent
commit
72cc5f2188
  1. 82
      src/parser/ExpressionParser.cpp
  2. 2
      src/parser/ExpressionParser.h
  3. 1
      src/parser/PrismParser.cpp
  4. 5
      src/storage/expressions/BinaryNumericalFunctionExpression.cpp
  5. 2
      src/storage/expressions/BinaryNumericalFunctionExpression.h
  6. 12
      src/storage/expressions/Expression.cpp
  7. 1
      src/storage/expressions/OperatorType.h
  8. 1
      test/functional/parser/PrismParserTest.cpp
  9. 12
      test/functional/storage/ExpressionTest.cpp

82
src/parser/ExpressionParser.cpp

@ -27,7 +27,10 @@ namespace storm {
unaryExpression = atomicExpression[qi::_val = qi::_1] | (qi::lit("!") >> atomicExpression)[qi::_val = phoenix::bind(&ExpressionParser::createNotExpression, phoenix::ref(*this), qi::_1)] | (qi::lit("-") >> atomicExpression)[qi::_val = phoenix::bind(&ExpressionParser::createMinusExpression, phoenix::ref(*this), qi::_1)]; unaryExpression = atomicExpression[qi::_val = qi::_1] | (qi::lit("!") >> atomicExpression)[qi::_val = phoenix::bind(&ExpressionParser::createNotExpression, phoenix::ref(*this), qi::_1)] | (qi::lit("-") >> atomicExpression)[qi::_val = phoenix::bind(&ExpressionParser::createMinusExpression, phoenix::ref(*this), qi::_1)];
unaryExpression.name("unary expression"); unaryExpression.name("unary expression");
multiplicationExpression = unaryExpression[qi::_val = qi::_1] >> *((qi::lit("*")[qi::_a = true] | qi::lit("/")[qi::_a = false]) >> unaryExpression[phoenix::if_(qi::_a) [qi::_val = phoenix::bind(&ExpressionParser::createMultExpression, phoenix::ref(*this), qi::_val, qi::_1)] .else_ [qi::_val = phoenix::bind(&ExpressionParser::createDivExpression, phoenix::ref(*this), qi::_val, qi::_1)]]);
powerExpression = unaryExpression[qi::_val = qi::_1] >> -(qi::lit("^") > expression)[qi::_val = phoenix::bind(&ExpressionParser::createPowerExpression, phoenix::ref(*this), qi::_val, qi::_1)];
powerExpression.name("power expression");
multiplicationExpression = powerExpression[qi::_val = qi::_1] >> *((qi::lit("*")[qi::_a = true] | qi::lit("/")[qi::_a = false]) >> powerExpression[phoenix::if_(qi::_a) [qi::_val = phoenix::bind(&ExpressionParser::createMultExpression, phoenix::ref(*this), qi::_val, qi::_1)] .else_ [qi::_val = phoenix::bind(&ExpressionParser::createDivExpression, phoenix::ref(*this), qi::_val, qi::_1)]]);
multiplicationExpression.name("multiplication expression"); multiplicationExpression.name("multiplication expression");
plusExpression = multiplicationExpression[qi::_val = qi::_1] >> *((qi::lit("+")[qi::_a = true] | qi::lit("-")[qi::_a = false]) >> multiplicationExpression)[phoenix::if_(qi::_a) [qi::_val = phoenix::bind(&ExpressionParser::createPlusExpression, phoenix::ref(*this), qi::_val, qi::_1)] .else_ [qi::_val = phoenix::bind(&ExpressionParser::createMinusExpression, phoenix::ref(*this), qi::_val, qi::_1)]]; plusExpression = multiplicationExpression[qi::_val = qi::_1] >> *((qi::lit("+")[qi::_a = true] | qi::lit("-")[qi::_a = false]) >> multiplicationExpression)[phoenix::if_(qi::_a) [qi::_val = phoenix::bind(&ExpressionParser::createPlusExpression, phoenix::ref(*this), qi::_val, qi::_1)] .else_ [qi::_val = phoenix::bind(&ExpressionParser::createMinusExpression, phoenix::ref(*this), qi::_val, qi::_1)]];
@ -69,12 +72,18 @@ namespace storm {
} }
void ExpressionParser::setIdentifierMapping(qi::symbols<char, storm::expressions::Expression> const* identifiers_) { void ExpressionParser::setIdentifierMapping(qi::symbols<char, storm::expressions::Expression> const* identifiers_) {
this->createExpressions = true;
this->identifiers_ = identifiers_;
if (identifiers_ != nullptr) {
this->createExpressions = true;
this->identifiers_ = identifiers_;
} else {
this->createExpressions = false;
this->identifiers_ = nullptr;
}
} }
void ExpressionParser::unsetIdentifierMapping() { void ExpressionParser::unsetIdentifierMapping() {
this->createExpressions = false; this->createExpressions = false;
this->identifiers_ = nullptr;
} }
void ExpressionParser::setAcceptDoubleLiterals(bool flag) { void ExpressionParser::setAcceptDoubleLiterals(bool flag) {
@ -86,7 +95,7 @@ namespace storm {
try { try {
return e1.ite(e2, e3); return e1.ite(e2, e3);
} catch (storm::exceptions::InvalidTypeException const& e) { } catch (storm::exceptions::InvalidTypeException const& e) {
LOG_THROW(false, storm::exceptions::WrongFormatException, "Parsing error in line " << get_line(qi::_3) << ": " << e.what() << ".");
LOG_THROW(false, storm::exceptions::WrongFormatException, "Parsing error in line " << get_line(qi::_3) << ": " << e.what());
} }
} else { } else {
return storm::expressions::Expression::createFalse(); return storm::expressions::Expression::createFalse();
@ -98,7 +107,7 @@ namespace storm {
try { try {
return e1.implies(e2); return e1.implies(e2);
} catch (storm::exceptions::InvalidTypeException const& e) { } catch (storm::exceptions::InvalidTypeException const& e) {
LOG_THROW(false, storm::exceptions::WrongFormatException, "Parsing error in line " << get_line(qi::_3) << ": " << e.what() << ".");
LOG_THROW(false, storm::exceptions::WrongFormatException, "Parsing error in line " << get_line(qi::_3) << ": " << e.what());
} }
} else { } else {
return storm::expressions::Expression::createFalse(); return storm::expressions::Expression::createFalse();
@ -110,7 +119,7 @@ namespace storm {
try { try {
return e1 || e2; return e1 || e2;
} catch (storm::exceptions::InvalidTypeException const& e) { } catch (storm::exceptions::InvalidTypeException const& e) {
LOG_THROW(false, storm::exceptions::WrongFormatException, "Parsing error in line " << get_line(qi::_3) << ": " << e.what() << ".");
LOG_THROW(false, storm::exceptions::WrongFormatException, "Parsing error in line " << get_line(qi::_3) << ": " << e.what());
} }
} else { } else {
return storm::expressions::Expression::createFalse(); return storm::expressions::Expression::createFalse();
@ -122,7 +131,7 @@ namespace storm {
try{ try{
return e1 && e2; return e1 && e2;
} catch (storm::exceptions::InvalidTypeException const& e) { } catch (storm::exceptions::InvalidTypeException const& e) {
LOG_THROW(false, storm::exceptions::WrongFormatException, "Parsing error in line " << get_line(qi::_3) << ": " << e.what() << ".");
LOG_THROW(false, storm::exceptions::WrongFormatException, "Parsing error in line " << get_line(qi::_3) << ": " << e.what());
} }
} else { } else {
return storm::expressions::Expression::createFalse(); return storm::expressions::Expression::createFalse();
@ -134,7 +143,7 @@ namespace storm {
try { try {
return e1 > e2; return e1 > e2;
} catch (storm::exceptions::InvalidTypeException const& e) { } catch (storm::exceptions::InvalidTypeException const& e) {
LOG_THROW(false, storm::exceptions::WrongFormatException, "Parsing error in line " << get_line(qi::_3) << ": " << e.what() << ".");
LOG_THROW(false, storm::exceptions::WrongFormatException, "Parsing error in line " << get_line(qi::_3) << ": " << e.what());
} }
} else { } else {
return storm::expressions::Expression::createFalse(); return storm::expressions::Expression::createFalse();
@ -146,7 +155,7 @@ namespace storm {
try { try {
return e1 >= e2; return e1 >= e2;
} catch (storm::exceptions::InvalidTypeException const& e) { } catch (storm::exceptions::InvalidTypeException const& e) {
LOG_THROW(false, storm::exceptions::WrongFormatException, "Parsing error in line " << get_line(qi::_3) << ": " << e.what() << ".");
LOG_THROW(false, storm::exceptions::WrongFormatException, "Parsing error in line " << get_line(qi::_3) << ": " << e.what());
} }
} else { } else {
return storm::expressions::Expression::createFalse(); return storm::expressions::Expression::createFalse();
@ -158,7 +167,7 @@ namespace storm {
try { try {
return e1 < e2; return e1 < e2;
} catch (storm::exceptions::InvalidTypeException const& e) { } catch (storm::exceptions::InvalidTypeException const& e) {
LOG_THROW(false, storm::exceptions::WrongFormatException, "Parsing error in line " << get_line(qi::_3) << ": " << e.what() << ".");
LOG_THROW(false, storm::exceptions::WrongFormatException, "Parsing error in line " << get_line(qi::_3) << ": " << e.what());
} }
} else { } else {
return storm::expressions::Expression::createFalse(); return storm::expressions::Expression::createFalse();
@ -170,7 +179,7 @@ namespace storm {
try { try {
return e1 <= e2; return e1 <= e2;
} catch (storm::exceptions::InvalidTypeException const& e) { } catch (storm::exceptions::InvalidTypeException const& e) {
LOG_THROW(false, storm::exceptions::WrongFormatException, "Parsing error in line " << get_line(qi::_3) << ": " << e.what() << ".");
LOG_THROW(false, storm::exceptions::WrongFormatException, "Parsing error in line " << get_line(qi::_3) << ": " << e.what());
} }
} else { } else {
return storm::expressions::Expression::createFalse(); return storm::expressions::Expression::createFalse();
@ -186,7 +195,7 @@ namespace storm {
return e1 == e2; return e1 == e2;
} }
} catch (storm::exceptions::InvalidTypeException const& e) { } catch (storm::exceptions::InvalidTypeException const& e) {
LOG_THROW(false, storm::exceptions::WrongFormatException, "Parsing error in line " << get_line(qi::_3) << ": " << e.what() << ".");
LOG_THROW(false, storm::exceptions::WrongFormatException, "Parsing error in line " << get_line(qi::_3) << ": " << e.what());
} }
} else { } else {
return storm::expressions::Expression::createFalse(); return storm::expressions::Expression::createFalse();
@ -196,13 +205,9 @@ namespace storm {
storm::expressions::Expression ExpressionParser::createNotEqualsExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const { storm::expressions::Expression ExpressionParser::createNotEqualsExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const {
if (this->createExpressions) { if (this->createExpressions) {
try { try {
if (e1.hasBooleanReturnType() && e2.hasBooleanReturnType()) {
return e1 ^ e2;
} else {
return e1 != e2;
}
return e1 != e2;
} catch (storm::exceptions::InvalidTypeException const& e) { } catch (storm::exceptions::InvalidTypeException const& e) {
LOG_THROW(false, storm::exceptions::WrongFormatException, "Parsing error in line " << get_line(qi::_3) << ": " << e.what() << ".");
LOG_THROW(false, storm::exceptions::WrongFormatException, "Parsing error in line " << get_line(qi::_3) << ": " << e.what());
} }
} else { } else {
return storm::expressions::Expression::createFalse(); return storm::expressions::Expression::createFalse();
@ -214,7 +219,7 @@ namespace storm {
try { try {
return e1 + e2; return e1 + e2;
} catch (storm::exceptions::InvalidTypeException const& e) { } catch (storm::exceptions::InvalidTypeException const& e) {
LOG_THROW(false, storm::exceptions::WrongFormatException, "Parsing error in line " << get_line(qi::_3) << ": " << e.what() << ".");
LOG_THROW(false, storm::exceptions::WrongFormatException, "Parsing error in line " << get_line(qi::_3) << ": " << e.what());
} }
} else { } else {
return storm::expressions::Expression::createFalse(); return storm::expressions::Expression::createFalse();
@ -226,7 +231,7 @@ namespace storm {
try { try {
return e1 - e2; return e1 - e2;
} catch (storm::exceptions::InvalidTypeException const& e) { } catch (storm::exceptions::InvalidTypeException const& e) {
LOG_THROW(false, storm::exceptions::WrongFormatException, "Parsing error in line " << get_line(qi::_3) << ": " << e.what() << ".");
LOG_THROW(false, storm::exceptions::WrongFormatException, "Parsing error in line " << get_line(qi::_3) << ": " << e.what());
} }
} else { } else {
return storm::expressions::Expression::createFalse(); return storm::expressions::Expression::createFalse();
@ -238,7 +243,19 @@ namespace storm {
try { try {
return e1 * e2; return e1 * e2;
} catch (storm::exceptions::InvalidTypeException const& e) { } catch (storm::exceptions::InvalidTypeException const& e) {
LOG_THROW(false, storm::exceptions::WrongFormatException, "Parsing error in line " << get_line(qi::_3) << ": " << e.what() << ".");
LOG_THROW(false, storm::exceptions::WrongFormatException, "Parsing error in line " << get_line(qi::_3) << ": " << e.what());
}
} else {
return storm::expressions::Expression::createFalse();
}
}
storm::expressions::Expression ExpressionParser::createPowerExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const {
if (this->createExpressions) {
try {
return e1 ^ e2;
} catch (storm::exceptions::InvalidTypeException const& e) {
LOG_THROW(false, storm::exceptions::WrongFormatException, "Parsing error in line " << get_line(qi::_3) << ": " << e.what());
} }
} else { } else {
return storm::expressions::Expression::createFalse(); return storm::expressions::Expression::createFalse();
@ -250,7 +267,7 @@ namespace storm {
try { try {
return e1 / e2; return e1 / e2;
} catch (storm::exceptions::InvalidTypeException const& e) { } catch (storm::exceptions::InvalidTypeException const& e) {
LOG_THROW(false, storm::exceptions::WrongFormatException, "Parsing error in line " << get_line(qi::_3) << ": " << e.what() << ".");
LOG_THROW(false, storm::exceptions::WrongFormatException, "Parsing error in line " << get_line(qi::_3) << ": " << e.what());
} }
} else { } else {
return storm::expressions::Expression::createFalse(); return storm::expressions::Expression::createFalse();
@ -262,7 +279,7 @@ namespace storm {
try { try {
return !e1; return !e1;
} catch (storm::exceptions::InvalidTypeException const& e) { } catch (storm::exceptions::InvalidTypeException const& e) {
LOG_THROW(false, storm::exceptions::WrongFormatException, "Parsing error in line " << get_line(qi::_3) << ": " << e.what() << ".");
LOG_THROW(false, storm::exceptions::WrongFormatException, "Parsing error in line " << get_line(qi::_3) << ": " << e.what());
} }
} else { } else {
return storm::expressions::Expression::createFalse(); return storm::expressions::Expression::createFalse();
@ -274,7 +291,7 @@ namespace storm {
try { try {
return -e1; return -e1;
} catch (storm::exceptions::InvalidTypeException const& e) { } catch (storm::exceptions::InvalidTypeException const& e) {
LOG_THROW(false, storm::exceptions::WrongFormatException, "Parsing error in line " << get_line(qi::_3) << ": " << e.what() << ".");
LOG_THROW(false, storm::exceptions::WrongFormatException, "Parsing error in line " << get_line(qi::_3) << ": " << e.what());
} }
} else { } else {
return storm::expressions::Expression::createFalse(); return storm::expressions::Expression::createFalse();
@ -308,9 +325,9 @@ namespace storm {
storm::expressions::Expression ExpressionParser::createIntegerLiteralExpression(int value) const { storm::expressions::Expression ExpressionParser::createIntegerLiteralExpression(int value) const {
if (this->createExpressions) { if (this->createExpressions) {
return storm::expressions::Expression::createFalse();
} else {
return storm::expressions::Expression::createIntegerLiteral(static_cast<int_fast64_t>(value)); return storm::expressions::Expression::createIntegerLiteral(static_cast<int_fast64_t>(value));
} else {
return storm::expressions::Expression::createFalse();
} }
} }
@ -319,7 +336,7 @@ namespace storm {
try { try {
return storm::expressions::Expression::minimum(e1, e2); return storm::expressions::Expression::minimum(e1, e2);
} catch (storm::exceptions::InvalidTypeException const& e) { } catch (storm::exceptions::InvalidTypeException const& e) {
LOG_THROW(false, storm::exceptions::WrongFormatException, "Parsing error in line " << get_line(qi::_3) << ": " << e.what() << ".");
LOG_THROW(false, storm::exceptions::WrongFormatException, "Parsing error in line " << get_line(qi::_3) << ": " << e.what());
} }
} else { } else {
return storm::expressions::Expression::createFalse(); return storm::expressions::Expression::createFalse();
@ -331,7 +348,7 @@ namespace storm {
try { try {
return storm::expressions::Expression::maximum(e1, e2); return storm::expressions::Expression::maximum(e1, e2);
} catch (storm::exceptions::InvalidTypeException const& e) { } catch (storm::exceptions::InvalidTypeException const& e) {
LOG_THROW(false, storm::exceptions::WrongFormatException, "Parsing error in line " << get_line(qi::_3) << ": " << e.what() << ".");
LOG_THROW(false, storm::exceptions::WrongFormatException, "Parsing error in line " << get_line(qi::_3) << ": " << e.what());
} }
} else { } else {
return storm::expressions::Expression::createFalse(); return storm::expressions::Expression::createFalse();
@ -343,7 +360,7 @@ namespace storm {
try { try {
return e1.floor(); return e1.floor();
} catch (storm::exceptions::InvalidTypeException const& e) { } catch (storm::exceptions::InvalidTypeException const& e) {
LOG_THROW(false, storm::exceptions::WrongFormatException, "Parsing error in line " << get_line(qi::_3) << ": " << e.what() << ".");
LOG_THROW(false, storm::exceptions::WrongFormatException, "Parsing error in line " << get_line(qi::_3) << ": " << e.what());
} }
} else { } else {
return storm::expressions::Expression::createFalse(); return storm::expressions::Expression::createFalse();
@ -355,7 +372,7 @@ namespace storm {
try { try {
return e1.ceil(); return e1.ceil();
} catch (storm::exceptions::InvalidTypeException const& e) { } catch (storm::exceptions::InvalidTypeException const& e) {
LOG_THROW(false, storm::exceptions::WrongFormatException, "Parsing error in line " << get_line(qi::_3) << ": " << e.what() << ".");
LOG_THROW(false, storm::exceptions::WrongFormatException, "Parsing error in line " << get_line(qi::_3) << ": " << e.what());
} }
} else { } else {
return storm::expressions::Expression::createFalse(); return storm::expressions::Expression::createFalse();
@ -364,11 +381,12 @@ namespace storm {
storm::expressions::Expression ExpressionParser::getIdentifierExpression(std::string const& identifier) const { storm::expressions::Expression ExpressionParser::getIdentifierExpression(std::string const& identifier) const {
if (this->createExpressions) { if (this->createExpressions) {
return storm::expressions::Expression::createFalse();
} else {
LOG_THROW(this->identifiers_ != nullptr, storm::exceptions::WrongFormatException, "Unable to substitute identifier expressions without given mapping.");
storm::expressions::Expression const* expression = this->identifiers_->find(identifier); storm::expressions::Expression const* expression = this->identifiers_->find(identifier);
LOG_THROW(expression != nullptr, storm::exceptions::WrongFormatException, "Parsing error in line " << get_line(qi::_3) << ": Undeclared identifier '" << identifier << "'."); LOG_THROW(expression != nullptr, storm::exceptions::WrongFormatException, "Parsing error in line " << get_line(qi::_3) << ": Undeclared identifier '" << identifier << "'.");
return *expression; return *expression;
} else {
return storm::expressions::Expression::createFalse();
} }
} }

2
src/parser/ExpressionParser.h

@ -66,6 +66,7 @@ namespace storm {
qi::rule<Iterator, storm::expressions::Expression(), qi::locals<bool>, Skipper> equalityExpression; qi::rule<Iterator, storm::expressions::Expression(), qi::locals<bool>, Skipper> equalityExpression;
qi::rule<Iterator, storm::expressions::Expression(), qi::locals<bool>, Skipper> plusExpression; qi::rule<Iterator, storm::expressions::Expression(), qi::locals<bool>, Skipper> plusExpression;
qi::rule<Iterator, storm::expressions::Expression(), qi::locals<bool>, Skipper> multiplicationExpression; qi::rule<Iterator, storm::expressions::Expression(), qi::locals<bool>, Skipper> multiplicationExpression;
qi::rule<Iterator, storm::expressions::Expression(), qi::locals<bool>, Skipper> powerExpression;
qi::rule<Iterator, storm::expressions::Expression(), Skipper> unaryExpression; qi::rule<Iterator, storm::expressions::Expression(), Skipper> unaryExpression;
qi::rule<Iterator, storm::expressions::Expression(), Skipper> atomicExpression; qi::rule<Iterator, storm::expressions::Expression(), Skipper> atomicExpression;
qi::rule<Iterator, storm::expressions::Expression(), Skipper> literalExpression; qi::rule<Iterator, storm::expressions::Expression(), Skipper> literalExpression;
@ -91,6 +92,7 @@ namespace storm {
storm::expressions::Expression createPlusExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const; storm::expressions::Expression createPlusExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const;
storm::expressions::Expression createMinusExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const; storm::expressions::Expression createMinusExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const;
storm::expressions::Expression createMultExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const; storm::expressions::Expression createMultExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const;
storm::expressions::Expression createPowerExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const;
storm::expressions::Expression createDivExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const; storm::expressions::Expression createDivExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const;
storm::expressions::Expression createNotExpression(storm::expressions::Expression e1) const; storm::expressions::Expression createNotExpression(storm::expressions::Expression e1) const;
storm::expressions::Expression createMinusExpression(storm::expressions::Expression e1) const; storm::expressions::Expression createMinusExpression(storm::expressions::Expression e1) const;

1
src/parser/PrismParser.cpp

@ -189,6 +189,7 @@ namespace storm {
void PrismParser::moveToSecondRun() { void PrismParser::moveToSecondRun() {
this->secondRun = true; this->secondRun = true;
this->expressionParser.setIdentifierMapping(&this->identifiers_);
} }
void PrismParser::allowDoubleLiterals(bool flag) { void PrismParser::allowDoubleLiterals(bool flag) {

5
src/storage/expressions/BinaryNumericalFunctionExpression.cpp

@ -1,4 +1,5 @@
#include <algorithm> #include <algorithm>
#include <cmath>
#include "src/storage/expressions/BinaryNumericalFunctionExpression.h" #include "src/storage/expressions/BinaryNumericalFunctionExpression.h"
#include "src/exceptions/ExceptionMacros.h" #include "src/exceptions/ExceptionMacros.h"
@ -22,6 +23,7 @@ namespace storm {
case OperatorType::Divide: return storm::expressions::OperatorType::Divide; break; case OperatorType::Divide: return storm::expressions::OperatorType::Divide; break;
case OperatorType::Min: return storm::expressions::OperatorType::Min; break; case OperatorType::Min: return storm::expressions::OperatorType::Min; break;
case OperatorType::Max: return storm::expressions::OperatorType::Max; break; case OperatorType::Max: return storm::expressions::OperatorType::Max; break;
case OperatorType::Power: return storm::expressions::OperatorType::Power; break;
} }
} }
@ -37,6 +39,7 @@ namespace storm {
case OperatorType::Divide: return firstOperandEvaluation / secondOperandEvaluation; break; case OperatorType::Divide: return firstOperandEvaluation / secondOperandEvaluation; break;
case OperatorType::Min: return std::min(firstOperandEvaluation, secondOperandEvaluation); break; case OperatorType::Min: return std::min(firstOperandEvaluation, secondOperandEvaluation); break;
case OperatorType::Max: return std::max(firstOperandEvaluation, secondOperandEvaluation); break; case OperatorType::Max: return std::max(firstOperandEvaluation, secondOperandEvaluation); break;
case OperatorType::Power: return static_cast<int_fast64_t>(std::pow(firstOperandEvaluation, secondOperandEvaluation)); break;
} }
} }
@ -52,6 +55,7 @@ namespace storm {
case OperatorType::Divide: return static_cast<double>(firstOperandEvaluation / secondOperandEvaluation); break; case OperatorType::Divide: return static_cast<double>(firstOperandEvaluation / secondOperandEvaluation); break;
case OperatorType::Min: return static_cast<double>(std::min(firstOperandEvaluation, secondOperandEvaluation)); break; case OperatorType::Min: return static_cast<double>(std::min(firstOperandEvaluation, secondOperandEvaluation)); break;
case OperatorType::Max: return static_cast<double>(std::max(firstOperandEvaluation, secondOperandEvaluation)); break; case OperatorType::Max: return static_cast<double>(std::max(firstOperandEvaluation, secondOperandEvaluation)); break;
case OperatorType::Power: return std::pow(firstOperandEvaluation, secondOperandEvaluation); break;
} }
} }
@ -79,6 +83,7 @@ namespace storm {
case OperatorType::Divide: stream << *this->getFirstOperand() << " / " << *this->getSecondOperand(); break; case OperatorType::Divide: stream << *this->getFirstOperand() << " / " << *this->getSecondOperand(); break;
case OperatorType::Min: stream << "min(" << *this->getFirstOperand() << ", " << *this->getSecondOperand() << ")"; break; case OperatorType::Min: stream << "min(" << *this->getFirstOperand() << ", " << *this->getSecondOperand() << ")"; break;
case OperatorType::Max: stream << "max(" << *this->getFirstOperand() << ", " << *this->getSecondOperand() << ")"; break; case OperatorType::Max: stream << "max(" << *this->getFirstOperand() << ", " << *this->getSecondOperand() << ")"; break;
case OperatorType::Power: stream << *this->getFirstOperand() << " ^ " << *this->getSecondOperand(); break;
} }
stream << ")"; stream << ")";
} }

2
src/storage/expressions/BinaryNumericalFunctionExpression.h

@ -11,7 +11,7 @@ namespace storm {
/*! /*!
* An enum type specifying the different operators applicable. * An enum type specifying the different operators applicable.
*/ */
enum class OperatorType {Plus, Minus, Times, Divide, Min, Max};
enum class OperatorType {Plus, Minus, Times, Divide, Min, Max, Power};
/*! /*!
* Constructs a binary numerical function expression with the given return type, operands and operator. * Constructs a binary numerical function expression with the given return type, operands and operator.

12
src/storage/expressions/Expression.cpp

@ -196,8 +196,8 @@ namespace storm {
} }
Expression Expression::operator^(Expression const& other) const { Expression Expression::operator^(Expression const& other) const {
LOG_THROW(this->hasBooleanReturnType() && other.hasBooleanReturnType(), storm::exceptions::InvalidTypeException, "Operator '^' requires boolean operands.");
return Expression(std::shared_ptr<BaseExpression>(new BinaryBooleanFunctionExpression(ExpressionReturnType::Bool, this->getBaseExpressionPointer(), other.getBaseExpressionPointer(), BinaryBooleanFunctionExpression::OperatorType::Xor)));
LOG_THROW(this->hasNumericalReturnType() && other.hasNumericalReturnType(), storm::exceptions::InvalidTypeException, "Operator '^' requires numerical operands.");
return Expression(std::shared_ptr<BaseExpression>(new BinaryNumericalFunctionExpression(this->getReturnType() == ExpressionReturnType::Int && other.getReturnType() == ExpressionReturnType::Int ? ExpressionReturnType::Int : ExpressionReturnType::Double, this->getBaseExpressionPointer(), other.getBaseExpressionPointer(), BinaryNumericalFunctionExpression::OperatorType::Power)));
} }
Expression Expression::operator&&(Expression const& other) const { Expression Expression::operator&&(Expression const& other) const {
@ -221,8 +221,12 @@ namespace storm {
} }
Expression Expression::operator!=(Expression const& other) const { Expression Expression::operator!=(Expression const& other) const {
LOG_THROW(this->hasNumericalReturnType() && other.hasNumericalReturnType(), storm::exceptions::InvalidTypeException, "Operator '!=' requires numerical operands.");
return Expression(std::shared_ptr<BaseExpression>(new BinaryRelationExpression(ExpressionReturnType::Bool, this->getBaseExpressionPointer(), other.getBaseExpressionPointer(), BinaryRelationExpression::RelationType::NotEqual)));
LOG_THROW((this->hasNumericalReturnType() && other.hasNumericalReturnType()) || (this->hasBooleanReturnType() && other.hasBooleanReturnType()), storm::exceptions::InvalidTypeException, "Operator '!=' requires operands of equal type.");
if (this->hasNumericalReturnType() && other.hasNumericalReturnType()) {
return Expression(std::shared_ptr<BaseExpression>(new BinaryRelationExpression(ExpressionReturnType::Bool, this->getBaseExpressionPointer(), other.getBaseExpressionPointer(), BinaryRelationExpression::RelationType::NotEqual)));
} else {
return Expression(std::shared_ptr<BaseExpression>(new BinaryBooleanFunctionExpression(ExpressionReturnType::Bool, this->getBaseExpressionPointer(), other.getBaseExpressionPointer(), BinaryBooleanFunctionExpression::OperatorType::Xor)));
}
} }
Expression Expression::operator>(Expression const& other) const { Expression Expression::operator>(Expression const& other) const {

1
src/storage/expressions/OperatorType.h

@ -16,6 +16,7 @@ namespace storm {
Divide, Divide,
Min, Min,
Max, Max,
Power,
Equal, Equal,
NotEqual, NotEqual,
Less, Less,

1
test/functional/parser/PrismParserTest.cpp

@ -4,6 +4,7 @@
TEST(PrismParser, StandardModelTest) { TEST(PrismParser, StandardModelTest) {
storm::prism::Program result; storm::prism::Program result;
result = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/parser/prism/coin2.nm");
EXPECT_NO_THROW(result = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/parser/prism/coin2.nm")); EXPECT_NO_THROW(result = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/parser/prism/coin2.nm"));
EXPECT_NO_THROW(result = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/parser/prism/crowds5_5.pm")); EXPECT_NO_THROW(result = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/parser/prism/crowds5_5.pm"));
EXPECT_NO_THROW(result = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/parser/prism/csma2_2.nm")); EXPECT_NO_THROW(result = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/parser/prism/csma2_2.nm"));

12
test/functional/storage/ExpressionTest.cpp

@ -223,10 +223,10 @@ TEST(Expression, OperatorTest) {
ASSERT_NO_THROW(tempExpression = boolVarExpression.iff(boolVarExpression)); ASSERT_NO_THROW(tempExpression = boolVarExpression.iff(boolVarExpression));
EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Bool); EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Bool);
ASSERT_THROW(tempExpression = trueExpression ^ piExpression, storm::exceptions::InvalidTypeException);
ASSERT_NO_THROW(tempExpression = trueExpression ^ falseExpression);
ASSERT_THROW(tempExpression = trueExpression != piExpression, storm::exceptions::InvalidTypeException);
ASSERT_NO_THROW(tempExpression = trueExpression != falseExpression);
EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Bool); EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Bool);
ASSERT_NO_THROW(tempExpression = boolVarExpression ^ boolVarExpression);
ASSERT_NO_THROW(tempExpression = boolVarExpression != boolVarExpression);
EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Bool); EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Bool);
ASSERT_THROW(tempExpression = trueExpression.floor(), storm::exceptions::InvalidTypeException); ASSERT_THROW(tempExpression = trueExpression.floor(), storm::exceptions::InvalidTypeException);
@ -240,6 +240,12 @@ TEST(Expression, OperatorTest) {
EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Int); EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Int);
ASSERT_NO_THROW(tempExpression = doubleVarExpression.ceil()); ASSERT_NO_THROW(tempExpression = doubleVarExpression.ceil());
EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Int); EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Int);
ASSERT_THROW(tempExpression = trueExpression ^ piExpression, storm::exceptions::InvalidTypeException);
ASSERT_NO_THROW(tempExpression = threeExpression ^ threeExpression);
EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Int);
ASSERT_NO_THROW(tempExpression = intVarExpression ^ doubleVarExpression);
EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Double);
} }
TEST(Expression, SubstitutionTest) { TEST(Expression, SubstitutionTest) {

Loading…
Cancel
Save