Browse Source

Improved performance of the expression parser a bit more.

Former-commit-id: 7a0ae116c9
tempestpy_adaptions
dehnert 11 years ago
parent
commit
7c5603de3e
  1. 8
      src/exceptions/ExceptionMacros.h
  2. 123
      src/parser/ExpressionParser.cpp
  3. 55
      src/parser/ExpressionParser.h
  4. 33
      src/storage/expressions/OperatorType.cpp
  5. 4
      src/storage/expressions/OperatorType.h
  6. 3
      test/functional/parser/PrismParserTest.cpp

8
src/exceptions/ExceptionMacros.h

@ -22,10 +22,10 @@ extern log4cplus::Logger logger;
#define LOG_THROW(cond, exception, message) \
{ \
if (!(cond)) { \
LOG4CPLUS_ERROR(logger, message); \
throw exception() << message; \
} \
if (!(cond)) { \
LOG4CPLUS_ERROR(logger, message); \
throw exception() << message; \
} \
} while (false)
#endif /* STORM_EXCEPTIONS_EXCEPTIONMACROS_H_ */

123
src/parser/ExpressionParser.cpp

@ -5,26 +5,26 @@
namespace storm {
namespace parser {
ExpressionParser::ExpressionParser(qi::symbols<char, uint_fast64_t> const& invalidIdentifiers_) : ExpressionParser::base_type(expression), createExpressions(false), acceptDoubleLiterals(true), identifiers_(nullptr), invalidIdentifiers_(invalidIdentifiers_) {
ExpressionParser::ExpressionParser(qi::symbols<char, uint_fast64_t> const& invalidIdentifiers_) : ExpressionParser::base_type(expression), orOperator_(), andOperator_(), equalityOperator_(), relationalOperator_(), plusOperator_(), multiplicationOperator_(), powerOperator_(), unaryOperator_(), floorCeilOperator_(), minMaxOperator_(), trueFalse_(), createExpressions(false), acceptDoubleLiterals(true), identifiers_(nullptr), invalidIdentifiers_(invalidIdentifiers_) {
identifier %= qi::as_string[qi::raw[qi::lexeme[((qi::alpha | qi::char_('_')) >> *(qi::alnum | qi::char_('_')))]]][qi::_pass = phoenix::bind(&ExpressionParser::isValidIdentifier, phoenix::ref(*this), qi::_1)];
identifier.name("identifier");
floorCeilExpression = ((qi::lit("floor")[qi::_a = true] | qi::lit("ceil")[qi::_a = false]) >> qi::lit("(") >> plusExpression >> qi::lit(")"))[phoenix::if_(qi::_a) [qi::_val = phoenix::bind(&ExpressionParser::createFloorExpression, phoenix::ref(*this), qi::_1)] .else_ [qi::_val = phoenix::bind(&ExpressionParser::createCeilExpression, phoenix::ref(*this), qi::_1)]];
floorCeilExpression = ((floorCeilOperator_ >> qi::lit("(")) > plusExpression > qi::lit(")"))[qi::_val = phoenix::bind(&ExpressionParser::createFloorCeilExpression, phoenix::ref(*this), qi::_1, qi::_2)];
floorCeilExpression.name("floor/ceil expression");
minMaxExpression = ((qi::lit("min")[qi::_a = true] | qi::lit("max")[qi::_a = false]) >> qi::lit("(") >> plusExpression >> qi::lit(",") >> plusExpression >> qi::lit(")"))[phoenix::if_(qi::_a) [qi::_val = phoenix::bind(&ExpressionParser::createMinimumExpression, phoenix::ref(*this), qi::_1, qi::_2)] .else_ [qi::_val = phoenix::bind(&ExpressionParser::createMaximumExpression, phoenix::ref(*this), qi::_1, qi::_2)]];
minMaxExpression = ((minMaxOperator_ >> qi::lit("(")) > plusExpression > qi::lit(",") > plusExpression > qi::lit(")"))[qi::_val = phoenix::bind(&ExpressionParser::createMinimumMaximumExpression, phoenix::ref(*this), qi::_2, qi::_1, qi::_3)];
minMaxExpression.name("min/max expression");
identifierExpression = identifier[qi::_val = phoenix::bind(&ExpressionParser::getIdentifierExpression, phoenix::ref(*this), qi::_1)];
identifierExpression.name("identifier expression");
literalExpression = qi::lit("true")[qi::_val = phoenix::bind(&ExpressionParser::createTrueExpression, phoenix::ref(*this))] | qi::lit("false")[qi::_val = phoenix::bind(&ExpressionParser::createFalseExpression, phoenix::ref(*this))] | strict_double[qi::_val = phoenix::bind(&ExpressionParser::createDoubleLiteralExpression, phoenix::ref(*this), qi::_1, qi::_pass)] | qi::int_[qi::_val = phoenix::bind(&ExpressionParser::createIntegerLiteralExpression, phoenix::ref(*this), qi::_1)];
literalExpression = trueFalse_[qi::_val = qi::_1] | strict_double[qi::_val = phoenix::bind(&ExpressionParser::createDoubleLiteralExpression, phoenix::ref(*this), qi::_1, qi::_pass)] | qi::int_[qi::_val = phoenix::bind(&ExpressionParser::createIntegerLiteralExpression, phoenix::ref(*this), qi::_1)];
literalExpression.name("literal expression");
atomicExpression = minMaxExpression | floorCeilExpression | qi::lit("(") >> expression >> qi::lit(")") | literalExpression | identifierExpression;
atomicExpression = floorCeilExpression | minMaxExpression | (qi::lit("(") >> expression >> qi::lit(")")) | literalExpression | identifierExpression;
atomicExpression.name("atomic expression");
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 = (-unaryOperator_ >> atomicExpression)[qi::_val = phoenix::bind(&ExpressionParser::createUnaryExpression, phoenix::ref(*this), qi::_1, qi::_2)];
unaryExpression.name("unary expression");
powerExpression = unaryExpression[qi::_val = qi::_1] > -(powerOperator_ > expression)[qi::_val = phoenix::bind(&ExpressionParser::createPowerExpression, phoenix::ref(*this), qi::_val, qi::_1, qi::_2)];
@ -97,9 +97,8 @@ namespace storm {
} catch (storm::exceptions::InvalidTypeException const& e) {
LOG_THROW(false, storm::exceptions::WrongFormatException, "Parsing error in line " << get_line(qi::_3) << ": " << e.what());
}
} else {
return storm::expressions::Expression::createFalse();
}
return storm::expressions::Expression::createFalse();
}
storm::expressions::Expression ExpressionParser::createOrExpression(storm::expressions::Expression const& e1, storm::expressions::OperatorType const& operatorType, storm::expressions::Expression const& e2) const {
@ -113,9 +112,8 @@ namespace storm {
} catch (storm::exceptions::InvalidTypeException const& e) {
LOG_THROW(false, storm::exceptions::WrongFormatException, "Parsing error in line " << get_line(qi::_3) << ": " << e.what());
}
} else {
return storm::expressions::Expression::createFalse();
}
return storm::expressions::Expression::createFalse();
}
storm::expressions::Expression ExpressionParser::createAndExpression(storm::expressions::Expression const& e1, storm::expressions::OperatorType const& operatorType, storm::expressions::Expression const& e2) const {
@ -128,9 +126,8 @@ namespace storm {
} catch (storm::exceptions::InvalidTypeException const& e) {
LOG_THROW(false, storm::exceptions::WrongFormatException, "Parsing error in line " << get_line(qi::_3) << ": " << e.what());
}
} else {
return storm::expressions::Expression::createFalse();
}
return storm::expressions::Expression::createFalse();
}
storm::expressions::Expression ExpressionParser::createRelationalExpression(storm::expressions::Expression const& e1, storm::expressions::OperatorType const& operatorType, storm::expressions::Expression const& e2) const {
@ -146,9 +143,8 @@ namespace storm {
} catch (storm::exceptions::InvalidTypeException const& e) {
LOG_THROW(false, storm::exceptions::WrongFormatException, "Parsing error in line " << get_line(qi::_3) << ": " << e.what());
}
} else {
return storm::expressions::Expression::createFalse();
}
return storm::expressions::Expression::createFalse();
}
storm::expressions::Expression ExpressionParser::createEqualsExpression(storm::expressions::Expression const& e1, storm::expressions::OperatorType const& operatorType, storm::expressions::Expression const& e2) const {
@ -162,9 +158,8 @@ namespace storm {
} catch (storm::exceptions::InvalidTypeException const& e) {
LOG_THROW(false, storm::exceptions::WrongFormatException, "Parsing error in line " << get_line(qi::_3) << ": " << e.what());
}
} else {
return storm::expressions::Expression::createFalse();
}
return storm::expressions::Expression::createFalse();
}
storm::expressions::Expression ExpressionParser::createPlusExpression(storm::expressions::Expression const& e1, storm::expressions::OperatorType const& operatorType, storm::expressions::Expression const& e2) const {
@ -178,9 +173,8 @@ namespace storm {
} catch (storm::exceptions::InvalidTypeException const& e) {
LOG_THROW(false, storm::exceptions::WrongFormatException, "Parsing error in line " << get_line(qi::_3) << ": " << e.what());
}
} else {
return storm::expressions::Expression::createFalse();
}
return storm::expressions::Expression::createFalse();
}
storm::expressions::Expression ExpressionParser::createMultExpression(storm::expressions::Expression const& e1, storm::expressions::OperatorType const& operatorType, storm::expressions::Expression const& e2) const {
@ -194,9 +188,8 @@ namespace storm {
} catch (storm::exceptions::InvalidTypeException const& e) {
LOG_THROW(false, storm::exceptions::WrongFormatException, "Parsing error in line " << get_line(qi::_3) << ": " << e.what());
}
} else {
return storm::expressions::Expression::createFalse();
}
return storm::expressions::Expression::createFalse();
}
storm::expressions::Expression ExpressionParser::createPowerExpression(storm::expressions::Expression const& e1, storm::expressions::OperatorType const& operatorType, storm::expressions::Expression const& e2) const {
@ -209,47 +202,29 @@ namespace storm {
} catch (storm::exceptions::InvalidTypeException const& e) {
LOG_THROW(false, storm::exceptions::WrongFormatException, "Parsing error in line " << get_line(qi::_3) << ": " << e.what());
}
} else {
return storm::expressions::Expression::createFalse();
}
return storm::expressions::Expression::createFalse();
}
storm::expressions::Expression ExpressionParser::createNotExpression(storm::expressions::Expression e1) const {
if (this->createExpressions) {
try {
return !e1;
} catch (storm::exceptions::InvalidTypeException const& e) {
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::createMinusExpression(storm::expressions::Expression e1) const {
storm::expressions::Expression ExpressionParser::createUnaryExpression(boost::optional<storm::expressions::OperatorType> const& operatorType, storm::expressions::Expression const& e1) const {
if (this->createExpressions) {
try {
return -e1;
if (operatorType) {
switch (operatorType.get()) {
case storm::expressions::OperatorType::Not: return !e1; break;
case storm::expressions::OperatorType::Minus: return -e1; break;
default: LOG_ASSERT(false, "Invalid operation."); break;
}
} else {
return e1;
}
} catch (storm::exceptions::InvalidTypeException const& e) {
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::createTrueExpression() const {
if (this->createExpressions) {
return storm::expressions::Expression::createTrue();
} else {
return storm::expressions::Expression::createFalse();
}
}
storm::expressions::Expression ExpressionParser::createFalseExpression() const {
return storm::expressions::Expression::createFalse();
}
storm::expressions::Expression ExpressionParser::createDoubleLiteralExpression(double value, bool& pass) const {
// If we are not supposed to accept double expressions, we reject it by setting pass to false.
if (!this->acceptDoubleLiterals) {
@ -271,52 +246,34 @@ namespace storm {
}
}
storm::expressions::Expression ExpressionParser::createMinimumExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const {
if (this->createExpressions) {
try {
return storm::expressions::Expression::minimum(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 {
return storm::expressions::Expression::createFalse();
}
}
storm::expressions::Expression ExpressionParser::createMaximumExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const {
if (this->createExpressions) {
try {
return storm::expressions::Expression::maximum(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 {
return storm::expressions::Expression::createFalse();
}
}
storm::expressions::Expression ExpressionParser::createFloorExpression(storm::expressions::Expression e1) const {
storm::expressions::Expression ExpressionParser::createMinimumMaximumExpression(storm::expressions::Expression const& e1, storm::expressions::OperatorType const& operatorType, storm::expressions::Expression const& e2) const {
if (this->createExpressions) {
try {
return e1.floor();
switch (operatorType) {
case storm::expressions::OperatorType::Min: return storm::expressions::Expression::minimum(e1, e2); break;
case storm::expressions::OperatorType::Max: return storm::expressions::Expression::maximum(e1, e2); break;
default: LOG_ASSERT(false, "Invalid operation."); break;
}
} catch (storm::exceptions::InvalidTypeException const& e) {
LOG_THROW(false, storm::exceptions::WrongFormatException, "Parsing error in line " << get_line(qi::_3) << ": " << e.what());
}
} else {
return storm::expressions::Expression::createFalse();
}
return storm::expressions::Expression::createFalse();
}
storm::expressions::Expression ExpressionParser::createCeilExpression(storm::expressions::Expression e1) const {
storm::expressions::Expression ExpressionParser::createFloorCeilExpression(storm::expressions::OperatorType const& operatorType, storm::expressions::Expression const& e1) const {
if (this->createExpressions) {
try {
return e1.ceil();
switch (operatorType) {
case storm::expressions::OperatorType::Floor: return e1.floor(); break;
case storm::expressions::OperatorType::Ceil: return e1.ceil(); break;
default: LOG_ASSERT(false, "Invalid operation."); break;
}
} catch (storm::exceptions::InvalidTypeException const& e) {
LOG_THROW(false, storm::exceptions::WrongFormatException, "Parsing error in line " << get_line(qi::_3) << ": " << e.what());
}
} else {
return storm::expressions::Expression::createFalse();
}
return storm::expressions::Expression::createFalse();
}
storm::expressions::Expression ExpressionParser::getIdentifierExpression(std::string const& identifier) const {

55
src/parser/ExpressionParser.h

@ -120,6 +120,50 @@ namespace storm {
// A parser used for recognizing the operators at the "power" precedence level.
powerOperatorStruct powerOperator_;
struct unaryOperatorStruct : qi::symbols<char, storm::expressions::OperatorType> {
unaryOperatorStruct() {
add
("!", storm::expressions::OperatorType::Not)
("-", storm::expressions::OperatorType::Minus);
}
};
// A parser used for recognizing the operators at the "unary" precedence level.
unaryOperatorStruct unaryOperator_;
struct floorCeilOperatorStruct : qi::symbols<char, storm::expressions::OperatorType> {
floorCeilOperatorStruct() {
add
("floor", storm::expressions::OperatorType::Floor)
("ceil", storm::expressions::OperatorType::Ceil);
}
};
// A parser used for recognizing the operators at the "floor/ceil" precedence level.
floorCeilOperatorStruct floorCeilOperator_;
struct minMaxOperatorStruct : qi::symbols<char, storm::expressions::OperatorType> {
minMaxOperatorStruct() {
add
("min", storm::expressions::OperatorType::Min)
("max", storm::expressions::OperatorType::Max);
}
};
// A parser used for recognizing the operators at the "min/max" precedence level.
minMaxOperatorStruct minMaxOperator_;
struct trueFalseOperatorStruct : qi::symbols<char, storm::expressions::Expression> {
trueFalseOperatorStruct() {
add
("true", storm::expressions::Expression::createTrue())
("false", storm::expressions::Expression::createFalse());
}
};
// A parser used for recognizing the literals true and false.
trueFalseOperatorStruct trueFalse_;
// A flag that indicates whether expressions should actually be generated or just a syntax check shall be
// performed.
bool createExpressions;
@ -164,16 +208,11 @@ namespace storm {
storm::expressions::Expression createPlusExpression(storm::expressions::Expression const& e1, storm::expressions::OperatorType const& operatorType, storm::expressions::Expression const& e2) const;
storm::expressions::Expression createMultExpression(storm::expressions::Expression const& e1, storm::expressions::OperatorType const& operatorType, storm::expressions::Expression const& e2) const;
storm::expressions::Expression createPowerExpression(storm::expressions::Expression const& e1, storm::expressions::OperatorType const& operatorType, storm::expressions::Expression const& e2) const;
storm::expressions::Expression createNotExpression(storm::expressions::Expression e1) const;
storm::expressions::Expression createMinusExpression(storm::expressions::Expression e1) const;
storm::expressions::Expression createTrueExpression() const;
storm::expressions::Expression createFalseExpression() const;
storm::expressions::Expression createUnaryExpression(boost::optional<storm::expressions::OperatorType> const& operatorType, storm::expressions::Expression const& e1) const;
storm::expressions::Expression createDoubleLiteralExpression(double value, bool& pass) const;
storm::expressions::Expression createIntegerLiteralExpression(int value) const;
storm::expressions::Expression createMinimumExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const;
storm::expressions::Expression createMaximumExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const;
storm::expressions::Expression createFloorExpression(storm::expressions::Expression e1) const;
storm::expressions::Expression createCeilExpression(storm::expressions::Expression e1) const;
storm::expressions::Expression createMinimumMaximumExpression(storm::expressions::Expression const& e1, storm::expressions::OperatorType const& operatorType, storm::expressions::Expression const& e2) const;
storm::expressions::Expression createFloorCeilExpression(storm::expressions::OperatorType const& operatorType, storm::expressions::Expression const& e1) const;
storm::expressions::Expression getIdentifierExpression(std::string const& identifier) const;
bool isValidIdentifier(std::string const& identifier);

33
src/storage/expressions/OperatorType.cpp

@ -0,0 +1,33 @@
#include "src/storage/expressions/OperatorType.h"
namespace storm {
namespace expressions {
std::ostream& operator<<(std::ostream& stream, OperatorType const& operatorType) {
switch (operatorType) {
case OperatorType::And: stream << "&"; break;
case OperatorType::Or: stream << "|"; break;
case OperatorType::Xor: stream << "!="; break;
case OperatorType::Implies: stream << "=>"; break;
case OperatorType::Iff: stream << "<=>"; break;
case OperatorType::Plus: stream << "+"; break;
case OperatorType::Minus: stream << "-"; break;
case OperatorType::Times: stream << "*"; break;
case OperatorType::Divide: stream << "/"; break;
case OperatorType::Min: stream << "min"; break;
case OperatorType::Max: stream << "max"; break;
case OperatorType::Power: stream << "^"; break;
case OperatorType::Equal: stream << "="; break;
case OperatorType::NotEqual: stream << "!="; break;
case OperatorType::Less: stream << "<"; break;
case OperatorType::LessOrEqual: stream << "<="; break;
case OperatorType::Greater: stream << ">"; break;
case OperatorType::GreaterOrEqual: stream << ">="; break;
case OperatorType::Not: stream << "!"; break;
case OperatorType::Floor: stream << "floor"; break;
case OperatorType::Ceil: stream << "ceil"; break;
case OperatorType::Ite: stream << "ite"; break;
}
return stream;
}
}
}

4
src/storage/expressions/OperatorType.h

@ -1,6 +1,8 @@
#ifndef STORM_STORAGE_EXPRESSIONS_OPERATORTYPE_H_
#define STORM_STORAGE_EXPRESSIONS_OPERATORTYPE_H_
#include <ostream>
namespace storm {
namespace expressions {
// An enum representing all possible operator types.
@ -28,6 +30,8 @@ namespace storm {
Ceil,
Ite
};
std::ostream& operator<<(std::ostream& stream, OperatorType const& operatorType);
}
}

3
test/functional/parser/PrismParserTest.cpp

@ -94,7 +94,8 @@ TEST(PrismParser, ComplexTest) {
endrewards)";
storm::prism::Program result;
result = storm::parser::PrismParser::parseFromString(testInput, "testfile");
result = storm::parser::PrismParser::parseFromString(testInput, "testfile");
EXPECT_NO_THROW(result = storm::parser::PrismParser::parseFromString(testInput, "testfile"));
EXPECT_EQ(storm::prism::Program::ModelType::MA, result.getModelType());
EXPECT_EQ(3, result.getNumberOfModules());
EXPECT_EQ(2, result.getNumberOfRewardModels());

Loading…
Cancel
Save