Storm
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
ExpressionParser.cpp
Go to the documentation of this file.
5
9
11
12namespace boost {
13namespace spirit {
14namespace traits {
15template<>
16bool scale(int exp, storm::RationalNumber& r, storm::RationalNumber acc) {
17 if (exp >= 0) {
18 r = acc * storm::utility::pow(storm::RationalNumber(10), static_cast<uint_fast64_t>(exp));
19 } else {
20 r = acc / storm::utility::pow(storm::RationalNumber(10), static_cast<uint_fast64_t>(-exp));
21 }
22 return true;
23}
24
25#if BOOST_VERSION < 107000
26template<>
27bool is_equal_to_one(storm::RationalNumber const& value) {
28 return storm::utility::isOne(value);
29}
30#endif
31
32template<>
33storm::RationalNumber negate(bool neg, storm::RationalNumber const& number) {
34 return neg ? storm::RationalNumber(-number) : number;
35}
36} // namespace traits
37} // namespace spirit
38} // namespace boost
39
40namespace storm {
41namespace parser {
42ExpressionParser::ExpressionParser(storm::expressions::ExpressionManager const& manager, qi::symbols<char, uint_fast64_t> const& invalidIdentifiers_,
43 bool enableErrorHandling, bool allowBacktracking)
44 : ExpressionParser::base_type(expression),
45 orOperator_(),
46 andOperator_(),
47 equalityOperator_(),
48 relationalOperator_(),
49 plusOperator_(),
50 multiplicationOperator_(),
51 infixPowerModuloOperator_(),
52 unaryOperator_(),
53 floorCeilOperator_(),
54 minMaxOperator_(),
55 prefixPowerModuloLogarithmOperator_(),
56 invalidIdentifiers_(invalidIdentifiers_) {
57 expressionCreator = std::make_unique<ExpressionCreator>(manager);
58
59 identifier %= qi::as_string[qi::raw[qi::lexeme[((qi::alpha | qi::char_('_') | qi::char_('.')) >> *(qi::alnum | qi::char_('_')))]]]
60 [qi::_pass = phoenix::bind(&ExpressionParser::isValidIdentifier, phoenix::ref(*this), qi::_1)];
61 identifier.name("identifier");
62
63 if (allowBacktracking) {
64 predicateExpression =
65 ((predicateOperator_ >> qi::lit("(")) >> (expression % qi::lit(",")) >>
66 qi::lit(
67 ")"))[qi::_val = phoenix::bind(&ExpressionCreator::createPredicateExpression, phoenix::ref(*expressionCreator), qi::_1, qi::_2, qi::_pass)];
68 } else {
69 predicateExpression =
70 ((predicateOperator_ >> qi::lit("(")) > (expression % qi::lit(",")) >
71 qi::lit(
72 ")"))[qi::_val = phoenix::bind(&ExpressionCreator::createPredicateExpression, phoenix::ref(*expressionCreator), qi::_1, qi::_2, qi::_pass)];
73 }
74 predicateExpression.name("predicate expression");
75
76 if (allowBacktracking) {
77 floorCeilExpression =
78 ((floorCeilOperator_ >> qi::lit("(")) >> expression >>
79 qi::lit(
80 ")"))[qi::_val = phoenix::bind(&ExpressionCreator::createFloorCeilExpression, phoenix::ref(*expressionCreator), qi::_1, qi::_2, qi::_pass)];
81 } else {
82 floorCeilExpression =
83 ((floorCeilOperator_ >> qi::lit("(")) > expression >
84 qi::lit(
85 ")"))[qi::_val = phoenix::bind(&ExpressionCreator::createFloorCeilExpression, phoenix::ref(*expressionCreator), qi::_1, qi::_2, qi::_pass)];
86 }
87 floorCeilExpression.name("floor/ceil expression");
88
89 if (allowBacktracking) {
90 roundExpression =
91 ((qi::lit("round") >> qi::lit("(")) >> expression >>
92 qi::lit(")"))[qi::_val = phoenix::bind(&ExpressionCreator::createRoundExpression, phoenix::ref(*expressionCreator), qi::_1, qi::_pass)];
93 } else {
94 roundExpression =
95 ((qi::lit("round") >> qi::lit("(")) > expression >
96 qi::lit(")"))[qi::_val = phoenix::bind(&ExpressionCreator::createRoundExpression, phoenix::ref(*expressionCreator), qi::_1, qi::_pass)];
97 }
98 roundExpression.name("round expression");
99
100 if (allowBacktracking) {
101 minMaxExpression =
102 ((minMaxOperator_[qi::_a = qi::_1] >> qi::lit("(")) >> expression[qi::_val = qi::_1] >>
103 +(qi::lit(",") >> expression)[qi::_b = phoenix::bind(&ExpressionCreator::createMinimumMaximumExpression, phoenix::ref(*expressionCreator),
104 qi::_val, qi::_a, qi::_1, qi::_pass)][qi::_val = qi::_b]) >>
105 qi::lit(")");
106 } else {
107 minMaxExpression =
108 ((minMaxOperator_[qi::_a = qi::_1] >> qi::lit("(")) > expression[qi::_val = qi::_1] >
109 +(qi::lit(",") > expression)[qi::_val = phoenix::bind(&ExpressionCreator::createMinimumMaximumExpression, phoenix::ref(*expressionCreator),
110 qi::_val, qi::_a, qi::_1, qi::_pass)]) > qi::lit(")");
111 }
112 minMaxExpression.name("min/max expression");
113
114 if (allowBacktracking) {
115 prefixPowerModuloLogarithmExpression =
116 ((prefixPowerModuloLogarithmOperator_ >> qi::lit("(")) >> expression >> qi::lit(",") >> expression >>
117 qi::lit(")"))[qi::_val = phoenix::bind(&ExpressionCreator::createPowerModuloLogarithmExpression, phoenix::ref(*expressionCreator), qi::_2, qi::_1,
118 qi::_3, qi::_pass)] |
119 (qi::lit("func") >> qi::lit("(") >> prefixPowerModuloLogarithmOperator_ >> qi::lit(",") >> expression >> qi::lit(",") >> expression >>
120 qi::lit(")"))[qi::_val = phoenix::bind(&ExpressionCreator::createPowerModuloLogarithmExpression, phoenix::ref(*expressionCreator), qi::_2, qi::_1,
121 qi::_3, qi::_pass)];
122 } else {
123 prefixPowerModuloLogarithmExpression =
124 ((prefixPowerModuloLogarithmOperator_ >> qi::lit("(")) > expression > qi::lit(",") > expression >
125 qi::lit(")"))[qi::_val = phoenix::bind(&ExpressionCreator::createPowerModuloLogarithmExpression, phoenix::ref(*expressionCreator), qi::_2, qi::_1,
126 qi::_3, qi::_pass)] |
127 ((qi::lit("func") >> qi::lit("(")) > prefixPowerModuloLogarithmOperator_ > qi::lit(",") > expression > qi::lit(",") > expression >
128 qi::lit(")"))[qi::_val = phoenix::bind(&ExpressionCreator::createPowerModuloLogarithmExpression, phoenix::ref(*expressionCreator), qi::_2, qi::_1,
129 qi::_3, qi::_pass)];
130 }
131 prefixPowerModuloLogarithmExpression.name("(prefix) power/modulo/logarithm expression");
132
133 identifierExpression =
134 identifier[qi::_val = phoenix::bind(&ExpressionCreator::getIdentifierExpression, phoenix::ref(*expressionCreator), qi::_1, qi::_pass)];
135 identifierExpression.name("identifier expression");
136
137 // Integer literals. We Handle 64-bit overflows with a nice error message, while silently rejecting non-integer inputs
138 // i.e., these rules imply "if we have an integer literal, then there must not be an overflow."
139 integerOverflowHelperRule = qi::eps[qi::_pass = !qi::_r1];
140 integerOverflowHelperRule.name("no 64-bit integer overflow");
141 integerLiteralExpression = integerLiteral_[qi::_val = phoenix::bind(&ExpressionCreator::createIntegerLiteralExpression, phoenix::ref(*expressionCreator),
142 qi::_1, qi::_pass, qi::_a)] > integerOverflowHelperRule(qi::_a);
143 integerLiteralExpression.name("integer literal");
144
145 literalExpression =
146 qi::lit("true")[qi::_val = phoenix::bind(&ExpressionCreator::createBooleanLiteralExpression, phoenix::ref(*expressionCreator), true, qi::_pass)] |
147 qi::lit("false")[qi::_val = phoenix::bind(&ExpressionCreator::createBooleanLiteralExpression, phoenix::ref(*expressionCreator), false, qi::_pass)] |
148 floatLiteral_[qi::_val = phoenix::bind(&ExpressionCreator::createRationalLiteralExpression, phoenix::ref(*expressionCreator), qi::_1, qi::_pass)] |
149 integerLiteralExpression[qi::_val = qi::_1];
150 literalExpression.name("literal expression");
151
152 atomicExpression = predicateExpression | floorCeilExpression | roundExpression | prefixPowerModuloLogarithmExpression | minMaxExpression |
153 (qi::lit("(") >> expression >> qi::lit(")")) | identifierExpression | literalExpression;
154 atomicExpression.name("atomic expression");
155
156 unaryExpression =
157 (*unaryOperator_ >>
158 atomicExpression)[qi::_val = phoenix::bind(&ExpressionCreator::createUnaryExpression, phoenix::ref(*expressionCreator), qi::_1, qi::_2, qi::_pass)];
159 unaryExpression.name("unary expression");
160
161 if (allowBacktracking) {
162 infixPowerModuloExpression =
163 unaryExpression[qi::_val = qi::_1] >>
164 -(infixPowerModuloOperator_ >>
165 unaryExpression)[qi::_a = phoenix::bind(&ExpressionCreator::createPowerModuloLogarithmExpression, phoenix::ref(*expressionCreator), qi::_val,
166 qi::_1, qi::_2, qi::_pass)][qi::_val = qi::_a];
167 } else {
168 infixPowerModuloExpression =
169 unaryExpression[qi::_val = qi::_1] >
170 -(infixPowerModuloOperator_ >> unaryExpression)[qi::_val = phoenix::bind(&ExpressionCreator::createPowerModuloLogarithmExpression,
171 phoenix::ref(*expressionCreator), qi::_val, qi::_1, qi::_2, qi::_pass)];
172 }
173 infixPowerModuloExpression.name("(infix) power/modulo expression");
174
175 if (allowBacktracking) {
176 multiplicationExpression =
177 infixPowerModuloExpression[qi::_val = qi::_1] >>
178 *(multiplicationOperator_ >>
179 infixPowerModuloExpression)[qi::_a = phoenix::bind(&ExpressionCreator::createMultExpression, phoenix::ref(*expressionCreator), qi::_val, qi::_1,
180 qi::_2, qi::_pass)][qi::_val = qi::_a];
181 } else {
182 multiplicationExpression =
183 infixPowerModuloExpression[qi::_val = qi::_1] >
184 *(multiplicationOperator_ >
185 infixPowerModuloExpression)[qi::_val = phoenix::bind(&ExpressionCreator::createMultExpression, phoenix::ref(*expressionCreator), qi::_val, qi::_1,
186 qi::_2, qi::_pass)];
187 }
188 multiplicationExpression.name("multiplication expression");
189
190 if (allowBacktracking) {
191 plusExpression =
192 multiplicationExpression[qi::_val = qi::_1] >>
193 *(plusOperator_ >> multiplicationExpression)[qi::_a = phoenix::bind(&ExpressionCreator::createPlusExpression, phoenix::ref(*expressionCreator),
194 qi::_val, qi::_1, qi::_2, qi::_pass)][qi::_val = qi::_a];
195 } else {
196 plusExpression =
197 multiplicationExpression[qi::_val = qi::_1] >
198 *(plusOperator_ >> multiplicationExpression)[qi::_val = phoenix::bind(&ExpressionCreator::createPlusExpression, phoenix::ref(*expressionCreator),
199 qi::_val, qi::_1, qi::_2, qi::_pass)];
200 }
201 plusExpression.name("plus expression");
202
203 if (allowBacktracking) {
204 relativeExpression =
205 plusExpression[qi::_val = qi::_1] >>
206 -(relationalOperator_ >> plusExpression)[qi::_a = phoenix::bind(&ExpressionCreator::createRelationalExpression, phoenix::ref(*expressionCreator),
207 qi::_val, qi::_1, qi::_2, qi::_pass)][qi::_val = qi::_a];
208 } else {
209 relativeExpression =
210 plusExpression[qi::_val = qi::_1] >
211 -(relationalOperator_ > plusExpression)[qi::_val = phoenix::bind(&ExpressionCreator::createRelationalExpression, phoenix::ref(*expressionCreator),
212 qi::_val, qi::_1, qi::_2, qi::_pass)];
213 }
214 relativeExpression.name("relative expression");
215
216 if (allowBacktracking) {
217 equalityExpression =
218 relativeExpression[qi::_val = qi::_1] >>
219 *(equalityOperator_ >> relativeExpression)[qi::_a = phoenix::bind(&ExpressionCreator::createEqualsExpression, phoenix::ref(*expressionCreator),
220 qi::_val, qi::_1, qi::_2, qi::_pass)][qi::_val = qi::_a];
221 } else {
222 equalityExpression =
223 relativeExpression[qi::_val = qi::_1] >>
224 *(equalityOperator_ >> relativeExpression)[qi::_val = phoenix::bind(&ExpressionCreator::createEqualsExpression, phoenix::ref(*expressionCreator),
225 qi::_val, qi::_1, qi::_2, qi::_pass)];
226 }
227 equalityExpression.name("equality expression");
228
229 if (allowBacktracking) {
230 andExpression = equalityExpression[qi::_val = qi::_1] >>
231 *(andOperator_ >> equalityExpression)[qi::_a = phoenix::bind(&ExpressionCreator::createAndExpression, phoenix::ref(*expressionCreator),
232 qi::_val, qi::_1, qi::_2, qi::_pass)][qi::_val = qi::_a];
233 } else {
234 andExpression = equalityExpression[qi::_val = qi::_1] >>
235 *(andOperator_ > equalityExpression)[qi::_val = phoenix::bind(&ExpressionCreator::createAndExpression, phoenix::ref(*expressionCreator),
236 qi::_val, qi::_1, qi::_2, qi::_pass)];
237 }
238 andExpression.name("and expression");
239
240 if (allowBacktracking) {
241 orExpression = andExpression[qi::_val = qi::_1] >>
242 *(orOperator_ >> andExpression)[qi::_a = phoenix::bind(&ExpressionCreator::createOrExpression, phoenix::ref(*expressionCreator),
243 qi::_val, qi::_1, qi::_2, qi::_pass)][qi::_val = qi::_a];
244 } else {
245 orExpression = andExpression[qi::_val = qi::_1] >
246 *(orOperator_ > andExpression)[qi::_val = phoenix::bind(&ExpressionCreator::createOrExpression, phoenix::ref(*expressionCreator),
247 qi::_val, qi::_1, qi::_2, qi::_pass)];
248 }
249 orExpression.name("or expression");
250
251 if (allowBacktracking) {
252 iteExpression = orExpression[qi::_val = qi::_1] >>
253 -(qi::lit("?") >> iteExpression >> qi::lit(":") >>
254 iteExpression)[qi::_a = phoenix::bind(&ExpressionCreator::createIteExpression, phoenix::ref(*expressionCreator), qi::_val, qi::_1,
255 qi::_2, qi::_pass)][qi::_val = qi::_a];
256 } else {
257 iteExpression =
258 orExpression[qi::_val = qi::_1] > -(qi::lit("?") > iteExpression > qi::lit(":") >
259 iteExpression)[qi::_val = phoenix::bind(&ExpressionCreator::createIteExpression,
260 phoenix::ref(*expressionCreator), qi::_val, qi::_1, qi::_2, qi::_pass)];
261 }
262 iteExpression.name("if-then-else expression");
263
264 expression %= iteExpression;
265 expression.name("expression");
266
286 if (enableErrorHandling) {
287 // Enable error reporting.
288 qi::on_error<qi::fail>(expression, handler(qi::_1, qi::_2, qi::_3, qi::_4));
289 qi::on_error<qi::fail>(iteExpression, handler(qi::_1, qi::_2, qi::_3, qi::_4));
290 qi::on_error<qi::fail>(orExpression, handler(qi::_1, qi::_2, qi::_3, qi::_4));
291 qi::on_error<qi::fail>(andExpression, handler(qi::_1, qi::_2, qi::_3, qi::_4));
292 qi::on_error<qi::fail>(equalityExpression, handler(qi::_1, qi::_2, qi::_3, qi::_4));
293 qi::on_error<qi::fail>(relativeExpression, handler(qi::_1, qi::_2, qi::_3, qi::_4));
294 qi::on_error<qi::fail>(plusExpression, handler(qi::_1, qi::_2, qi::_3, qi::_4));
295 qi::on_error<qi::fail>(multiplicationExpression, handler(qi::_1, qi::_2, qi::_3, qi::_4));
296 qi::on_error<qi::fail>(unaryExpression, handler(qi::_1, qi::_2, qi::_3, qi::_4));
297 qi::on_error<qi::fail>(atomicExpression, handler(qi::_1, qi::_2, qi::_3, qi::_4));
298 qi::on_error<qi::fail>(literalExpression, handler(qi::_1, qi::_2, qi::_3, qi::_4));
299 qi::on_error<qi::fail>(integerLiteralExpression, handler(qi::_1, qi::_2, qi::_3, qi::_4));
300 qi::on_error<qi::fail>(integerOverflowHelperRule, handler(qi::_1, qi::_2, qi::_3, qi::_4));
301 qi::on_error<qi::fail>(identifierExpression, handler(qi::_1, qi::_2, qi::_3, qi::_4));
302 qi::on_error<qi::fail>(minMaxExpression, handler(qi::_1, qi::_2, qi::_3, qi::_4));
303 qi::on_error<qi::fail>(floorCeilExpression, handler(qi::_1, qi::_2, qi::_3, qi::_4));
304 qi::on_error<qi::fail>(roundExpression, handler(qi::_1, qi::_2, qi::_3, qi::_4));
305 }
306}
307
309 // Needed, because auto-generated destructor requires ExpressionCreator to be a complete type in the header.
310}
311
312void ExpressionParser::setIdentifierMapping(qi::symbols<char, storm::expressions::Expression> const* identifiers_) {
313 expressionCreator->setIdentifierMapping(identifiers_);
314}
315
316void ExpressionParser::setIdentifierMapping(std::unordered_map<std::string, storm::expressions::Expression> const& identifierMapping) {
317 expressionCreator->setIdentifierMapping(identifierMapping);
318}
319
321 expressionCreator->unsetIdentifierMapping();
322}
323
325 expressionCreator->setAcceptDoubleLiterals(flag);
326}
327
328bool ExpressionParser::isValidIdentifier(std::string const& identifier) {
329 if (this->invalidIdentifiers_.find(identifier) != nullptr) {
330 return false;
331 }
332 return true;
333}
334
335storm::expressions::Expression ExpressionParser::parseFromString(std::string const& expressionString, bool ignoreError) const {
336 PositionIteratorType first(expressionString.begin());
337 PositionIteratorType iter = first;
338 PositionIteratorType last(expressionString.end());
339
340 // Create empty result;
342
343 try {
344 // Start parsing.
345 bool succeeded = qi::phrase_parse(
346 iter, last, *this, storm::spirit_encoding::space_type() | qi::lit("//") >> *(qi::char_ - (qi::eol | qi::eoi)) >> (qi::eol | qi::eoi), result);
347 succeeded &= (iter == last);
348 if (!succeeded) {
349 STORM_LOG_THROW(ignoreError, storm::exceptions::WrongFormatException, "Could not parse expression '" << expressionString << "'.");
351 }
352 STORM_LOG_DEBUG("Parsed expression successfully.");
353 } catch (qi::expectation_failure<PositionIteratorType> const& e) {
354 STORM_LOG_THROW(ignoreError, storm::exceptions::WrongFormatException, e.what_);
356 }
357 return result;
358}
359} // namespace parser
360} // namespace storm
boost::spirit::line_pos_iterator< BaseIteratorType > PositionIteratorType
This class is responsible for managing a set of typed variables and all expressions using these varia...
storm::expressions::Expression createIntegerLiteralExpression(storm::RationalNumber const &value, bool &pass, bool &overflow) const
storm::expressions::Expression getIdentifierExpression(std::string const &identifier, bool &pass) const
storm::expressions::Expression createRationalLiteralExpression(storm::RationalNumber const &value, bool &pass) const
storm::expressions::Expression createPredicateExpression(storm::expressions::OperatorType const &opTyp, std::vector< storm::expressions::Expression > const &operands, bool &pass) const
storm::expressions::Expression createIteExpression(storm::expressions::Expression const &e1, storm::expressions::Expression const &e2, storm::expressions::Expression const &e3, bool &pass) const
storm::expressions::Expression createMultExpression(storm::expressions::Expression const &e1, storm::expressions::OperatorType const &operatorType, storm::expressions::Expression const &e2, bool &pass) const
storm::expressions::Expression createPlusExpression(storm::expressions::Expression const &e1, storm::expressions::OperatorType const &operatorType, storm::expressions::Expression const &e2, bool &pass) const
storm::expressions::Expression createEqualsExpression(storm::expressions::Expression const &e1, storm::expressions::OperatorType const &operatorType, storm::expressions::Expression const &e2, bool &pass) const
storm::expressions::Expression createFloorCeilExpression(storm::expressions::OperatorType const &operatorType, storm::expressions::Expression const &e1, bool &pass) const
storm::expressions::Expression createOrExpression(storm::expressions::Expression const &e1, storm::expressions::OperatorType const &operatorType, storm::expressions::Expression const &e2, bool &pass) const
storm::expressions::Expression createRelationalExpression(storm::expressions::Expression const &e1, storm::expressions::OperatorType const &operatorType, storm::expressions::Expression const &e2, bool &pass) const
storm::expressions::Expression createRoundExpression(storm::expressions::Expression const &e1, bool &pass) const
storm::expressions::Expression createBooleanLiteralExpression(bool value, bool &pass) const
storm::expressions::Expression createUnaryExpression(std::vector< storm::expressions::OperatorType > const &operatorType, storm::expressions::Expression const &e1, bool &pass) const
storm::expressions::Expression createPowerModuloLogarithmExpression(storm::expressions::Expression const &e1, storm::expressions::OperatorType const &operatorType, storm::expressions::Expression const &e2, bool &pass) const
storm::expressions::Expression createAndExpression(storm::expressions::Expression const &e1, storm::expressions::OperatorType const &operatorType, storm::expressions::Expression const &e2, bool &pass) const
storm::expressions::Expression createMinimumMaximumExpression(storm::expressions::Expression const &e1, storm::expressions::OperatorType const &operatorType, storm::expressions::Expression const &e2, bool &pass) const
storm::expressions::Expression parseFromString(std::string const &expressionString, bool ignoreError=false) const
Parses an expression from the given string.
void setIdentifierMapping(qi::symbols< char, storm::expressions::Expression > const *identifiers_)
Sets an identifier mapping that is used to determine valid variables in the expression.
void unsetIdentifierMapping()
Unsets a previously set identifier mapping.
void setAcceptDoubleLiterals(bool flag)
Sets whether double literals are to be accepted or not.
ExpressionParser(storm::expressions::ExpressionManager const &manager, qi::symbols< char, uint_fast64_t > const &invalidIdentifiers_=qi::symbols< char, uint_fast64_t >(), bool enableErrorHandling=true, bool allowBacktracking=false)
Creates an expression parser.
#define STORM_LOG_DEBUG(message)
Definition logging.h:23
#define STORM_LOG_THROW(cond, exception, message)
Definition macros.h:30
bool is_equal_to_one(storm::RationalNumber const &value)
storm::RationalNumber negate(bool neg, storm::RationalNumber const &number)
bool scale(int exp, storm::RationalNumber &r, storm::RationalNumber acc)
bool isOne(ValueType const &a)
Definition constants.cpp:36
ValueType pow(ValueType const &value, int_fast64_t exponent)
LabParser.cpp.
Definition cli.cpp:18