Storm
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
FormulaParserGrammar.cpp
Go to the documentation of this file.
2
3#include <memory>
4
6
7namespace storm {
8namespace parser {
9
10FormulaParserGrammar::FormulaParserGrammar(std::shared_ptr<storm::expressions::ExpressionManager const> const& manager)
11 : FormulaParserGrammar::base_type(start), constManager(manager), manager(nullptr), expressionParser(*manager, keywords_, true, true), propertyCount(0) {
12 initialize();
13}
14
15FormulaParserGrammar::FormulaParserGrammar(std::shared_ptr<storm::expressions::ExpressionManager> const& manager)
16 : FormulaParserGrammar::base_type(start), constManager(manager), manager(manager), expressionParser(*manager, keywords_, true, true), propertyCount(0) {
17 initialize();
18}
19
20qi::symbols<char, storm::expressions::Expression> const& FormulaParserGrammar::getIdentifiers() const {
21 return identifiers_;
22}
23
24void FormulaParserGrammar::initialize() {
25 // Register all variables so we can parse them in the expressions.
26 for (auto variableTypePair : *constManager) {
27 addIdentifierExpression(variableTypePair.first.getName(), variableTypePair.first);
28 }
29 // Set the identifier mapping to actually generate expressions.
30 expressionParser.setIdentifierMapping(&identifiers_);
31
32 keywords_.name("keyword");
33 nonStandardKeywords_.name("non-standard Storm-specific keyword");
34 relationalOperator_.name("relational operator");
35 optimalityOperator_.name("optimality operator");
36 operatorKeyword_.name("Operator keyword");
37 filterType_.name("filter type");
38
39 // Auxiliary helpers
40 isPathFormula = qi::eps(qi::_r1 == FormulaKind::Path);
41 noAmbiguousNonAssociativeOperator =
42 !(qi::lit(qi::_r2)[qi::_pass = phoenix::bind(&FormulaParserGrammar::raiseAmbiguousNonAssociativeOperatorError, phoenix::ref(*this), qi::_r1, qi::_r2)]);
43 noAmbiguousNonAssociativeOperator.name("no ambiguous non-associative operator");
44 identifier %= qi::as_string[qi::raw[qi::lexeme[((qi::alpha | qi::char_('_') | qi::char_('.')) >> *(qi::alnum | qi::char_('_')))]]];
45 identifier.name("identifier");
46 label %= qi::as_string[qi::raw[qi::lexeme[((qi::alpha | qi::char_('_')) >> *(qi::alnum | qi::char_('_')))]]];
47 label.name("label");
48 quotedString %= qi::as_string[qi::lexeme[qi::omit[qi::char_('"')] > qi::raw[*(!qi::char_('"') >> qi::char_)] > qi::omit[qi::lit('"')]]];
49 quotedString.name("quoted string");
50
51 // PCTL-like Operator Formulas
52 operatorInformation =
53 (-optimalityOperator_)[qi::_a = qi::_1] >>
54 ((qi::lit("=") >
55 qi::lit("?"))[qi::_val = phoenix::bind(&FormulaParserGrammar::createOperatorInformation, phoenix::ref(*this), qi::_a, boost::none, boost::none)] |
56 (relationalOperator_ >
57 expressionParser)[qi::_val = phoenix::bind(&FormulaParserGrammar::createOperatorInformation, phoenix::ref(*this), qi::_a, qi::_1, qi::_2)]);
58 operatorInformation.name("operator information");
59 operatorSubFormula =
60 (((qi::eps(qi::_r1 == storm::logic::FormulaContext::Probability) > formula(FormulaKind::Path, qi::_r1)) |
61 (qi::eps(qi::_r1 == storm::logic::FormulaContext::Reward) >
62 (longRunAverageRewardFormula | eventuallyFormula(qi::_r1) | cumulativeRewardFormula | instantaneousRewardFormula | totalRewardFormula)) |
63 (qi::eps(qi::_r1 == storm::logic::FormulaContext::Time) > eventuallyFormula(qi::_r1)) |
64 (qi::eps(qi::_r1 == storm::logic::FormulaContext::LongRunAverage) > formula(FormulaKind::State, storm::logic::FormulaContext::LongRunAverage))) >>
65 -(qi::lit("||") >
66 formula(FormulaKind::Path, storm::logic::FormulaContext::Probability)))[qi::_val = phoenix::bind(&FormulaParserGrammar::createConditionalFormula,
67 phoenix::ref(*this), qi::_1, qi::_2, qi::_r1)];
68 operatorSubFormula.name("operator subformula");
69 rewardModelName = qi::eps(qi::_r1 == storm::logic::FormulaContext::Reward) >> (qi::lit("{\"") > label > qi::lit("\"}"));
70 rewardModelName.name("reward model name");
71 operatorFormula =
72 (operatorKeyword_[qi::_a = qi::_1] > -rewardModelName(qi::_a) > operatorInformation > qi::lit("[") > operatorSubFormula(qi::_a) >
73 qi::lit("]"))[qi::_val = phoenix::bind(&FormulaParserGrammar::createOperatorFormula, phoenix::ref(*this), qi::_a, qi::_2, qi::_3, qi::_4)];
74 operatorFormula.name("operator formula");
75
76 // Atomic propositions
77 labelFormula =
78 (qi::lit("\"") >> label >> qi::lit("\""))[qi::_val = phoenix::bind(&FormulaParserGrammar::createAtomicLabelFormula, phoenix::ref(*this), qi::_1)];
79 labelFormula.name("label formula");
80 expressionFormula = expressionParser[qi::_val = phoenix::bind(&FormulaParserGrammar::createAtomicExpressionFormula, phoenix::ref(*this), qi::_1)];
81 expressionFormula.name("expression formula");
82
83 basicPropositionalFormula =
84 expressionFormula // try as expression first, e.g. '(false)=false' is an atomic expression formula. Also should be checked before operator formulas and
85 // others. Otherwise, e.g. variable "Random" would be parsed as reward operator 'R' (followed by andom)
86 | (qi::lit("(") >>
87 (formula(qi::_r1, qi::_r2) > qi::lit(")"))) // If we're starting with '(' but this is not an expression, we must have a formula inside the brackets
88 | labelFormula | negationPropositionalFormula(qi::_r1, qi::_r2) | operatorFormula |
89 (isPathFormula(qi::_r1) >> prefixOperatorPathFormula(qi::_r2)) // Needed for e.g. F "a" & X "a" = F ("a" & (X "a"))
90 | multiOperatorFormula // Has to come after prefixOperatorPathFormula to avoid confusion with multiBoundedPathFormula
91 | quantileFormula | gameFormula;
92
93 // Propositional Logic operators
94 // To correctly parse the operator precedences (! binds stronger than & binds stronger than |), we run through different "precedence levels" starting with
95 // the strongest binding operator.
96 negationPropositionalFormula =
97 (qi::lit("!") >
98 basicPropositionalFormula(qi::_r1, qi::_r2))[qi::_val = phoenix::bind(&FormulaParserGrammar::createUnaryBooleanStateOrPathFormula, phoenix::ref(*this),
100 basicPropositionalFormula.name("basic propositional formula");
101 andLevelPropositionalFormula =
102 basicPropositionalFormula(qi::_r1, qi::_r2)[qi::_val = qi::_1] >>
103 *(qi::lit("&") > basicPropositionalFormula(
104 qi::_r1, qi::_r2)[qi::_val = phoenix::bind(&FormulaParserGrammar::createBinaryBooleanStateOrPathFormula, phoenix::ref(*this),
105 qi::_val, qi::_1, storm::logic::BinaryBooleanStateFormula::OperatorType::And)]);
106 andLevelPropositionalFormula.name("and precedence level propositional formula");
107 orLevelPropositionalFormula =
108 andLevelPropositionalFormula(qi::_r1, qi::_r2)[qi::_val = qi::_1] >>
109 *((!qi::lit("||") >> qi::lit("|")) // Make sure to not confuse with conditional operator "||"
110 > andLevelPropositionalFormula(
111 qi::_r1, qi::_r2)[qi::_val = phoenix::bind(&FormulaParserGrammar::createBinaryBooleanStateOrPathFormula, phoenix::ref(*this), qi::_val, qi::_1,
112 storm::logic::BinaryBooleanStateFormula::OperatorType::Or)]);
113 orLevelPropositionalFormula.name("or precedence level propositional formula");
114 propositionalFormula = orLevelPropositionalFormula(qi::_r1, qi::_r2);
115
116 // Path operators
117 // Again need to parse precedences correctly. Propositional formulae bind stronger than temporal operators.
118 basicPathFormula = propositionalFormula(FormulaKind::Path, qi::_r1) // Bracketed case is handled here as well
119 | prefixOperatorPathFormula(
120 qi::_r1); // Needs to be checked *after* atomic expression formulas. Otherwise e.g. variable Fail would be parsed as "F (ail)"
121 prefixOperatorPathFormula =
122 eventuallyFormula(qi::_r1) | nextFormula(qi::_r1) | globallyFormula(qi::_r1) | hoaPathFormula(qi::_r1) | multiBoundedPathFormula(qi::_r1);
123 basicPathFormula.name("basic path formula");
124 timeBoundReference =
125 (-qi::lit("rew") >>
126 rewardModelName(storm::logic::FormulaContext::Reward))[qi::_val = phoenix::bind(&FormulaParserGrammar::createTimeBoundReference, phoenix::ref(*this),
128 (qi::lit("rew") >>
129 -rewardModelName(storm::logic::FormulaContext::Reward))[qi::_val = phoenix::bind(&FormulaParserGrammar::createTimeBoundReference, phoenix::ref(*this),
131 (qi::lit("steps"))[qi::_val = phoenix::bind(&FormulaParserGrammar::createTimeBoundReference, phoenix::ref(*this), storm::logic::TimeBoundType::Steps,
132 boost::none)] |
133 (-qi::lit("time"))[qi::_val = phoenix::bind(&FormulaParserGrammar::createTimeBoundReference, phoenix::ref(*this), storm::logic::TimeBoundType::Time,
134 boost::none)];
135 timeBoundReference.name("time bound reference");
136 timeBound = ((timeBoundReference >> qi::lit("[")) > expressionParser > qi::lit(",") > expressionParser >
137 qi::lit("]"))[qi::_val = phoenix::bind(&FormulaParserGrammar::createTimeBoundFromInterval, phoenix::ref(*this), qi::_2, qi::_3, qi::_1)] |
138 (timeBoundReference >> (qi::lit("<=")[(qi::_a = true, qi::_b = false)] | qi::lit("<")[(qi::_a = true, qi::_b = true)] |
139 qi::lit(">=")[(qi::_a = false, qi::_b = false)] | qi::lit(">")[(qi::_a = false, qi::_b = true)]) >>
140 expressionParser)[qi::_val = phoenix::bind(&FormulaParserGrammar::createTimeBoundFromSingleBound, phoenix::ref(*this), qi::_2, qi::_a, qi::_b,
141 qi::_1)] |
142 (timeBoundReference >> qi::lit("=") >>
143 expressionParser)[qi::_val = phoenix::bind(&FormulaParserGrammar::createTimeBoundFromInterval, phoenix::ref(*this), qi::_2, qi::_2, qi::_1)];
144 timeBound.name("time bound");
145 timeBounds = (timeBound % qi::lit(",")) | (((-qi::lit("^") >> qi::lit("{")) >> (timeBound % qi::lit(","))) >> qi::lit("}"));
146 timeBounds.name("time bounds");
147 eventuallyFormula =
148 (qi::lit("F") > (-timeBounds) >
149 basicPathFormula(qi::_r1))[qi::_val = phoenix::bind(&FormulaParserGrammar::createEventuallyFormula, phoenix::ref(*this), qi::_1, qi::_r1, qi::_2)];
150 eventuallyFormula.name("eventually formula");
151 nextFormula = (qi::lit("X") > basicPathFormula(qi::_r1))[qi::_val = phoenix::bind(&FormulaParserGrammar::createNextFormula, phoenix::ref(*this), qi::_1)];
152 nextFormula.name("next formula");
153 globallyFormula =
154 (qi::lit("G") > basicPathFormula(qi::_r1))[qi::_val = phoenix::bind(&FormulaParserGrammar::createGloballyFormula, phoenix::ref(*this), qi::_1)];
155 globallyFormula.name("globally formula");
156 hoaPathFormula =
157 qi::lit("HOA:") > qi::lit("{") > quotedString[qi::_val = phoenix::bind(&FormulaParserGrammar::createHOAPathFormula, phoenix::ref(*this), qi::_1)] >>
158 *(qi::lit(",") > quotedString > qi::lit("->") >
159 formula(FormulaKind::State, qi::_r1))[phoenix::bind(&FormulaParserGrammar::addHoaAPMapping, phoenix::ref(*this), *qi::_val, qi::_1, qi::_2)] >
160 qi::lit("}");
161 multiBoundedPathFormulaOperand = pathFormula(
162 qi::_r1)[qi::_pass = phoenix::bind(&FormulaParserGrammar::isValidMultiBoundedPathFormulaOperand, phoenix::ref(*this), qi::_1)][qi::_val = qi::_1];
163 multiBoundedPathFormulaOperand.name("multi bounded path formula operand");
164 multiBoundedPathFormula = ((qi::lit("multi") > qi::lit("(")) >> (multiBoundedPathFormulaOperand(qi::_r1) % qi::lit(",")) >>
165 qi::lit(")"))[qi::_val = phoenix::bind(&FormulaParserGrammar::createMultiBoundedPathFormula, phoenix::ref(*this), qi::_1)];
166 multiBoundedPathFormula.name("multi bounded path formula");
167 untilLevelPathFormula =
168 basicPathFormula(qi::_r1)[qi::_val = qi::_1] >>
169 -((qi::lit("U") > (-timeBounds) >
170 basicPathFormula(qi::_r1))[qi::_val = phoenix::bind(&FormulaParserGrammar::createUntilFormula, phoenix::ref(*this), qi::_val, qi::_1, qi::_2)]) >>
171 (qi::eps > noAmbiguousNonAssociativeOperator(qi::_val, std::string("U"))); // Do not parse a U b U c
172 untilLevelPathFormula.name("until precedence level path formula");
173 pathFormula = untilLevelPathFormula(qi::_r1);
174 pathFormula.name("path formula");
175
176 // Quantitative path formulae (reward)
177 longRunAverageRewardFormula = (qi::lit("LRA") | qi::lit("S") |
178 qi::lit("MP"))[qi::_val = phoenix::bind(&FormulaParserGrammar::createLongRunAverageRewardFormula, phoenix::ref(*this))];
179 longRunAverageRewardFormula.name("long run average reward formula");
180 instantaneousRewardFormula =
181 (qi::lit("I=") > expressionParser)[qi::_val = phoenix::bind(&FormulaParserGrammar::createInstantaneousRewardFormula, phoenix::ref(*this), qi::_1)];
182 instantaneousRewardFormula.name("instantaneous reward formula");
183 cumulativeRewardFormula =
184 (qi::lit("C") >> timeBounds)[qi::_val = phoenix::bind(&FormulaParserGrammar::createCumulativeRewardFormula, phoenix::ref(*this), qi::_1)];
185 cumulativeRewardFormula.name("cumulative reward formula");
186 totalRewardFormula = (qi::lit("C"))[qi::_val = phoenix::bind(&FormulaParserGrammar::createTotalRewardFormula, phoenix::ref(*this))];
187 totalRewardFormula.name("total reward formula");
188
189 // Game Formulae
190 playerCoalition = (-((identifier[phoenix::push_back(qi::_a, qi::_1)] | qi::uint_[phoenix::push_back(qi::_a, qi::_1)]) %
191 ','))[qi::_val = phoenix::bind(&FormulaParserGrammar::createPlayerCoalition, phoenix::ref(*this), qi::_a)];
192 playerCoalition.name("player coalition");
193 gameFormula = (qi::lit("<<") > playerCoalition > qi::lit(">>") >
194 operatorFormula)[qi::_val = phoenix::bind(&FormulaParserGrammar::createGameFormula, phoenix::ref(*this), qi::_1, qi::_2)];
195 gameFormula.name("game formula");
196
197 // Multi-objective, quantiles
198 multiOperatorFormula = (qi::lit("multi") > qi::lit("(") > (operatorFormula % qi::lit(",")) >
199 qi::lit(")"))[qi::_val = phoenix::bind(&FormulaParserGrammar::createMultiOperatorFormula, phoenix::ref(*this), qi::_1)];
200 multiOperatorFormula.name("multi-objective operator formula");
201 quantileBoundVariable = (-optimalityOperator_ >> identifier >>
202 qi::lit(","))[qi::_val = phoenix::bind(&FormulaParserGrammar::createQuantileBoundVariables, phoenix::ref(*this), qi::_1, qi::_2)];
203 quantileBoundVariable.name("quantile bound variable");
204 quantileFormula = (qi::lit("quantile") > qi::lit("(") > *(quantileBoundVariable) >
205 operatorFormula[qi::_pass = phoenix::bind(&FormulaParserGrammar::isBooleanReturnType, phoenix::ref(*this), qi::_1, true)] >
206 qi::lit(")"))[qi::_val = phoenix::bind(&FormulaParserGrammar::createQuantileFormula, phoenix::ref(*this), qi::_1, qi::_2)];
207 quantileFormula.name("Quantile formula");
208
209 // General formulae
210 formula = (isPathFormula(qi::_r1) >> pathFormula(qi::_r2) | propositionalFormula(qi::_r1, qi::_r2));
211 formula.name("formula");
212
213 topLevelFormula = formula(FormulaKind::State, storm::logic::FormulaContext::Undefined);
214 topLevelFormula.name("top-level formula");
215
216 formulaName = qi::lit("\"") >> identifier >> qi::lit("\"") >> qi::lit(":");
217 formulaName.name("formula name");
218
219 constantDefinition =
220 (qi::lit("const") > -(qi::lit("int")[qi::_a = ConstantDataType::Integer] | qi::lit("bool")[qi::_a = ConstantDataType::Bool] |
221 qi::lit("double")[qi::_a = ConstantDataType::Rational]) >>
222 identifier >> -(qi::lit("=") > expressionParser))[phoenix::bind(&FormulaParserGrammar::addConstant, phoenix::ref(*this), qi::_1, qi::_a, qi::_2)];
223 constantDefinition.name("constant definition");
224
225#pragma clang diagnostic push
226#pragma clang diagnostic ignored "-Woverloaded-shift-op-parentheses"
227
228 filterProperty =
229 (-formulaName >> qi::lit("filter") > qi::lit("(") > filterType_ > qi::lit(",") > topLevelFormula > qi::lit(",") >
230 formula(FormulaKind::State, storm::logic::FormulaContext::Undefined) >
231 qi::lit(")"))[qi::_val = phoenix::bind(&FormulaParserGrammar::createProperty, phoenix::ref(*this), qi::_1, qi::_2, qi::_3, qi::_4)] |
232 (-formulaName >>
233 topLevelFormula)[qi::_val = phoenix::bind(&FormulaParserGrammar::createPropertyWithDefaultFilterTypeAndStates, phoenix::ref(*this), qi::_1, qi::_2)];
234 filterProperty.name("filter property");
235
236#pragma clang diagnostic pop
237
238 start = (qi::eps >> filterProperty[phoenix::push_back(qi::_val, qi::_1)] |
239 qi::eps(phoenix::bind(&FormulaParserGrammar::areConstantDefinitionsAllowed, phoenix::ref(*this))) >> constantDefinition | qi::eps) %
240 +(qi::char_("\n;")) >>
241 qi::skip(storm::spirit_encoding::space_type() | qi::lit("//") >> *(qi::char_ - (qi::eol | qi::eoi)))[qi::eps] >> qi::eoi;
242 start.name("start");
243
244 // Enable the following lines to print debug output for most the rules.
245 // debug(rewardModelName)
246 // debug(operatorFormula)
247 // debug(labelFormula)
248 // debug(expressionFormula)
249 // debug(basicPropositionalFormula)
250 // debug(negationPropositionalFormula)
251 // debug(andLevelPropositionalFormula)
252 // debug(orLevelPropositionalFormula)
253 // debug(propositionalFormula)
254 // debug(timeBoundReference)
255 // debug(timeBound)
256 // debug(timeBounds)
257 // debug(eventuallyFormula)
258 // debug(nextFormula)
259 // debug(globallyFormula)
260 // debug(hoaPathFormula)
261 // debug(multiBoundedPathFormula)
262 // debug(prefixOperatorPathFormula)
263 // debug(basicPathFormula)
264 // debug(untilLevelPathFormula)
265 // debug(pathFormula)
266 // debug(longRunAverageRewardFormula)
267 // debug(instantaneousRewardFormula)
268 // debug(cumulativeRewardFormula)
269 // debug(totalRewardFormula)
270 // debug(playerCoalition)
271 // debug(gameFormula)
272 // debug(multiOperatorFormula)
273 // debug(quantileBoundVariable)
274 // debug(quantileFormula)
275 // debug(formula)
276 // debug(topLevelFormula)
277 // debug(formulaName)
278 // debug(filterProperty)
279 // debug(constantDefinition )
280 // debug(start)
281
282 // Enable error reporting.
283 qi::on_error<qi::fail>(rewardModelName, handler(qi::_1, qi::_2, qi::_3, qi::_4));
284 qi::on_error<qi::fail>(operatorFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4));
285 qi::on_error<qi::fail>(labelFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4));
286 qi::on_error<qi::fail>(expressionFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4));
287 qi::on_error<qi::fail>(basicPropositionalFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4));
288 qi::on_error<qi::fail>(negationPropositionalFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4));
289 qi::on_error<qi::fail>(andLevelPropositionalFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4));
290 qi::on_error<qi::fail>(orLevelPropositionalFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4));
291 qi::on_error<qi::fail>(propositionalFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4));
292 qi::on_error<qi::fail>(timeBoundReference, handler(qi::_1, qi::_2, qi::_3, qi::_4));
293 qi::on_error<qi::fail>(timeBound, handler(qi::_1, qi::_2, qi::_3, qi::_4));
294 qi::on_error<qi::fail>(timeBounds, handler(qi::_1, qi::_2, qi::_3, qi::_4));
295 qi::on_error<qi::fail>(eventuallyFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4));
296 qi::on_error<qi::fail>(nextFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4));
297 qi::on_error<qi::fail>(globallyFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4));
298 qi::on_error<qi::fail>(hoaPathFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4));
299 qi::on_error<qi::fail>(multiBoundedPathFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4));
300 qi::on_error<qi::fail>(prefixOperatorPathFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4));
301 qi::on_error<qi::fail>(basicPathFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4));
302 qi::on_error<qi::fail>(untilLevelPathFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4));
303 qi::on_error<qi::fail>(pathFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4));
304 qi::on_error<qi::fail>(longRunAverageRewardFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4));
305 qi::on_error<qi::fail>(instantaneousRewardFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4));
306 qi::on_error<qi::fail>(cumulativeRewardFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4));
307 qi::on_error<qi::fail>(totalRewardFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4));
308 qi::on_error<qi::fail>(playerCoalition, handler(qi::_1, qi::_2, qi::_3, qi::_4));
309 qi::on_error<qi::fail>(gameFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4));
310 qi::on_error<qi::fail>(multiOperatorFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4));
311 qi::on_error<qi::fail>(quantileBoundVariable, handler(qi::_1, qi::_2, qi::_3, qi::_4));
312 qi::on_error<qi::fail>(quantileFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4));
313 qi::on_error<qi::fail>(formula, handler(qi::_1, qi::_2, qi::_3, qi::_4));
314 qi::on_error<qi::fail>(topLevelFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4));
315 qi::on_error<qi::fail>(formulaName, handler(qi::_1, qi::_2, qi::_3, qi::_4));
316 qi::on_error<qi::fail>(filterProperty, handler(qi::_1, qi::_2, qi::_3, qi::_4));
317 qi::on_error<qi::fail>(constantDefinition, handler(qi::_1, qi::_2, qi::_3, qi::_4));
318 qi::on_error<qi::fail>(start, handler(qi::_1, qi::_2, qi::_3, qi::_4));
319}
320
321void FormulaParserGrammar::addIdentifierExpression(std::string const& identifier, storm::expressions::Expression const& expression) {
322 STORM_LOG_WARN_COND(keywords_.find(identifier) == nullptr,
323 "Identifier `" << identifier << "' coincides with a reserved keyword or operator. Property expressions using the variable or constant '"
324 << identifier << "' will not be parsed correctly.");
325 STORM_LOG_WARN_COND(nonStandardKeywords_.find(identifier) == nullptr,
326 "Identifier `" << identifier << "' coincides with a reserved keyword or operator. Property expressions using the variable or constant '"
327 << identifier << "' might not be parsed correctly.");
328 this->identifiers_.add(identifier, expression);
329}
330
331void FormulaParserGrammar::addConstant(std::string const& name, ConstantDataType type, boost::optional<storm::expressions::Expression> const& expression) {
332 STORM_LOG_ASSERT(manager, "Mutable expression manager required to define new constants.");
334 STORM_LOG_THROW(!manager->hasVariable(name), storm::exceptions::WrongFormatException,
335 "Invalid constant definition '" << name << "' in property: variable already exists.");
336
337 if (type == ConstantDataType::Bool) {
338 newVariable = manager->declareBooleanVariable(name);
339 } else if (type == ConstantDataType::Integer) {
340 newVariable = manager->declareIntegerVariable(name);
341 } else {
342 newVariable = manager->declareRationalVariable(name);
343 }
344
345 if (expression) {
346 addIdentifierExpression(name, expression.get());
347 } else {
348 undefinedConstants.insert(newVariable);
349 addIdentifierExpression(name, newVariable);
350 }
351}
352
353bool FormulaParserGrammar::areConstantDefinitionsAllowed() const {
354 return static_cast<bool>(manager);
355}
356
357std::shared_ptr<storm::logic::TimeBoundReference> FormulaParserGrammar::createTimeBoundReference(storm::logic::TimeBoundType const& type,
358 boost::optional<std::string> const& rewardModelName) const {
360 return std::make_shared<storm::logic::TimeBoundReference>(rewardModelName);
361 } else {
362 return std::make_shared<storm::logic::TimeBoundReference>(type);
363 }
364}
365
366std::tuple<boost::optional<storm::logic::TimeBound>, boost::optional<storm::logic::TimeBound>, std::shared_ptr<storm::logic::TimeBoundReference>>
367FormulaParserGrammar::createTimeBoundFromInterval(storm::expressions::Expression const& lowerBound, storm::expressions::Expression const& upperBound,
368 std::shared_ptr<storm::logic::TimeBoundReference> const& timeBoundReference) const {
369 // As soon as it somehow does not break everything anymore, I will change return types here.
370
371 storm::logic::TimeBound lower(false, lowerBound);
372 storm::logic::TimeBound upper(false, upperBound);
373 return std::make_tuple(lower, upper, timeBoundReference);
374}
375
376std::tuple<boost::optional<storm::logic::TimeBound>, boost::optional<storm::logic::TimeBound>, std::shared_ptr<storm::logic::TimeBoundReference>>
377FormulaParserGrammar::createTimeBoundFromSingleBound(storm::expressions::Expression const& bound, bool upperBound, bool strict,
378 std::shared_ptr<storm::logic::TimeBoundReference> const& timeBoundReference) const {
379 // As soon as it somehow does not break everything anymore, I will change return types here.
380 if (upperBound) {
381 return std::make_tuple(boost::none, storm::logic::TimeBound(strict, bound), timeBoundReference);
382 } else {
383 return std::make_tuple(storm::logic::TimeBound(strict, bound), boost::none, timeBoundReference);
384 }
385}
386
387std::shared_ptr<storm::logic::Formula const> FormulaParserGrammar::createInstantaneousRewardFormula(storm::expressions::Expression const& timeBound) const {
388 return std::shared_ptr<storm::logic::Formula const>(new storm::logic::InstantaneousRewardFormula(timeBound));
389}
390
391std::shared_ptr<storm::logic::Formula const> FormulaParserGrammar::createCumulativeRewardFormula(
392 std::vector<std::tuple<boost::optional<storm::logic::TimeBound>, boost::optional<storm::logic::TimeBound>,
393 std::shared_ptr<storm::logic::TimeBoundReference>>> const& timeBounds) const {
394 std::vector<storm::logic::TimeBound> bounds;
395 std::vector<storm::logic::TimeBoundReference> timeBoundReferences;
396 for (auto const& timeBound : timeBounds) {
397 STORM_LOG_THROW(!std::get<0>(timeBound), storm::exceptions::WrongFormatException, "Cumulative reward formulas with lower time bound are not allowed.");
398 STORM_LOG_THROW(std::get<1>(timeBound), storm::exceptions::WrongFormatException, "Cumulative reward formulas require an upper bound.");
399 bounds.push_back(std::get<1>(timeBound).get());
400 timeBoundReferences.emplace_back(*std::get<2>(timeBound));
401 }
402 return std::shared_ptr<storm::logic::Formula const>(new storm::logic::CumulativeRewardFormula(bounds, timeBoundReferences));
403}
404
405std::shared_ptr<storm::logic::Formula const> FormulaParserGrammar::createTotalRewardFormula() const {
406 return std::shared_ptr<storm::logic::Formula const>(new storm::logic::TotalRewardFormula());
407}
408
409std::shared_ptr<storm::logic::Formula const> FormulaParserGrammar::createLongRunAverageRewardFormula() const {
410 return std::shared_ptr<storm::logic::Formula const>(new storm::logic::LongRunAverageRewardFormula());
411}
412
413std::shared_ptr<storm::logic::Formula const> FormulaParserGrammar::createAtomicExpressionFormula(storm::expressions::Expression const& expression) const {
414 STORM_LOG_THROW(expression.hasBooleanType(), storm::exceptions::WrongFormatException,
415 "Expected expression " + expression.toString() + " to be of boolean type.");
416 if (expression.isLiteral()) {
417 return createBooleanLiteralFormula(expression.evaluateAsBool());
418 }
419 return std::shared_ptr<storm::logic::Formula const>(new storm::logic::AtomicExpressionFormula(expression));
420}
421
422std::shared_ptr<storm::logic::Formula const> FormulaParserGrammar::createBooleanLiteralFormula(bool literal) const {
423 return std::shared_ptr<storm::logic::Formula const>(new storm::logic::BooleanLiteralFormula(literal));
424}
425
426std::shared_ptr<storm::logic::Formula const> FormulaParserGrammar::createAtomicLabelFormula(std::string const& label) const {
427 return std::shared_ptr<storm::logic::Formula const>(new storm::logic::AtomicLabelFormula(label));
428}
429
430std::shared_ptr<storm::logic::Formula const> FormulaParserGrammar::createEventuallyFormula(
431 boost::optional<std::vector<std::tuple<boost::optional<storm::logic::TimeBound>, boost::optional<storm::logic::TimeBound>,
432 std::shared_ptr<storm::logic::TimeBoundReference>>>> const& timeBounds,
433 storm::logic::FormulaContext context, std::shared_ptr<storm::logic::Formula const> const& subformula) const {
434 if (timeBounds && !timeBounds.get().empty()) {
435 std::vector<boost::optional<storm::logic::TimeBound>> lowerBounds, upperBounds;
436 std::vector<storm::logic::TimeBoundReference> timeBoundReferences;
437 for (auto const& timeBound : timeBounds.get()) {
438 lowerBounds.push_back(std::get<0>(timeBound));
439 upperBounds.push_back(std::get<1>(timeBound));
440 timeBoundReferences.emplace_back(*std::get<2>(timeBound));
441 }
442 return std::shared_ptr<storm::logic::Formula const>(
443 new storm::logic::BoundedUntilFormula(createBooleanLiteralFormula(true), subformula, lowerBounds, upperBounds, timeBoundReferences));
444 } else {
445 return std::shared_ptr<storm::logic::Formula const>(new storm::logic::EventuallyFormula(subformula, context));
446 }
447}
448
449std::shared_ptr<storm::logic::Formula const> FormulaParserGrammar::createGloballyFormula(std::shared_ptr<storm::logic::Formula const> const& subformula) const {
450 return std::shared_ptr<storm::logic::Formula const>(new storm::logic::GloballyFormula(subformula));
451}
452
453std::shared_ptr<storm::logic::Formula const> FormulaParserGrammar::createNextFormula(std::shared_ptr<storm::logic::Formula const> const& subformula) const {
454 return std::shared_ptr<storm::logic::Formula const>(new storm::logic::NextFormula(subformula));
455}
456
457std::shared_ptr<storm::logic::Formula const> FormulaParserGrammar::createUntilFormula(
458 std::shared_ptr<storm::logic::Formula const> const& leftSubformula,
459 boost::optional<std::vector<std::tuple<boost::optional<storm::logic::TimeBound>, boost::optional<storm::logic::TimeBound>,
460 std::shared_ptr<storm::logic::TimeBoundReference>>>> const& timeBounds,
461 std::shared_ptr<storm::logic::Formula const> const& rightSubformula) {
462 if (timeBounds && !timeBounds.get().empty()) {
463 std::vector<boost::optional<storm::logic::TimeBound>> lowerBounds, upperBounds;
464 std::vector<storm::logic::TimeBoundReference> timeBoundReferences;
465 for (auto const& timeBound : timeBounds.get()) {
466 lowerBounds.push_back(std::get<0>(timeBound));
467 upperBounds.push_back(std::get<1>(timeBound));
468 timeBoundReferences.emplace_back(*std::get<2>(timeBound));
469 }
470 return std::shared_ptr<storm::logic::Formula const>(
471 new storm::logic::BoundedUntilFormula(leftSubformula, rightSubformula, lowerBounds, upperBounds, timeBoundReferences));
472 } else {
473 return std::shared_ptr<storm::logic::Formula const>(new storm::logic::UntilFormula(leftSubformula, rightSubformula));
474 }
475}
476
477std::shared_ptr<storm::logic::Formula const> FormulaParserGrammar::createHOAPathFormula(std::string const& automatonFile) const {
478 return std::shared_ptr<storm::logic::Formula const>(new storm::logic::HOAPathFormula(automatonFile));
479}
480
481void FormulaParserGrammar::addHoaAPMapping(storm::logic::Formula const& hoaFormula, const std::string& ap,
482 std::shared_ptr<storm::logic::Formula const>& expression) const {
483 // taking a const Formula reference and doing static_ and const_cast from Formula to allow non-const access to
484 // qi::_val of the hoaPathFormula rule
485 storm::logic::HOAPathFormula& hoaFormula_ = static_cast<storm::logic::HOAPathFormula&>(const_cast<storm::logic::Formula&>(hoaFormula));
486 hoaFormula_.addAPMapping(ap, expression);
487}
488
489std::shared_ptr<storm::logic::Formula const> FormulaParserGrammar::createConditionalFormula(
490 std::shared_ptr<storm::logic::Formula const> const& leftSubformula, boost::optional<std::shared_ptr<storm::logic::Formula const>> const& rightSubformula,
491 storm::logic::FormulaContext context) const {
492 if (rightSubformula) {
493 return std::shared_ptr<storm::logic::Formula const>(new storm::logic::ConditionalFormula(leftSubformula, rightSubformula.get(), context));
494 } else {
495 // If there is no rhs, just return the lhs
496 return leftSubformula;
497 }
498}
499
500storm::logic::OperatorInformation FormulaParserGrammar::createOperatorInformation(boost::optional<storm::OptimizationDirection> const& optimizationDirection,
501 boost::optional<storm::logic::ComparisonType> const& comparisonType,
502 boost::optional<storm::expressions::Expression> const& threshold) const {
503 if (comparisonType && threshold) {
505 return storm::logic::OperatorInformation(optimizationDirection, storm::logic::Bound(comparisonType.get(), threshold.get()));
506 } else {
507 return storm::logic::OperatorInformation(optimizationDirection, boost::none);
508 }
509}
510
511std::shared_ptr<storm::logic::Formula const> FormulaParserGrammar::createOperatorFormula(storm::logic::FormulaContext const& context,
512 boost::optional<std::string> const& rewardModelName,
513 storm::logic::OperatorInformation const& operatorInformation,
514 std::shared_ptr<storm::logic::Formula const> const& subformula) {
515 switch (context) {
517 STORM_LOG_ASSERT(!rewardModelName, "Probability operator with reward information parsed");
518 return createProbabilityOperatorFormula(operatorInformation, subformula);
520 return createRewardOperatorFormula(rewardModelName, operatorInformation, subformula);
522 STORM_LOG_ASSERT(!rewardModelName, "LRA operator with reward information parsed");
523 return createLongRunAverageOperatorFormula(operatorInformation, subformula);
525 STORM_LOG_ASSERT(!rewardModelName, "Time operator with reward model name parsed");
526 return createTimeOperatorFormula(operatorInformation, subformula);
527 default:
528 STORM_LOG_THROW(false, storm::exceptions::WrongFormatException, "Unexpected formula context.");
529 }
530}
531
532std::shared_ptr<storm::logic::Formula const> FormulaParserGrammar::createLongRunAverageOperatorFormula(
533 storm::logic::OperatorInformation const& operatorInformation, std::shared_ptr<storm::logic::Formula const> const& subformula) const {
534 return std::shared_ptr<storm::logic::Formula const>(new storm::logic::LongRunAverageOperatorFormula(subformula, operatorInformation));
535}
536
537std::shared_ptr<storm::logic::Formula const> FormulaParserGrammar::createRewardOperatorFormula(
538 boost::optional<std::string> const& rewardModelName, storm::logic::OperatorInformation const& operatorInformation,
539 std::shared_ptr<storm::logic::Formula const> const& subformula) const {
540 return std::shared_ptr<storm::logic::Formula const>(new storm::logic::RewardOperatorFormula(subformula, rewardModelName, operatorInformation));
541}
542
543std::shared_ptr<storm::logic::Formula const> FormulaParserGrammar::createTimeOperatorFormula(
544 storm::logic::OperatorInformation const& operatorInformation, std::shared_ptr<storm::logic::Formula const> const& subformula) const {
545 return std::shared_ptr<storm::logic::Formula const>(new storm::logic::TimeOperatorFormula(subformula, operatorInformation));
546}
547
548std::shared_ptr<storm::logic::Formula const> FormulaParserGrammar::createProbabilityOperatorFormula(
549 storm::logic::OperatorInformation const& operatorInformation, std::shared_ptr<storm::logic::Formula const> const& subformula) {
550 return std::shared_ptr<storm::logic::Formula const>(new storm::logic::ProbabilityOperatorFormula(subformula, operatorInformation));
551}
552
553std::shared_ptr<storm::logic::Formula const> FormulaParserGrammar::createBinaryBooleanStateFormula(
554 std::shared_ptr<storm::logic::Formula const> const& leftSubformula, std::shared_ptr<storm::logic::Formula const> const& rightSubformula,
556 return std::shared_ptr<storm::logic::Formula const>(new storm::logic::BinaryBooleanStateFormula(operatorType, leftSubformula, rightSubformula));
557}
558
559std::shared_ptr<storm::logic::Formula const> FormulaParserGrammar::createUnaryBooleanStateFormula(
560 std::shared_ptr<storm::logic::Formula const> const& subformula, boost::optional<storm::logic::UnaryBooleanStateFormula::OperatorType> const& operatorType) {
561 if (operatorType) {
562 return std::shared_ptr<storm::logic::Formula const>(new storm::logic::UnaryBooleanStateFormula(operatorType.get(), subformula));
563 } else {
564 return subformula;
565 }
566}
567
568std::shared_ptr<storm::logic::Formula const> FormulaParserGrammar::createBinaryBooleanPathFormula(
569 std::shared_ptr<storm::logic::Formula const> const& leftSubformula, std::shared_ptr<storm::logic::Formula const> const& rightSubformula,
571 return std::shared_ptr<storm::logic::Formula const>(new storm::logic::BinaryBooleanPathFormula(operatorType, leftSubformula, rightSubformula));
572}
573
574std::shared_ptr<storm::logic::Formula const> FormulaParserGrammar::createUnaryBooleanPathFormula(
575 std::shared_ptr<storm::logic::Formula const> const& subformula, boost::optional<storm::logic::UnaryBooleanPathFormula::OperatorType> const& operatorType) {
576 if (operatorType) {
577 return std::shared_ptr<storm::logic::Formula const>(new storm::logic::UnaryBooleanPathFormula(operatorType.get(), subformula));
578 } else {
579 return subformula;
580 }
581}
582
583std::shared_ptr<storm::logic::Formula const> FormulaParserGrammar::createBinaryBooleanStateOrPathFormula(
584 std::shared_ptr<storm::logic::Formula const> const& leftSubformula, std::shared_ptr<storm::logic::Formula const> const& rightSubformula,
586 if (leftSubformula->isStateFormula() && rightSubformula->isStateFormula()) {
587 return createBinaryBooleanStateFormula(leftSubformula, rightSubformula, operatorType);
588 } else if (leftSubformula->isPathFormula() || rightSubformula->isPathFormula()) {
589 return createBinaryBooleanPathFormula(leftSubformula, rightSubformula, operatorType);
590 }
591 STORM_LOG_THROW(false, storm::exceptions::WrongFormatException, "Subformulas have unexpected type.");
592}
593
594std::shared_ptr<storm::logic::Formula const> FormulaParserGrammar::createUnaryBooleanStateOrPathFormula(
595 std::shared_ptr<storm::logic::Formula const> const& subformula, boost::optional<storm::logic::UnaryBooleanOperatorType> const& operatorType) {
596 if (subformula->isStateFormula()) {
597 return createUnaryBooleanStateFormula(subformula, operatorType);
598 } else if (subformula->isPathFormula()) {
599 return createUnaryBooleanPathFormula(subformula, operatorType);
600 }
601 STORM_LOG_THROW(false, storm::exceptions::WrongFormatException, "Subformulas have unexpected type.");
602}
603
604bool FormulaParserGrammar::isValidMultiBoundedPathFormulaOperand(std::shared_ptr<storm::logic::Formula const> const& operand) {
605 if (operand->isBoundedUntilFormula()) {
606 if (!operand->asBoundedUntilFormula().isMultiDimensional()) {
607 return true;
608 }
609 STORM_LOG_ERROR("Composition of multidimensional bounded until formula must consist of single dimension subformulas. Got '" << *operand
610 << "' instead.");
611 }
612 return false;
613}
614
615std::shared_ptr<storm::logic::Formula const> FormulaParserGrammar::createMultiBoundedPathFormula(
616 std::vector<std::shared_ptr<storm::logic::Formula const>> const& subformulas) {
617 std::vector<std::shared_ptr<storm::logic::Formula const>> leftSubformulas, rightSubformulas;
618 std::vector<boost::optional<storm::logic::TimeBound>> lowerBounds, upperBounds;
619 std::vector<storm::logic::TimeBoundReference> timeBoundReferences;
620 for (auto const& subformula : subformulas) {
621 STORM_LOG_THROW(subformula->isBoundedUntilFormula(), storm::exceptions::WrongFormatException,
622 "multi-path formulas require bounded until (or eventually) subformulae. Got '" << *subformula << "' instead.");
623 auto const& f = subformula->asBoundedUntilFormula();
624 STORM_LOG_THROW(!f.isMultiDimensional(), storm::exceptions::WrongFormatException,
625 "Composition of multidimensional bounded until formula must consist of single dimension subformulas. Got '" << f << "' instead.");
626 leftSubformulas.push_back(f.getLeftSubformula().asSharedPointer());
627 rightSubformulas.push_back(f.getRightSubformula().asSharedPointer());
628 if (f.hasLowerBound()) {
629 lowerBounds.emplace_back(storm::logic::TimeBound(f.isLowerBoundStrict(), f.getLowerBound()));
630 } else {
631 lowerBounds.emplace_back();
632 }
633 if (f.hasUpperBound()) {
634 upperBounds.emplace_back(storm::logic::TimeBound(f.isUpperBoundStrict(), f.getUpperBound()));
635 } else {
636 upperBounds.emplace_back();
637 }
638 timeBoundReferences.push_back(f.getTimeBoundReference());
639 }
640 return std::shared_ptr<storm::logic::Formula const>(
641 new storm::logic::BoundedUntilFormula(leftSubformulas, rightSubformulas, lowerBounds, upperBounds, timeBoundReferences));
642}
643
644std::shared_ptr<storm::logic::Formula const> FormulaParserGrammar::createMultiOperatorFormula(
645 std::vector<std::shared_ptr<storm::logic::Formula const>> const& subformulas) {
646 return std::shared_ptr<storm::logic::Formula const>(new storm::logic::MultiObjectiveFormula(subformulas));
647}
648
649storm::expressions::Variable FormulaParserGrammar::createQuantileBoundVariables(boost::optional<storm::solver::OptimizationDirection> const& dir,
650 std::string const& variableName) {
651 STORM_LOG_ASSERT(manager, "Mutable expression manager required to define quantile bound variable.");
653 if (manager->hasVariable(variableName)) {
654 var = manager->getVariable(variableName);
655 STORM_LOG_THROW(quantileFormulaVariables.count(var) > 0, storm::exceptions::WrongFormatException,
656 "Invalid quantile variable name '" << variableName << "' in quantile formula: variable already exists.");
657 } else {
658 var = manager->declareRationalVariable(variableName);
659 quantileFormulaVariables.insert(var);
660 }
661 STORM_LOG_WARN_COND(!dir.is_initialized(), "Optimization direction '"
662 << dir.get() << "' for quantile variable " << variableName
663 << " is ignored. This information will be derived from the subformula of the quantile.");
664 addIdentifierExpression(variableName, var);
665 return var;
666}
667
668std::shared_ptr<storm::logic::Formula const> FormulaParserGrammar::createQuantileFormula(std::vector<storm::expressions::Variable> const& boundVariables,
669 std::shared_ptr<storm::logic::Formula const> const& subformula) {
670 return std::shared_ptr<storm::logic::Formula const>(new storm::logic::QuantileFormula(boundVariables, subformula));
671}
672
673std::set<storm::expressions::Variable> FormulaParserGrammar::getUndefinedConstants(std::shared_ptr<storm::logic::Formula const> const& formula) const {
674 std::set<storm::expressions::Variable> result;
675 std::set<storm::expressions::Variable> usedVariables = formula->getUsedVariables();
676 std::set_intersection(usedVariables.begin(), usedVariables.end(), undefinedConstants.begin(), undefinedConstants.end(),
677 std::inserter(result, result.begin()));
678 return result;
679}
680
681storm::jani::Property FormulaParserGrammar::createProperty(boost::optional<std::string> const& propertyName, storm::modelchecker::FilterType const& filterType,
682 std::shared_ptr<storm::logic::Formula const> const& formula,
683 std::shared_ptr<storm::logic::Formula const> const& states) {
684 storm::jani::FilterExpression filterExpression(formula, filterType, states);
685
686 ++propertyCount;
687 if (propertyName) {
688 return storm::jani::Property(propertyName.get(), filterExpression, this->getUndefinedConstants(formula));
689 } else {
690 return storm::jani::Property(std::to_string(propertyCount - 1), filterExpression, this->getUndefinedConstants(formula));
691 }
692}
693
694storm::jani::Property FormulaParserGrammar::createPropertyWithDefaultFilterTypeAndStates(boost::optional<std::string> const& propertyName,
695 std::shared_ptr<storm::logic::Formula const> const& formula) {
696 ++propertyCount;
697 if (propertyName) {
698 return storm::jani::Property(propertyName.get(), formula, this->getUndefinedConstants(formula));
699 } else {
700 return storm::jani::Property(std::to_string(propertyCount), formula, this->getUndefinedConstants(formula));
701 }
702}
703
704storm::logic::PlayerCoalition FormulaParserGrammar::createPlayerCoalition(
705 std::vector<std::variant<std::string, storm::storage::PlayerIndex>> const& playerIds) const {
706 return storm::logic::PlayerCoalition(playerIds);
707}
708
709std::shared_ptr<storm::logic::Formula const> FormulaParserGrammar::createGameFormula(storm::logic::PlayerCoalition const& coalition,
710 std::shared_ptr<storm::logic::Formula const> const& subformula) const {
711 return std::shared_ptr<storm::logic::Formula const>(new storm::logic::GameFormula(coalition, subformula));
712}
713
714bool FormulaParserGrammar::isBooleanReturnType(std::shared_ptr<storm::logic::Formula const> const& formula, bool raiseErrorMessage) {
715 if (formula->hasQualitativeResult()) {
716 return true;
717 }
718 STORM_LOG_ERROR_COND(!raiseErrorMessage, "Formula " << *formula << " does not have a Boolean return type.");
719 return false;
720}
721
722bool FormulaParserGrammar::raiseAmbiguousNonAssociativeOperatorError(std::shared_ptr<storm::logic::Formula const> const& formula, std::string const& op) {
723 STORM_LOG_ERROR("Ambiguous use of non-associative operator '" << op << "' in formula '" << *formula << " U ... '");
724 return true;
725}
726
727} // namespace parser
728} // namespace storm
bool evaluateAsBool(Valuation const *valuation=nullptr) const
Evaluates the expression under the valuation of variables given by the valuation and returns the resu...
bool hasBooleanType() const
Retrieves whether the expression has a boolean return type.
bool isLiteral() const
Retrieves whether the expression is a literal.
std::string toString() const
Converts the expression into a string.
void addAPMapping(const std::string &ap, const std::shared_ptr< Formula const > &formula)
void setIdentifierMapping(qi::symbols< char, storm::expressions::Expression > const *identifiers_)
Sets an identifier mapping that is used to determine valid variables in the expression.
qi::symbols< char, storm::expressions::Expression > const & getIdentifiers() const
FormulaParserGrammar(std::shared_ptr< storm::expressions::ExpressionManager const > const &manager)
void addIdentifierExpression(std::string const &identifier, storm::expressions::Expression const &expression)
Adds an identifier and the expression it is supposed to be replaced with.
#define STORM_LOG_ERROR(message)
Definition logging.h:31
#define STORM_LOG_ASSERT(cond, message)
Definition macros.h:11
#define STORM_LOG_WARN_COND(cond, message)
Definition macros.h:38
#define STORM_LOG_ERROR_COND(cond, message)
Definition macros.h:52
#define STORM_LOG_THROW(cond, exception, message)
Definition macros.h:30
LabParser.cpp.
Definition cli.cpp:18