3#include <unordered_set>
23 std::ifstream inputFileStream;
29 std::string fileContent((std::istreambuf_iterator<char>(inputFileStream)), (std::istreambuf_iterator<char>()));
31 }
catch (storm::exceptions::WrongFormatException& e) {
35 }
catch (std::exception& e) {
47 bool hasByteOrderMark = input.size() >= 3 && input[0] ==
'\xEF' && input[1] ==
'\xBB' && input[2] ==
'\xBF';
61 storm::spirit_encoding::space_type space;
62 bool succeeded = qi::phrase_parse(iter, last, grammar, space | qi::lit(
"//") >> *(qi::char_ - (qi::eol | qi::eoi)) >> (qi::eol | qi::eoi), result);
63 STORM_LOG_THROW(succeeded, storm::exceptions::WrongFormatException,
"Parsing failed in first pass.");
70 grammar.moveToSecondRun();
71 succeeded = qi::phrase_parse(iter, last, grammar, space | qi::lit(
"//") >> *(qi::char_ - (qi::eol | qi::eoi)) >> (qi::eol | qi::eoi), result);
72 STORM_LOG_THROW(succeeded, storm::exceptions::WrongFormatException,
"Parsing failed in second pass.");
73 }
catch (qi::expectation_failure<PositionIteratorType>
const& e) {
75 std::size_t lineNumber = boost::spirit::get_line(e.first);
78 STORM_LOG_THROW(
false, storm::exceptions::WrongFormatException,
"Parsing error in line " << lineNumber <<
" of file " << filename <<
".");
86PrismParserGrammar::PrismParserGrammar(std::string
const& filename,
Iterator first,
bool prismCompatibility)
89 prismCompatibility(prismCompatibility),
92 manager(new
storm::expressions::ExpressionManager()),
95 boolExpression = (expression_[qi::_val = qi::_1])[qi::_pass = phoenix::bind(&PrismParserGrammar::isOfBoolType, phoenix::ref(*
this), qi::_val)];
96 boolExpression.name(
"boolean expression");
98 intExpression = (expression_[qi::_val = qi::_1])[qi::_pass = phoenix::bind(&PrismParserGrammar::isOfIntType, phoenix::ref(*
this), qi::_val)];
99 intExpression.name(
"integer expression");
101 numericalExpression = (expression_[qi::_val = qi::_1])[qi::_pass = phoenix::bind(&PrismParserGrammar::isOfNumericalType, phoenix::ref(*
this), qi::_val)];
102 numericalExpression.name(
"numerical expression");
105 identifier %= qi::as_string[qi::raw[qi::lexeme[((qi::alpha | qi::char_(
'_')) >> *(qi::alnum | qi::char_(
'_')))]]]
106 [qi::_pass = phoenix::bind(&PrismParserGrammar::isValidIdentifier, phoenix::ref(*
this), qi::_1)];
107 identifier.name(
"identifier");
110 freshIdentifier = (identifier[qi::_val = qi::_1])[qi::_pass = phoenix::bind(&PrismParserGrammar::isFreshIdentifier, phoenix::ref(*
this), qi::_1)];
111 freshIdentifier.name(
"fresh identifier");
113 modelTypeDefinition %= modelType_;
114 modelTypeDefinition.name(
"model type");
118 definedBooleanConstantDefinition =
119 (((qi::lit(
"const") >> qi::lit(
"bool")) > freshIdentifier) >>
120 (qi::lit(
"=") > boolExpression >
121 qi::lit(
";")))[qi::_val = phoenix::bind(&PrismParserGrammar::createDefinedBooleanConstant, phoenix::ref(*
this), qi::_1, qi::_2)];
122 definedBooleanConstantDefinition.name(
"defined boolean constant declaration");
124 definedIntegerConstantDefinition =
125 (((qi::lit(
"const") >> -qi::lit(
"int")) >> freshIdentifier) >>
126 (qi::lit(
"=") > intExpression > qi::lit(
";")))[qi::_val = phoenix::bind(&PrismParserGrammar::createDefinedIntegerConstant, phoenix::ref(*
this), qi::_1,
129 definedIntegerConstantDefinition.name(
"defined integer constant declaration");
131 definedDoubleConstantDefinition =
132 (((qi::lit(
"const") >> qi::lit(
"double")) > freshIdentifier) >>
133 (qi::lit(
"=") > numericalExpression >
134 qi::lit(
";")))[qi::_val = phoenix::bind(&PrismParserGrammar::createDefinedDoubleConstant, phoenix::ref(*
this), qi::_1, qi::_2)];
135 definedDoubleConstantDefinition.name(
"defined double constant declaration");
137 definedConstantDefinition %= (definedBooleanConstantDefinition | definedDoubleConstantDefinition | definedIntegerConstantDefinition);
138 definedConstantDefinition.name(
"defined constant definition");
141 undefinedBooleanConstantDefinition =
142 (((qi::lit(
"const") >> qi::lit(
"bool")) > freshIdentifier) >
143 qi::lit(
";"))[qi::_val = phoenix::bind(&PrismParserGrammar::createUndefinedBooleanConstant, phoenix::ref(*
this), qi::_1)];
144 undefinedBooleanConstantDefinition.name(
"undefined boolean constant declaration");
146 undefinedIntegerConstantDefinition =
147 (((qi::lit(
"const") >> -qi::lit(
"int")) > freshIdentifier) >
148 qi::lit(
";"))[qi::_val = phoenix::bind(&PrismParserGrammar::createUndefinedIntegerConstant, phoenix::ref(*
this), qi::_1)];
149 undefinedIntegerConstantDefinition.name(
"undefined integer constant declaration");
151 undefinedDoubleConstantDefinition =
152 (((qi::lit(
"const") >> qi::lit(
"double")) > freshIdentifier) >
153 qi::lit(
";"))[qi::_val = phoenix::bind(&PrismParserGrammar::createUndefinedDoubleConstant, phoenix::ref(*
this), qi::_1)];
154 undefinedDoubleConstantDefinition.name(
"undefined double constant definition");
156 undefinedConstantDefinition = (undefinedBooleanConstantDefinition | undefinedDoubleConstantDefinition |
157 undefinedIntegerConstantDefinition);
159 undefinedConstantDefinition.name(
"undefined constant definition");
162 formulaDefinitionRhs = (qi::lit(
"=") > qi::as_string[(+(qi::char_ - (qi::lit(
";") | qi::lit(
"endmodule"))))][qi::_val = qi::_1] > qi::lit(
";"));
163 formulaDefinitionRhs.name(
"formula defining expression");
165 formulaDefinition = (qi::lit(
"formula") > freshIdentifier >
166 formulaDefinitionRhs)[qi::_val = phoenix::bind(&PrismParserGrammar::createFormulaFirstRun, phoenix::ref(*
this), qi::_1, qi::_2)];
167 formulaDefinition.name(
"formula definition");
169 booleanVariableDefinition =
170 (((freshIdentifier > qi::lit(
":")) >> qi::lit(
"bool")) > -((qi::lit(
"init") > boolExpression[qi::_a = qi::_1]) | qi::attr(manager->boolean(
false))) >
171 qi::lit(
";"))[qi::_val = phoenix::bind(&PrismParserGrammar::createBooleanVariable, phoenix::ref(*
this), qi::_1, qi::_a)];
172 booleanVariableDefinition.name(
"boolean variable definition");
174 boundedIntegerVariableDefinition =
175 (((freshIdentifier > qi::lit(
":")) >> qi::lit(
"[")) > intExpression > qi::lit(
"..") > intExpression > qi::lit(
"]") >
176 -(qi::lit(
"init") > intExpression[qi::_a = qi::_1]) >
177 qi::lit(
";"))[qi::_val = phoenix::bind(&PrismParserGrammar::createIntegerVariable, phoenix::ref(*
this), qi::_1, qi::_2, qi::_3, qi::_a)];
178 boundedIntegerVariableDefinition.name(
"bounded integer variable definition");
180 unboundedIntegerVariableDefinition = (((freshIdentifier > qi::lit(
":")) >> qi::lit(
"int")) > -(qi::lit(
"init") > intExpression[qi::_a = qi::_1]) >
181 qi::lit(
";"))[qi::_val = phoenix::bind(&PrismParserGrammar::createIntegerVariable, phoenix::ref(*
this), qi::_1,
183 unboundedIntegerVariableDefinition.name(
"unbounded integer variable definition");
185 integerVariableDefinition = boundedIntegerVariableDefinition | unboundedIntegerVariableDefinition;
186 integerVariableDefinition.name(
"integer variable definition");
188 clockVariableDefinition = (((freshIdentifier > qi::lit(
":")) >> qi::lit(
"clock")) >
189 qi::lit(
";"))[qi::_val = phoenix::bind(&PrismParserGrammar::createClockVariable, phoenix::ref(*
this), qi::_1)];
190 clockVariableDefinition.name(
"clock variable definition");
192 variableDefinition = (booleanVariableDefinition[phoenix::push_back(qi::_r1, qi::_1)] | integerVariableDefinition[phoenix::push_back(qi::_r2, qi::_1)] |
193 clockVariableDefinition[phoenix::push_back(qi::_r3, qi::_1)]);
194 variableDefinition.name(
"variable declaration");
196 globalVariableDefinition =
200 globalVariableDefinition.name(
"global variable declaration list");
202 stateRewardDefinition = (boolExpression > qi::lit(
":") > numericalExpression >
203 qi::lit(
";"))[qi::_val = phoenix::bind(&PrismParserGrammar::createStateReward, phoenix::ref(*
this), qi::_1, qi::_2)];
204 stateRewardDefinition.name(
"state reward definition");
206 stateActionRewardDefinition =
207 (qi::lit(
"[") > -identifier > qi::lit(
"]") > boolExpression > qi::lit(
":") > numericalExpression >
208 qi::lit(
";"))[qi::_val = phoenix::bind(&PrismParserGrammar::createStateActionReward, phoenix::ref(*
this), qi::_1, qi::_2, qi::_3, qi::_r1)];
209 stateActionRewardDefinition.name(
"state action reward definition");
211 transitionRewardDefinition =
212 ((qi::lit(
"[") > -identifier[qi::_a = qi::_1] > qi::lit(
"]") > boolExpression[qi::_b = qi::_1]) >>
213 (qi::lit(
"->") > boolExpression[qi::_c = qi::_1] > qi::lit(
":") > numericalExpression[qi::_d = qi::_1] >
214 qi::lit(
";")))[qi::_val = phoenix::bind(&PrismParserGrammar::createTransitionReward, phoenix::ref(*
this), qi::_a, qi::_b, qi::_c, qi::_d, qi::_r1)];
215 transitionRewardDefinition.name(
"transition reward definition");
217 freshRewardModelName = (identifier[qi::_val = qi::_1])[qi::_pass = phoenix::bind(&PrismParserGrammar::isFreshRewardModelName, phoenix::ref(*
this), qi::_1)];
218 freshRewardModelName.name(
"fresh reward model name");
220 rewardModelDefinition =
221 (qi::lit(
"rewards") > -(qi::lit(
"\"") > freshRewardModelName[qi::_a = qi::_1] > qi::lit(
"\"")) >
222 +(transitionRewardDefinition(qi::_r1)[phoenix::push_back(qi::_d, qi::_1)] | stateActionRewardDefinition(qi::_r1)[phoenix::push_back(qi::_c, qi::_1)] |
223 stateRewardDefinition[phoenix::push_back(qi::_b, qi::_1)]) >
224 qi::lit(
"endrewards"))[qi::_val = phoenix::bind(&PrismParserGrammar::createRewardModel, phoenix::ref(*
this), qi::_a, qi::_b, qi::_c, qi::_d)];
225 rewardModelDefinition.name(
"reward model definition");
227 initialStatesConstruct =
228 (qi::lit(
"init") > boolExpression >
229 qi::lit(
"endinit"))[qi::_pass = phoenix::bind(&PrismParserGrammar::addInitialStatesConstruct, phoenix::ref(*
this), qi::_1, qi::_r1)];
230 initialStatesConstruct.name(
"initial construct");
232 observablesConstruct = (qi::lit(
"observables") > (identifier % qi::lit(
",")) >
233 qi::lit(
"endobservables"))[phoenix::bind(&PrismParserGrammar::createObservablesList, phoenix::ref(*
this), qi::_1)];
234 observablesConstruct.name(
"observables construct");
236 invariantConstruct = (qi::lit(
"invariant") > boolExpression > qi::lit(
"endinvariant"))[qi::_val = qi::_1];
237 invariantConstruct.name(
"invariant construct");
239 knownModuleName = (identifier[qi::_val = qi::_1])[qi::_pass = phoenix::bind(&PrismParserGrammar::isKnownModuleName, phoenix::ref(*
this), qi::_1,
false)];
240 knownModuleName.name(
"existing module name");
242 freshModuleName = (identifier[qi::_val = qi::_1])[qi::_pass = phoenix::bind(&PrismParserGrammar::isFreshModuleName, phoenix::ref(*
this), qi::_1)];
243 freshModuleName.name(
"fresh module name");
245 systemCompositionConstruct =
246 (qi::lit(
"system") > parallelComposition >
247 qi::lit(
"endsystem"))[phoenix::bind(&PrismParserGrammar::addSystemCompositionConstruct, phoenix::ref(*
this), qi::_1, qi::_r1)];
248 systemCompositionConstruct.name(
"system composition construct");
250 actionNameList %= identifier[phoenix::insert(qi::_val, qi::_1)] >> *(
"," >> identifier[phoenix::insert(qi::_val, qi::_1)]);
251 actionNameList.name(
"action list");
253 parallelComposition =
254 hidingOrRenamingComposition[qi::_val = qi::_1] >>
255 *((interleavingParallelComposition > hidingOrRenamingComposition)[qi::_val = phoenix::bind(&PrismParserGrammar::createInterleavingParallelComposition,
256 phoenix::ref(*
this), qi::_val, qi::_1)] |
257 (synchronizingParallelComposition > hidingOrRenamingComposition)[qi::_val = phoenix::bind(&PrismParserGrammar::createSynchronizingParallelComposition,
258 phoenix::ref(*
this), qi::_val, qi::_1)] |
259 (restrictedParallelComposition > hidingOrRenamingComposition)[qi::_val = phoenix::bind(&PrismParserGrammar::createRestrictedParallelComposition,
260 phoenix::ref(*
this), qi::_val, qi::_1, qi::_2)]);
261 parallelComposition.name(
"parallel composition");
263 synchronizingParallelComposition = qi::lit(
"||");
264 synchronizingParallelComposition.name(
"synchronizing parallel composition");
266 interleavingParallelComposition = qi::lit(
"|||");
267 interleavingParallelComposition.name(
"interleaving parallel composition");
269 restrictedParallelComposition = qi::lit(
"|[") > actionNameList > qi::lit(
"]|");
270 restrictedParallelComposition.name(
"restricted parallel composition");
272 hidingOrRenamingComposition = hidingComposition | renamingComposition | atomicComposition;
273 hidingOrRenamingComposition.name(
"hiding/renaming composition");
276 (atomicComposition >>
277 (qi::lit(
"/") > (qi::lit(
"{") > actionNameList >
278 qi::lit(
"}"))))[qi::_val = phoenix::bind(&PrismParserGrammar::createHidingComposition, phoenix::ref(*
this), qi::_1, qi::_2)];
279 hidingComposition.name(
"hiding composition");
282 +(identifier >> (qi::lit(
"<-") >> identifier))[phoenix::insert(qi::_val, phoenix::construct<std::pair<std::string, std::string>>(qi::_1, qi::_2))];
283 actionRenamingList.name(
"action renaming list");
285 renamingComposition =
286 (atomicComposition >>
288 (actionRenamingList > qi::lit(
"}"))))[qi::_val = phoenix::bind(&PrismParserGrammar::createRenamingComposition, phoenix::ref(*
this), qi::_1, qi::_2)];
289 renamingComposition.name(
"renaming composition");
291 atomicComposition = (qi::lit(
"(") > parallelComposition > qi::lit(
")")) | moduleComposition;
292 atomicComposition.name(
"atomic composition");
294 moduleComposition = identifier[qi::_val = phoenix::bind(&PrismParserGrammar::createModuleComposition, phoenix::ref(*
this), qi::_1)];
295 moduleComposition.name(
"module composition");
297 freshLabelName = (identifier[qi::_val = qi::_1])[qi::_pass = phoenix::bind(&PrismParserGrammar::isFreshLabelName, phoenix::ref(*
this), qi::_1)];
298 freshLabelName.name(
"fresh label name");
300 labelDefinition = (qi::lit(
"label") > -qi::lit(
"\"") > freshLabelName > -qi::lit(
"\"") > qi::lit(
"=") > boolExpression >
301 qi::lit(
";"))[qi::_val = phoenix::bind(&PrismParserGrammar::createLabel, phoenix::ref(*
this), qi::_1, qi::_2)];
302 labelDefinition.name(
"label definition");
304 freshObservationLabelName =
305 (identifier[qi::_val = qi::_1])[qi::_pass = phoenix::bind(&PrismParserGrammar::isFreshObservationLabelName, phoenix::ref(*
this), qi::_1)];
306 freshObservationLabelName.name(
"fresh observable name");
308 observableDefinition =
309 (qi::lit(
"observable") > -qi::lit(
"\"") > freshObservationLabelName > -qi::lit(
"\"") > qi::lit(
"=") > (intExpression | boolExpression) >
310 qi::lit(
";"))[qi::_val = phoenix::bind(&PrismParserGrammar::createObservationLabel, phoenix::ref(*
this), qi::_1, qi::_2)];
311 observableDefinition.name(
"observable definition");
313 assignmentDefinition = ((qi::lit(
"(") >> identifier >> qi::lit(
"'")) > qi::lit(
"=") > expression_ >
314 qi::lit(
")"))[qi::_val = phoenix::bind(&PrismParserGrammar::createAssignment, phoenix::ref(*
this), qi::_1, qi::_2)];
315 assignmentDefinition.name(
"assignment");
317 assignmentDefinitionList =
318 (assignmentDefinition %
"&")[qi::_val = qi::_1] | (qi::lit(
"true"))[qi::_val = phoenix::construct<std::vector<storm::prism::Assignment>>()];
319 assignmentDefinitionList.name(
"assignment list");
322 (assignmentDefinitionList[qi::_val = phoenix::bind(&PrismParserGrammar::createUpdate, phoenix::ref(*
this), manager->rational(1), qi::_1, qi::_r1)] |
323 ((numericalExpression > qi::lit(
":") >
324 assignmentDefinitionList)[qi::_val = phoenix::bind(&PrismParserGrammar::createUpdate, phoenix::ref(*
this), qi::_1, qi::_2, qi::_r1)]));
325 updateDefinition.name(
"update");
327 updateListDefinition %= +updateDefinition(qi::_r1) %
"+";
328 updateListDefinition.name(
"update list");
331 commandDefinition = (((qi::lit(
"[") > -identifier > qi::lit(
"]")) | (qi::lit(
"<") > -identifier > qi::lit(
">")[qi::_a =
true])) >
332 +(qi::char_ - (qi::lit(
";") | qi::lit(
"endmodule"))) >
333 qi::lit(
";"))[qi::_val = phoenix::bind(&PrismParserGrammar::createDummyCommand, phoenix::ref(*
this), qi::_1, qi::_r1)];
334 commandDefinition.name(
"command definition");
338 ((qi::lit(
"module") > freshModuleName > *(variableDefinition(qi::_a, qi::_b, qi::_c))) > -invariantConstruct > (*commandDefinition(qi::_r1)) >
339 qi::lit(
"endmodule"))[qi::_val = phoenix::bind(&PrismParserGrammar::createModule, phoenix::ref(*
this), qi::_1, qi::_a, qi::_b, qi::_c, qi::_2, qi::_3,
341 moduleDefinition.name(
"module definition");
343 freshPlayerName = (identifier[qi::_val = qi::_1])[qi::_pass = phoenix::bind(&PrismParserGrammar::isFreshPlayerName, phoenix::ref(*
this), qi::_1)];
344 freshPlayerName.name(
"fresh player name");
346 playerControlledActionName =
347 ((qi::lit(
"[") > identifier >
348 qi::lit(
"]"))[qi::_val = qi::_1])[qi::_pass = phoenix::bind(&PrismParserGrammar::isKnownActionName, phoenix::ref(*
this), qi::_1,
true)];
349 playerControlledActionName.name(
"player controlled action name");
351 playerControlledModuleName =
352 (identifier[qi::_val = qi::_1])[qi::_pass = phoenix::bind(&PrismParserGrammar::isKnownModuleName, phoenix::ref(*
this), qi::_1,
true)];
353 playerControlledModuleName.name(
"player controlled module name");
356 (qi::lit(
"player") > freshPlayerName[qi::_a = qi::_1] >
357 +((playerControlledActionName[phoenix::push_back(qi::_c, qi::_1)] | playerControlledModuleName[phoenix::push_back(qi::_b, qi::_1)]) %
',') >
358 qi::lit(
"endplayer"))[qi::_val = phoenix::bind(&PrismParserGrammar::createPlayer, phoenix::ref(*
this), qi::_a, qi::_b, qi::_c)];
359 playerConstruct.name(
"player construct");
363 ((identifier > qi::lit(
"=") > identifier)[phoenix::insert(qi::_a, phoenix::construct<std::pair<std::string, std::string>>(qi::_1, qi::_2))] %
",") >
364 qi::lit(
"]"))[qi::_val = phoenix::bind(&PrismParserGrammar::createModuleRenaming, phoenix::ref(*
this), qi::_a)];
365 moduleRenaming.name(
"Module renaming list");
368 (((qi::lit(
"module") > freshModuleName) >> qi::lit(
"=")) > knownModuleName[qi::_a = qi::_1] >
369 (moduleRenaming[qi::_b = qi::_1])[qi::_pass =
370 phoenix::bind(&PrismParserGrammar::isValidModuleRenaming, phoenix::ref(*
this), qi::_a, qi::_b, qi::_r1)] >
371 qi::lit(
"endmodule"))[qi::_val = phoenix::bind(&PrismParserGrammar::createRenamedModule, phoenix::ref(*
this), qi::_1, qi::_a, qi::_b, qi::_r1)];
372 renamedModule.name(
"module definition via renaming");
375 (qi::eps[phoenix::bind(&PrismParserGrammar::removeInitialConstruct, phoenix::ref(*
this), phoenix::ref(globalProgramInformation))] >
376 modelTypeDefinition[phoenix::bind(&PrismParserGrammar::setModelType, phoenix::ref(*
this), phoenix::ref(globalProgramInformation), qi::_1)] >
377 -observablesConstruct >
382 globalVariableDefinition(phoenix::ref(globalProgramInformation)) |
383 (renamedModule(phoenix::ref(globalProgramInformation)) | moduleDefinition(phoenix::ref(globalProgramInformation)))[phoenix::push_back(
385 initialStatesConstruct(phoenix::ref(globalProgramInformation)) |
386 rewardModelDefinition(phoenix::ref(globalProgramInformation))[phoenix::push_back(
392 playerConstruct(phoenix::ref(globalProgramInformation))[phoenix::push_back(
394 -(systemCompositionConstruct(phoenix::ref(globalProgramInformation))) >
395 qi::eoi)[qi::_val = phoenix::bind(&PrismParserGrammar::createProgram, phoenix::ref(*
this), phoenix::ref(globalProgramInformation))];
396 start.name(
"probabilistic program");
399 auto setLocationInfoFunction = this->annotate(qi::_val, qi::_1, qi::_3);
400 qi::on_success(undefinedBooleanConstantDefinition, setLocationInfoFunction);
401 qi::on_success(undefinedIntegerConstantDefinition, setLocationInfoFunction);
402 qi::on_success(undefinedDoubleConstantDefinition, setLocationInfoFunction);
403 qi::on_success(definedBooleanConstantDefinition, setLocationInfoFunction);
404 qi::on_success(definedIntegerConstantDefinition, setLocationInfoFunction);
405 qi::on_success(definedDoubleConstantDefinition, setLocationInfoFunction);
406 qi::on_success(booleanVariableDefinition, setLocationInfoFunction);
407 qi::on_success(integerVariableDefinition, setLocationInfoFunction);
408 qi::on_success(clockVariableDefinition, setLocationInfoFunction);
409 qi::on_success(moduleDefinition, setLocationInfoFunction);
410 qi::on_success(moduleRenaming, setLocationInfoFunction);
411 qi::on_success(renamedModule, setLocationInfoFunction);
412 qi::on_success(formulaDefinition, setLocationInfoFunction);
413 qi::on_success(rewardModelDefinition, setLocationInfoFunction);
414 qi::on_success(labelDefinition, setLocationInfoFunction);
415 qi::on_success(observableDefinition, setLocationInfoFunction);
416 qi::on_success(commandDefinition, setLocationInfoFunction);
417 qi::on_success(updateDefinition, setLocationInfoFunction);
418 qi::on_success(assignmentDefinition, setLocationInfoFunction);
421 qi::on_error<qi::fail>(start, handler(qi::_1, qi::_2, qi::_3, qi::_4));
424void PrismParserGrammar::moveToSecondRun() {
427 STORM_LOG_THROW(observables.empty(), storm::exceptions::WrongFormatException,
428 "Some variables marked as observable, but never declared, e.g. " << *observables.begin());
431 (((qi::lit(
"[") > -identifier > qi::lit(
"]")) | (qi::lit(
"<") > -identifier > qi::lit(
">")[qi::_a =
true])) > *expressionParser > qi::lit(
"->") >
432 updateListDefinition(qi::_r1) >
433 qi::lit(
";"))[qi::_val = phoenix::bind(&PrismParserGrammar::createCommand, phoenix::ref(*
this), qi::_a, qi::_1, qi::_2, qi::_3, qi::_r1)];
435 auto setLocationInfoFunction = this->annotate(qi::_val, qi::_1, qi::_3);
436 qi::on_success(commandDefinition, setLocationInfoFunction);
438 formulaDefinition = (qi::lit(
"formula") > identifier > qi::lit(
"=") > *expressionParser >
439 qi::lit(
";"))[qi::_val = phoenix::bind(&PrismParserGrammar::createFormulaSecondRun, phoenix::ref(*
this), qi::_1, qi::_2)];
440 formulaDefinition.name(
"formula definition");
441 this->secondRun =
true;
442 this->expressionParser->setIdentifierMapping(&this->identifiers_);
447 createFormulaIdentifiers(this->globalProgramInformation.
formulas);
452void PrismParserGrammar::createFormulaIdentifiers(std::vector<storm::prism::Formula>
const& formulas) {
453 STORM_LOG_THROW(formulas.size() == this->formulaExpressions.size(), storm::exceptions::UnexpectedException,
454 "Unexpected number of formulas and formula expressions");
455 this->formulaOrder.clear();
461 bool progress =
true;
464 for (uint64_t formulaIndex = unprocessed.getNextSetIndex(0); formulaIndex < formulas.size();
465 formulaIndex = unprocessed.getNextSetIndex(formulaIndex + 1)) {
469 unprocessed.set(formulaIndex,
false);
470 formulaOrder.push_back(formulaIndex);
474 variable = manager->declareIntegerVariable(formulas[formulaIndex].getName());
476 variable = manager->declareBooleanVariable(formulas[formulaIndex].getName());
479 "Unexpected type for formula expression of formula " << formulas[formulaIndex].getName());
480 variable = manager->declareRationalVariable(formulas[formulaIndex].getName());
482 this->identifiers_.add(formulas[formulaIndex].getName(), variable.
getExpression());
483 }
catch (storm::exceptions::InvalidArgumentException
const& e) {
485 "Parsing error in " << this->getFilename() <<
": illegal identifier '" << formulas[formulaIndex].getName() <<
"' at line '"
486 << formulas[formulaIndex].getLineNumber());
488 this->expressionParser->setIdentifierMapping(&this->identifiers_);
492 if (!unprocessed.empty()) {
493 for (
auto formulaIndex : unprocessed) {
494 STORM_LOG_ERROR(
"Parsing error in " << this->getFilename() <<
": Invalid expression for formula '" << formulas[formulaIndex].getName()
495 <<
"' at line '" << formulas[formulaIndex].getLineNumber() <<
"':\n\t" << formulaExpressions[formulaIndex]);
497 STORM_LOG_THROW(unprocessed.getNumberOfSetBits() == 1, storm::exceptions::WrongFormatException,
498 "Unable to parse expressions for " << unprocessed.getNumberOfSetBits() <<
" formulas. This could be due to circular dependencies");
500 "Unable to parse expression for formula '" << formulas[unprocessed.getNextSetIndex(0)].getName() <<
"'.");
504void PrismParserGrammar::allowDoubleLiterals(
bool flag) {
505 this->expressionParser->setAcceptDoubleLiterals(flag);
508std::string
const& PrismParserGrammar::getFilename()
const {
509 return this->filename;
512bool PrismParserGrammar::isValidIdentifier(std::string
const& identifier) {
513 if (this->keywords_.find(identifier) !=
nullptr) {
519bool PrismParserGrammar::isKnownModuleName(std::string
const& moduleName,
bool inSecondRun) {
520 if ((this->secondRun == inSecondRun) && this->globalProgramInformation.
moduleToIndexMap.count(moduleName) == 0) {
521 STORM_LOG_ERROR(
"Parsing error in " << this->getFilename() <<
": Unknown module '" << moduleName <<
"'.");
527bool PrismParserGrammar::isFreshModuleName(std::string
const& moduleName) {
528 if (!this->secondRun && this->globalProgramInformation.
moduleToIndexMap.count(moduleName) != 0) {
529 STORM_LOG_ERROR(
"Parsing error in " << this->getFilename() <<
": Duplicate module name '" << moduleName <<
"'.");
535bool PrismParserGrammar::isKnownActionName(std::string
const& actionName,
bool inSecondRun) {
536 if ((this->secondRun == inSecondRun) && this->globalProgramInformation.
actionIndices.count(actionName) == 0) {
537 STORM_LOG_ERROR(
"Parsing error in " << this->getFilename() <<
": Unknown action label '" << actionName <<
"'.");
543bool PrismParserGrammar::isFreshIdentifier(std::string
const& identifier) {
544 if (!this->secondRun && this->manager->hasVariable(identifier)) {
545 STORM_LOG_ERROR(
"Parsing error in " << this->getFilename() <<
": Duplicate identifier '" << identifier <<
"'.");
551bool PrismParserGrammar::isFreshLabelName(std::string
const& labelName) {
552 if (!this->secondRun) {
553 for (
auto const& existingLabel : this->globalProgramInformation.labels) {
554 if (labelName == existingLabel.getName()) {
555 STORM_LOG_ERROR(
"Parsing error in " << this->getFilename() <<
": Duplicate label name '" << identifier <<
"'.");
563bool PrismParserGrammar::isFreshObservationLabelName(std::string
const& labelName) {
564 if (!this->secondRun) {
565 for (
auto const& existingLabel : this->globalProgramInformation.observationLabels) {
566 if (labelName == existingLabel.getName()) {
567 STORM_LOG_ERROR(
"Parsing error in " << this->getFilename() <<
": Duplicate observable name '" << identifier <<
"'.");
575bool PrismParserGrammar::isFreshRewardModelName(std::string
const& rewardModelName) {
576 if (!this->secondRun) {
577 for (
auto const& existingRewardModel : this->globalProgramInformation.rewardModels) {
578 if (rewardModelName == existingRewardModel.getName()) {
579 STORM_LOG_ERROR(
"Parsing error in " << this->getFilename() <<
": Duplicate reward model name '" << identifier <<
"'.");
587bool PrismParserGrammar::isFreshPlayerName(std::string
const& playerName) {
604 GlobalProgramInformation& globalProgramInformation) {
605 STORM_LOG_THROW(!globalProgramInformation.hasInitialConstruct, storm::exceptions::WrongFormatException,
606 "Parsing error in " << this->getFilename() <<
": Program must not define two initial constructs.");
607 if (globalProgramInformation.hasInitialConstruct) {
610 globalProgramInformation.hasInitialConstruct =
true;
615bool PrismParserGrammar::addSystemCompositionConstruct(std::shared_ptr<storm::prism::Composition>
const& composition,
616 GlobalProgramInformation& globalProgramInformation) {
623 "Parsing error in " << this->getFilename() <<
": Program must not set model type multiple times.");
624 globalProgramInformation.modelType = modelType;
627std::shared_ptr<storm::prism::Composition> PrismParserGrammar::createModuleComposition(std::string
const& moduleName)
const {
628 return std::make_shared<storm::prism::ModuleComposition>(moduleName);
631std::shared_ptr<storm::prism::Composition> PrismParserGrammar::createRenamingComposition(std::shared_ptr<storm::prism::Composition>
const& subcomposition,
632 std::map<std::string, std::string>
const& renaming)
const {
633 return std::make_shared<storm::prism::RenamingComposition>(subcomposition, renaming);
636std::shared_ptr<storm::prism::Composition> PrismParserGrammar::createHidingComposition(std::shared_ptr<storm::prism::Composition>
const& subcomposition,
637 std::set<std::string>
const& actionsToHide)
const {
638 return std::make_shared<storm::prism::HidingComposition>(subcomposition, actionsToHide);
641std::shared_ptr<storm::prism::Composition> PrismParserGrammar::createSynchronizingParallelComposition(
642 std::shared_ptr<storm::prism::Composition>
const& left, std::shared_ptr<storm::prism::Composition>
const& right)
const {
643 return std::make_shared<storm::prism::SynchronizingParallelComposition>(left, right);
646std::shared_ptr<storm::prism::Composition> PrismParserGrammar::createInterleavingParallelComposition(
647 std::shared_ptr<storm::prism::Composition>
const& left, std::shared_ptr<storm::prism::Composition>
const& right)
const {
648 return std::make_shared<storm::prism::InterleavingParallelComposition>(left, right);
651std::shared_ptr<storm::prism::Composition> PrismParserGrammar::createRestrictedParallelComposition(
652 std::shared_ptr<storm::prism::Composition>
const& left, std::set<std::string>
const& synchronizingActions,
653 std::shared_ptr<storm::prism::Composition>
const& right)
const {
654 return std::make_shared<storm::prism::RestrictedParallelComposition>(left, synchronizingActions, right);
657storm::prism::Constant PrismParserGrammar::createUndefinedBooleanConstant(std::string
const& newConstant)
const {
658 if (!this->secondRun) {
661 this->identifiers_.add(newConstant, newVariable.
getExpression());
662 }
catch (storm::exceptions::InvalidArgumentException
const& e) {
664 "Parsing error in " << this->getFilename() <<
": illegal identifier '" << newConstant <<
"'.");
670storm::prism::Constant PrismParserGrammar::createUndefinedIntegerConstant(std::string
const& newConstant)
const {
671 if (!this->secondRun) {
674 this->identifiers_.add(newConstant, newVariable.
getExpression());
675 }
catch (storm::exceptions::InvalidArgumentException
const& e) {
677 "Parsing error in " << this->getFilename() <<
": illegal identifier '" << newConstant <<
"'.");
683storm::prism::Constant PrismParserGrammar::createUndefinedDoubleConstant(std::string
const& newConstant)
const {
684 if (!this->secondRun) {
687 this->identifiers_.add(newConstant, newVariable.
getExpression());
688 }
catch (storm::exceptions::InvalidArgumentException
const& e) {
690 "Parsing error in " << this->getFilename() <<
": illegal identifier '" << newConstant <<
"'.");
697 if (!this->secondRun) {
700 this->identifiers_.add(newConstant, newVariable.
getExpression());
701 }
catch (storm::exceptions::InvalidArgumentException
const& e) {
703 "Parsing error in " << this->getFilename() <<
": illegal identifier '" << newConstant <<
"'.");
710 if (!this->secondRun) {
713 this->identifiers_.add(newConstant, newVariable.
getExpression());
714 }
catch (storm::exceptions::InvalidArgumentException
const& e) {
716 "Parsing error in " << this->getFilename() <<
": illegal identifier '" << newConstant <<
"'.");
723 if (!this->secondRun) {
726 this->identifiers_.add(newConstant, newVariable.
getExpression());
727 }
catch (storm::exceptions::InvalidArgumentException
const& e) {
729 "Parsing error in " << this->getFilename() <<
": illegal identifier '" << newConstant <<
"'.");
735storm::prism::Formula PrismParserGrammar::createFormulaFirstRun(std::string
const& formulaName, std::string
const& expression) {
738 STORM_LOG_ASSERT(!this->secondRun,
"This constructor should have only been called during the first run.");
739 formulaExpressions.push_back(expression);
745 STORM_LOG_ASSERT(this->secondRun,
"This constructor should have only been called during the second run.");
758storm::prism::RewardModel PrismParserGrammar::createRewardModel(std::string
const& rewardModelName, std::vector<storm::prism::StateReward>
const& stateRewards,
759 std::vector<storm::prism::StateActionReward>
const& stateActionRewards,
760 std::vector<storm::prism::TransitionReward>
const& transitionRewards)
const {
761 return storm::prism::RewardModel(rewardModelName, stateRewards, stateActionRewards, transitionRewards, this->getFilename());
766 if (this->secondRun) {
776 GlobalProgramInformation& globalProgramInformation)
const {
777 if (this->secondRun) {
778 std::string realActionName = actionName ? actionName.get() :
"";
780 auto const& nameIndexPair = globalProgramInformation.actionIndices.find(realActionName);
781 STORM_LOG_THROW(nameIndexPair != globalProgramInformation.actionIndices.end(), storm::exceptions::WrongFormatException,
782 "Action reward refers to illegal action '" << realActionName <<
"'.");
793 GlobalProgramInformation& globalProgramInformation)
const {
794 if (this->secondRun) {
795 std::string realActionName = actionName ? actionName.get() :
"";
797 auto const& nameIndexPair = globalProgramInformation.actionIndices.find(realActionName);
798 STORM_LOG_THROW(nameIndexPair != globalProgramInformation.actionIndices.end(), storm::exceptions::WrongFormatException,
799 "Transition reward refers to illegal action '" << realActionName <<
"'.");
801 rewardValueExpression, this->getFilename());
812 std::vector<storm::prism::Assignment>
const& assignments,
813 GlobalProgramInformation& globalProgramInformation)
const {
814 ++globalProgramInformation.currentUpdateIndex;
815 return storm::prism::Update(globalProgramInformation.currentUpdateIndex - 1, likelihoodExpression, assignments, this->getFilename());
818storm::prism::Command PrismParserGrammar::createCommand(
bool markovian, boost::optional<std::string>
const& actionName,
820 GlobalProgramInformation& globalProgramInformation)
const {
821 ++globalProgramInformation.currentCommandIndex;
822 std::string realActionName = actionName ? actionName.get() :
"";
824 uint_fast64_t actionIndex = 0;
827 auto nameIndexPair = globalProgramInformation.actionIndices.find(realActionName);
828 if (nameIndexPair == globalProgramInformation.actionIndices.end()) {
829 std::size_t nextIndex = globalProgramInformation.actionIndices.size();
830 globalProgramInformation.actionIndices.emplace(realActionName, nextIndex);
831 actionIndex = nextIndex;
833 actionIndex = nameIndexPair->second;
835 return storm::prism::Command(globalProgramInformation.currentCommandIndex - 1, markovian, actionIndex, realActionName, guardExpression, updates,
836 this->getFilename());
839storm::prism::Command PrismParserGrammar::createDummyCommand(boost::optional<std::string>
const& actionName,
840 GlobalProgramInformation& globalProgramInformation)
const {
841 STORM_LOG_ASSERT(!this->secondRun,
"Dummy procedure must not be called in second run.");
842 std::string realActionName = actionName ? actionName.get() :
"";
845 auto nameIndexPair = globalProgramInformation.actionIndices.find(realActionName);
846 if (nameIndexPair == globalProgramInformation.actionIndices.end()) {
847 std::size_t nextIndex = globalProgramInformation.actionIndices.size();
848 globalProgramInformation.actionIndices.emplace(realActionName, nextIndex);
856 if (!this->secondRun) {
859 this->identifiers_.add(variableName, newVariable.
getExpression());
860 }
catch (storm::exceptions::InvalidArgumentException
const& e) {
862 "Parsing error in " << this->getFilename() <<
": illegal identifier '" << variableName <<
"'.");
865 bool observable = this->observables.count(variableName) > 0;
867 this->observables.erase(variableName);
875 if (!this->secondRun) {
878 this->identifiers_.add(variableName, newVariable.
getExpression());
879 }
catch (storm::exceptions::InvalidArgumentException
const& e) {
881 "Parsing error in " << this->getFilename() <<
": illegal identifier '" << variableName <<
"'.");
884 bool observable = this->observables.count(variableName) > 0;
886 this->observables.erase(variableName);
889 return storm::prism::IntegerVariable(manager->getVariable(variableName), lowerBoundExpression, upperBoundExpression, initialValueExpression, observable,
890 this->getFilename());
894 if (!this->secondRun) {
897 this->identifiers_.add(variableName, newVariable.
getExpression());
898 }
catch (storm::exceptions::InvalidArgumentException
const& e) {
900 "Parsing error in " << this->getFilename() <<
": illegal identifier '" << variableName <<
"'.");
903 bool observable = this->observables.count(variableName) > 0;
905 this->observables.erase(variableName);
911void PrismParserGrammar::createObservablesList(std::vector<std::string>
const& observables) {
912 this->observables.insert(observables.begin(), observables.end());
916storm::prism::Player PrismParserGrammar::createPlayer(std::string
const& playerName, std::vector<std::string>
const& moduleNames,
917 std::vector<std::string>
const& actionNames) {
918 if (this->secondRun) {
919 std::unordered_set<std::string> controlledModules;
920 std::unordered_set<std::string> controlledActions;
921 for (
auto const& moduleName : moduleNames) {
922 auto moduleIndexPair = globalProgramInformation.moduleToIndexMap.find(moduleName);
923 STORM_LOG_ASSERT(moduleIndexPair != globalProgramInformation.moduleToIndexMap.end(),
924 "Parsing error in " << this->getFilename() <<
" for player " << playerName <<
": No module named '" << moduleName <<
"' present.");
925 controlledModules.insert(moduleIndexPair->first);
926 bool moduleNotYetControlled = globalProgramInformation.playerControlledModules.insert(moduleIndexPair->second).second;
927 STORM_LOG_THROW(moduleNotYetControlled, storm::exceptions::WrongFormatException,
928 "Parsing error in " << this->getFilename() <<
" for player " << playerName <<
": Module '" << moduleName
929 <<
"' already controlled by another player.");
931 for (std::string actionName : actionNames) {
932 auto actionIndexPair = globalProgramInformation.actionIndices.find(actionName);
933 STORM_LOG_ASSERT(actionIndexPair != globalProgramInformation.actionIndices.end(),
934 "Parsing error in " << this->getFilename() <<
" for player " << playerName <<
": No action named '" << actionName <<
"' present.");
935 controlledActions.insert(actionIndexPair->first);
936 bool actionNotYetControlled = globalProgramInformation.playerControlledActions.insert(actionIndexPair->second).second;
937 STORM_LOG_THROW(actionNotYetControlled, storm::exceptions::WrongFormatException,
938 "Parsing error in " << this->getFilename() <<
" for player " << playerName <<
": Command '" << actionName
939 <<
"' already controlled by another player.");
947storm::prism::Module PrismParserGrammar::createModule(std::string
const& moduleName, std::vector<storm::prism::BooleanVariable>
const& booleanVariables,
948 std::vector<storm::prism::IntegerVariable>
const& integerVariables,
949 std::vector<storm::prism::ClockVariable>
const& clockVariables,
950 boost::optional<storm::expressions::Expression>
const& invariant,
951 std::vector<storm::prism::Command>
const& commands,
952 GlobalProgramInformation& globalProgramInformation)
const {
953 if (!this->secondRun) {
954 globalProgramInformation.moduleToIndexMap[moduleName] = globalProgramInformation.modules.size();
957 STORM_LOG_ASSERT(!this->secondRun || globalProgramInformation.moduleToIndexMap.count(moduleName) > 0,
"Module name '" << moduleName <<
"' was not found.");
958 STORM_LOG_ASSERT(!this->secondRun || globalProgramInformation.moduleToIndexMap[moduleName] == globalProgramInformation.modules.size(),
959 "The index for module '" << moduleName <<
"' does not match the index from the first parsing run.");
961 invariant.is_initialized() ? invariant.get() :
storm::expressions::Expression(), commands, this->getFilename());
965 GlobalProgramInformation
const& globalProgramInformation)
const {
966 if (!this->secondRun) {
967 auto const& renaming = moduleRenaming.
getRenaming();
968 auto const& moduleIndexPair = globalProgramInformation.moduleToIndexMap.find(oldModuleName);
969 if (moduleIndexPair == globalProgramInformation.moduleToIndexMap.end()) {
970 STORM_LOG_ERROR(
"Parsing error in " << this->getFilename() <<
": No module named '" << oldModuleName <<
"' to rename.");
973 storm::prism::Module const& moduleToRename = globalProgramInformation.modules[moduleIndexPair->second];
975 for (
auto const& variable : moduleToRename.getBooleanVariables()) {
976 auto const& renamingPair = renaming.find(variable.
getName());
977 if (renamingPair == renaming.end()) {
978 STORM_LOG_ERROR(
"Parsing error in renaming of module '" << oldModuleName <<
"': Boolean variable '" << variable.
getName()
979 <<
"' was not renamed.");
983 for (
auto const& variable : moduleToRename.getIntegerVariables()) {
984 auto const& renamingPair = renaming.find(variable.
getName());
985 if (renamingPair == renaming.end()) {
986 STORM_LOG_ERROR(
"Parsing error in renaming of module '" << oldModuleName <<
"': Integer variable '" << variable.
getName()
987 <<
"' was not renamed.");
991 for (
auto const& variable : moduleToRename.getClockVariables()) {
992 auto const& renamingPair = renaming.find(variable.
getName());
993 if (renamingPair == renaming.end()) {
994 STORM_LOG_ERROR(
"Parsing error in renaming of module '" << oldModuleName <<
"': Clock variable '" << variable.
getName()
995 <<
"' was not renamed.");
1007storm::prism::Module PrismParserGrammar::createRenamedModule(std::string
const& newModuleName, std::string
const& oldModuleName,
1009 GlobalProgramInformation& globalProgramInformation)
const {
1011 auto const& moduleIndexPair = globalProgramInformation.moduleToIndexMap.find(oldModuleName);
1012 STORM_LOG_THROW(moduleIndexPair != globalProgramInformation.moduleToIndexMap.end(), storm::exceptions::WrongFormatException,
1013 "Parsing error in " << this->getFilename() <<
": No module named '" << oldModuleName <<
"' to rename.");
1014 storm::prism::Module const& moduleToRename = globalProgramInformation.modules[moduleIndexPair->second];
1016 "Parsing error in " << this->getFilename() <<
": The module '" << newModuleName <<
"' can not be created from module '" << oldModuleName
1017 <<
"' through module renaming because '" << oldModuleName <<
"' is also a renamed module. Create '" << newModuleName
1018 <<
"' via a renaming from base module '" << moduleToRename.
getBaseModule() <<
"' instead.");
1019 auto const& renaming = moduleRenaming.
getRenaming();
1020 if (!this->secondRun) {
1022 globalProgramInformation.moduleToIndexMap[newModuleName] = globalProgramInformation.modules.size();
1026 for (
auto const& variable : moduleToRename.getBooleanVariables()) {
1027 auto const& renamingPair = renaming.find(variable.
getName());
1028 STORM_LOG_THROW(renamingPair != renaming.end(), storm::exceptions::WrongFormatException,
1029 "Parsing error in " << this->getFilename() <<
": Boolean variable '" << variable.
getName() <<
" was not renamed.");
1031 this->identifiers_.add(renamingPair->second, renamedVariable.
getExpression());
1032 if (this->observables.count(renamingPair->second) > 0) {
1033 this->observables.erase(renamingPair->second);
1036 for (
auto const& variable : moduleToRename.getIntegerVariables()) {
1037 auto const& renamingPair = renaming.find(variable.
getName());
1038 STORM_LOG_THROW(renamingPair != renaming.end(), storm::exceptions::WrongFormatException,
1039 "Parsing error in " << this->getFilename() <<
": Integer variable '" << variable.
getName() <<
" was not renamed.");
1041 this->identifiers_.add(renamingPair->second, renamedVariable.
getExpression());
1042 if (this->observables.count(renamingPair->second) > 0) {
1043 this->observables.erase(renamingPair->second);
1046 for (
auto const& variable : moduleToRename.getClockVariables()) {
1047 auto const& renamingPair = renaming.find(variable.
getName());
1048 STORM_LOG_THROW(renamingPair != renaming.end(), storm::exceptions::WrongFormatException,
1049 "Parsing error in " << this->getFilename() <<
": Clock variable '" << variable.
getName() <<
" was not renamed.");
1051 this->identifiers_.add(renamingPair->second, renamedVariable.
getExpression());
1052 if (this->observables.count(renamingPair->second) > 0) {
1053 this->observables.erase(renamingPair->second);
1057 for (
auto const& command : moduleToRename.getCommands()) {
1058 std::string newActionName = command.getActionName();
1059 auto const& renamingPair = renaming.find(command.getActionName());
1060 if (renamingPair != renaming.end()) {
1061 newActionName = renamingPair->second;
1065 auto nameIndexPair = globalProgramInformation.actionIndices.find(newActionName);
1066 if (nameIndexPair == globalProgramInformation.actionIndices.end()) {
1067 std::size_t nextIndex = globalProgramInformation.actionIndices.size();
1068 globalProgramInformation.actionIndices.emplace(newActionName, nextIndex);
1076 STORM_LOG_ASSERT(globalProgramInformation.moduleToIndexMap.count(newModuleName) > 0,
"Module name '" << newModuleName <<
"' was not found.");
1077 STORM_LOG_ASSERT(globalProgramInformation.moduleToIndexMap[newModuleName] == globalProgramInformation.modules.size(),
1078 "The index for module " << newModuleName <<
" does not match the index from the first parsing run.");
1081 std::map<storm::expressions::Variable, storm::expressions::Expression> expressionRenaming;
1082 for (
auto const& namePair : renaming) {
1085 if (substitutedExpression !=
nullptr) {
1086 expressionRenaming.emplace(manager->getVariable(namePair.first), *substitutedExpression);
1091 std::vector<storm::prism::BooleanVariable> booleanVariables;
1092 for (
auto const& variable : moduleToRename.getBooleanVariables()) {
1093 auto const& renamingPair = renaming.find(variable.
getName());
1094 STORM_LOG_THROW(renamingPair != renaming.end(), storm::exceptions::WrongFormatException,
1095 "Parsing error in " << this->getFilename() <<
": Boolean variable '" << variable.
getName() <<
" was not renamed.");
1096 bool observable = this->observables.count(renamingPair->second) > 0;
1098 this->observables.erase(renamingPair->second);
1101 manager->getVariable(renamingPair->second),
1102 variable.hasInitialValue() ? variable.getInitialValueExpression().substitute(expressionRenaming) : variable.getInitialValueExpression(),
1103 observable, this->getFilename(), moduleRenaming.getLineNumber()));
1107 std::vector<storm::prism::IntegerVariable> integerVariables;
1108 for (
auto const& variable : moduleToRename.getIntegerVariables()) {
1109 auto const& renamingPair = renaming.find(variable.
getName());
1110 STORM_LOG_THROW(renamingPair != renaming.end(), storm::exceptions::WrongFormatException,
1111 "Parsing error in " << this->getFilename() <<
": Integer variable '" << variable.
getName() <<
" was not renamed.");
1112 bool observable = this->observables.count(renamingPair->second) > 0;
1114 this->observables.erase(renamingPair->second);
1117 manager->getVariable(renamingPair->second), variable.getLowerBoundExpression().substitute(expressionRenaming),
1118 variable.getUpperBoundExpression().substitute(expressionRenaming),
1119 variable.hasInitialValue() ? variable.getInitialValueExpression().substitute(expressionRenaming) : variable.getInitialValueExpression(),
1120 observable, this->getFilename(), moduleRenaming.getLineNumber()));
1124 std::vector<storm::prism::ClockVariable> clockVariables;
1125 for (
auto const& variable : moduleToRename.getClockVariables()) {
1126 auto const& renamingPair = renaming.find(variable.
getName());
1127 STORM_LOG_THROW(renamingPair != renaming.end(), storm::exceptions::WrongFormatException,
1128 "Parsing error in " << this->getFilename() <<
": Clock variable '" << variable.
getName() <<
" was not renamed.");
1129 bool observable = this->observables.count(renamingPair->second) > 0;
1131 this->observables.erase(renamingPair->second);
1133 clockVariables.push_back(
1144 std::vector<storm::prism::Command> commands;
1145 for (
auto const& command : moduleToRename.getCommands()) {
1146 std::vector<storm::prism::Update> updates;
1147 for (
auto const& update : command.getUpdates()) {
1148 std::vector<storm::prism::Assignment> assignments;
1149 for (
auto const& assignment : update.getAssignments()) {
1150 auto const& renamingPair = renaming.find(assignment.getVariableName());
1151 if (renamingPair != renaming.end()) {
1152 assignments.emplace_back(manager->getVariable(renamingPair->second), assignment.getExpression().substitute(expressionRenaming),
1155 assignments.emplace_back(assignment.getVariable(), assignment.getExpression().substitute(expressionRenaming), this->getFilename(),
1159 updates.emplace_back(globalProgramInformation.currentUpdateIndex, update.getLikelihoodExpression().substitute(expressionRenaming), assignments,
1161 ++globalProgramInformation.currentUpdateIndex;
1164 std::string newActionName = command.getActionName();
1165 auto const& renamingPair = renaming.find(command.getActionName());
1166 if (renamingPair != renaming.end()) {
1167 newActionName = renamingPair->second;
1170 uint_fast64_t actionIndex = 0;
1171 auto nameIndexPair = globalProgramInformation.actionIndices.find(newActionName);
1172 if (nameIndexPair == globalProgramInformation.actionIndices.end()) {
1173 std::size_t nextIndex = globalProgramInformation.actionIndices.size();
1174 globalProgramInformation.actionIndices.emplace(newActionName, nextIndex);
1175 actionIndex = nextIndex;
1177 actionIndex = nameIndexPair->second;
1180 commands.emplace_back(globalProgramInformation.currentCommandIndex, command.isMarkovian(), actionIndex, newActionName,
1181 command.getGuardExpression().substitute(expressionRenaming), updates, this->getFilename(), moduleRenaming.
getLineNumber());
1182 ++globalProgramInformation.currentCommandIndex;
1185 return storm::prism::Module(newModuleName, booleanVariables, integerVariables, clockVariables, invariant, commands, oldModuleName, renaming);
1189storm::prism::Program PrismParserGrammar::createProgram(GlobalProgramInformation
const& globalProgramInformation)
const {
1192 STORM_LOG_WARN(
"Program does not specify model type. Implicitly assuming 'mdp'.");
1197 std::vector<storm::prism::Formula> orderedFormulas;
1198 if (this->secondRun) {
1199 orderedFormulas.reserve(globalProgramInformation.formulas.size());
1200 for (uint64_t
const& i : formulaOrder) {
1201 orderedFormulas.push_back(std::move(globalProgramInformation.formulas[i]));
1206 manager, finalModelType, globalProgramInformation.constants, globalProgramInformation.globalBooleanVariables,
1207 globalProgramInformation.globalIntegerVariables, orderedFormulas, globalProgramInformation.players, globalProgramInformation.modules,
1208 globalProgramInformation.actionIndices, globalProgramInformation.rewardModels, globalProgramInformation.labels,
1209 globalProgramInformation.observationLabels,
1210 secondRun && !globalProgramInformation.hasInitialConstruct ? boost::none :
boost::make_optional(globalProgramInformation.initialConstruct),
1211 globalProgramInformation.systemCompositionConstruct, prismCompatibility, this->getFilename(), 1, this->secondRun);
1214void PrismParserGrammar::removeInitialConstruct(GlobalProgramInformation& globalProgramInformation)
const {
boost::spirit::line_pos_iterator< BaseIteratorType > PositionIteratorType
PositionIteratorType Iterator
VariableExpression const & asVariableExpression() const
bool hasNumericalType() const
Retrieves whether the expression has a numerical return type, i.e., integer or double.
bool hasBooleanType() const
Retrieves whether the expression has a boolean return type.
bool hasIntegerType() const
Retrieves whether the expression has an integral return type.
BaseExpression const & getBaseExpression() const
Retrieves the base expression underlying this expression object.
Expression substitute(std::map< Variable, Expression > const &variableToExpressionMap) const
Substitutes all occurrences of the variables according to the given map.
bool isInitialized() const
Checks whether the object encapsulates a base-expression.
Variable const & getVariable() const
Retrieves the variable associated with this expression.
storm::expressions::Expression getExpression() const
Retrieves an expression that represents the variable.
std::string const & getName() const
Retrieves the name of the variable.
static storm::prism::Program parseFromString(std::string const &input, std::string const &filename, bool prismCompatability=false)
Parses the given input stream into the PRISM storage classes assuming it complies with the PRISM synt...
static storm::prism::Program parse(std::string const &filename, bool prismCompatability=false)
Parses the given file into the PRISM storage classes assuming it complies with the PRISM syntax.
std::string const & getBaseModule() const
If the module was created via renaming, this method retrieves the name of the module that was used as...
storm::expressions::Expression const & getInvariant() const
Returns the specified invariant (only relevant for PTA models)
bool isRenamedFromModule() const
Retrieves whether this module was created from another module via renaming.
bool hasInvariant() const
Returns true, if an invariant was specified (only relevant for PTA models)
std::map< std::string, std::string > const & getRenaming() const
If the module was created via renaming, this method returns the applied renaming of identifiers used ...
ModelType
An enum for the different model types.
bool hasInitialConstruct() const
Retrieves whether the program specifies an initial construct.
A bit vector that is internally represented as a vector of 64-bit values.
#define STORM_LOG_WARN(message)
#define STORM_LOG_DEBUG(message)
#define STORM_LOG_TRACE(message)
#define STORM_LOG_ERROR(message)
#define STORM_LOG_ASSERT(cond, message)
#define STORM_LOG_THROW(cond, exception, message)
void closeFile(std::ofstream &stream)
Close the given file after writing.
void openFile(std::string const &filepath, std::ofstream &filestream, bool append=false, bool silent=false)
Open the given file for writing.