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");
321 likelihoodDefinition =
322 (numericalExpression >
324 (qi::lit(
"[") > numericalExpression > qi::lit(
",") > numericalExpression > qi::lit(
"]") >
325 qi::lit(
":"))[qi::_val = phoenix::construct<typename storm::prism::Update::ExpressionPair>(qi::_1, qi::_2)];
328 (assignmentDefinitionList[qi::_val = phoenix::bind(&PrismParserGrammar::createUpdate, phoenix::ref(*
this),
330 ((likelihoodDefinition >
331 assignmentDefinitionList)[qi::_val = phoenix::bind(&PrismParserGrammar::createUpdate, phoenix::ref(*
this), qi::_1, qi::_2, qi::_r1)]));
332 updateDefinition.name(
"update");
334 updateListDefinition %= +updateDefinition(qi::_r1) %
"+";
335 updateListDefinition.name(
"update list");
338 commandDefinition = (((qi::lit(
"[") > -identifier > qi::lit(
"]")) | (qi::lit(
"<") > -identifier > qi::lit(
">")[qi::_a =
true])) >
339 +(qi::char_ - (qi::lit(
";") | qi::lit(
"endmodule"))) >
340 qi::lit(
";"))[qi::_val = phoenix::bind(&PrismParserGrammar::createDummyCommand, phoenix::ref(*
this), qi::_1, qi::_r1)];
341 commandDefinition.name(
"command definition");
345 ((qi::lit(
"module") > freshModuleName > *(variableDefinition(qi::_a, qi::_b, qi::_c))) > -invariantConstruct > (*commandDefinition(qi::_r1)) >
346 qi::lit(
"endmodule"))[qi::_val = phoenix::bind(&PrismParserGrammar::createModule, phoenix::ref(*
this), qi::_1, qi::_a, qi::_b, qi::_c, qi::_2, qi::_3,
348 moduleDefinition.name(
"module definition");
350 freshPlayerName = (identifier[qi::_val = qi::_1])[qi::_pass = phoenix::bind(&PrismParserGrammar::isFreshPlayerName, phoenix::ref(*
this), qi::_1)];
351 freshPlayerName.name(
"fresh player name");
353 playerControlledActionName =
354 ((qi::lit(
"[") > identifier >
355 qi::lit(
"]"))[qi::_val = qi::_1])[qi::_pass = phoenix::bind(&PrismParserGrammar::isKnownActionName, phoenix::ref(*
this), qi::_1,
true)];
356 playerControlledActionName.name(
"player controlled action name");
358 playerControlledModuleName =
359 (identifier[qi::_val = qi::_1])[qi::_pass = phoenix::bind(&PrismParserGrammar::isKnownModuleName, phoenix::ref(*
this), qi::_1,
true)];
360 playerControlledModuleName.name(
"player controlled module name");
363 (qi::lit(
"player") > freshPlayerName[qi::_a = qi::_1] >
364 +((playerControlledActionName[phoenix::push_back(qi::_c, qi::_1)] | playerControlledModuleName[phoenix::push_back(qi::_b, qi::_1)]) %
',') >
365 qi::lit(
"endplayer"))[qi::_val = phoenix::bind(&PrismParserGrammar::createPlayer, phoenix::ref(*
this), qi::_a, qi::_b, qi::_c)];
366 playerConstruct.name(
"player construct");
370 ((identifier > qi::lit(
"=") > identifier)[phoenix::insert(qi::_a, phoenix::construct<std::pair<std::string, std::string>>(qi::_1, qi::_2))] %
",") >
371 qi::lit(
"]"))[qi::_val = phoenix::bind(&PrismParserGrammar::createModuleRenaming, phoenix::ref(*
this), qi::_a)];
372 moduleRenaming.name(
"Module renaming list");
375 (((qi::lit(
"module") > freshModuleName) >> qi::lit(
"=")) > knownModuleName[qi::_a = qi::_1] >
376 (moduleRenaming[qi::_b = qi::_1])[qi::_pass =
377 phoenix::bind(&PrismParserGrammar::isValidModuleRenaming, phoenix::ref(*
this), qi::_a, qi::_b, qi::_r1)] >
378 qi::lit(
"endmodule"))[qi::_val = phoenix::bind(&PrismParserGrammar::createRenamedModule, phoenix::ref(*
this), qi::_1, qi::_a, qi::_b, qi::_r1)];
379 renamedModule.name(
"module definition via renaming");
382 (qi::eps[phoenix::bind(&PrismParserGrammar::removeInitialConstruct, phoenix::ref(*
this), phoenix::ref(globalProgramInformation))] >
383 modelTypeDefinition[phoenix::bind(&PrismParserGrammar::setModelType, phoenix::ref(*
this), phoenix::ref(globalProgramInformation), qi::_1)] >
384 -observablesConstruct >
389 globalVariableDefinition(phoenix::ref(globalProgramInformation)) |
390 (renamedModule(phoenix::ref(globalProgramInformation)) | moduleDefinition(phoenix::ref(globalProgramInformation)))[phoenix::push_back(
392 initialStatesConstruct(phoenix::ref(globalProgramInformation)) |
393 rewardModelDefinition(phoenix::ref(globalProgramInformation))[phoenix::push_back(
399 playerConstruct(phoenix::ref(globalProgramInformation))[phoenix::push_back(
401 -(systemCompositionConstruct(phoenix::ref(globalProgramInformation))) >
402 qi::eoi)[qi::_val = phoenix::bind(&PrismParserGrammar::createProgram, phoenix::ref(*
this), phoenix::ref(globalProgramInformation))];
403 start.name(
"probabilistic program");
406 auto setLocationInfoFunction = this->annotate(qi::_val, qi::_1, qi::_3);
407 qi::on_success(undefinedBooleanConstantDefinition, setLocationInfoFunction);
408 qi::on_success(undefinedIntegerConstantDefinition, setLocationInfoFunction);
409 qi::on_success(undefinedDoubleConstantDefinition, setLocationInfoFunction);
410 qi::on_success(definedBooleanConstantDefinition, setLocationInfoFunction);
411 qi::on_success(definedIntegerConstantDefinition, setLocationInfoFunction);
412 qi::on_success(definedDoubleConstantDefinition, setLocationInfoFunction);
413 qi::on_success(booleanVariableDefinition, setLocationInfoFunction);
414 qi::on_success(integerVariableDefinition, setLocationInfoFunction);
415 qi::on_success(clockVariableDefinition, setLocationInfoFunction);
416 qi::on_success(moduleDefinition, setLocationInfoFunction);
417 qi::on_success(moduleRenaming, setLocationInfoFunction);
418 qi::on_success(renamedModule, setLocationInfoFunction);
419 qi::on_success(formulaDefinition, setLocationInfoFunction);
420 qi::on_success(rewardModelDefinition, setLocationInfoFunction);
421 qi::on_success(labelDefinition, setLocationInfoFunction);
422 qi::on_success(observableDefinition, setLocationInfoFunction);
423 qi::on_success(commandDefinition, setLocationInfoFunction);
424 qi::on_success(updateDefinition, setLocationInfoFunction);
425 qi::on_success(assignmentDefinition, setLocationInfoFunction);
428 qi::on_error<qi::fail>(start, handler(qi::_1, qi::_2, qi::_3, qi::_4));
431void PrismParserGrammar::moveToSecondRun() {
434 STORM_LOG_THROW(observables.empty(), storm::exceptions::WrongFormatException,
435 "Some variables marked as observable, but never declared, e.g. " << *observables.begin());
438 (((qi::lit(
"[") > -identifier > qi::lit(
"]")) | (qi::lit(
"<") > -identifier > qi::lit(
">")[qi::_a =
true])) > *expressionParser > qi::lit(
"->") >
439 updateListDefinition(qi::_r1) >
440 qi::lit(
";"))[qi::_val = phoenix::bind(&PrismParserGrammar::createCommand, phoenix::ref(*
this), qi::_a, qi::_1, qi::_2, qi::_3, qi::_r1)];
442 auto setLocationInfoFunction = this->annotate(qi::_val, qi::_1, qi::_3);
443 qi::on_success(commandDefinition, setLocationInfoFunction);
445 formulaDefinition = (qi::lit(
"formula") > identifier > qi::lit(
"=") > *expressionParser >
446 qi::lit(
";"))[qi::_val = phoenix::bind(&PrismParserGrammar::createFormulaSecondRun, phoenix::ref(*
this), qi::_1, qi::_2)];
447 formulaDefinition.name(
"formula definition");
448 this->secondRun =
true;
449 this->expressionParser->setIdentifierMapping(&this->identifiers_);
454 createFormulaIdentifiers(this->globalProgramInformation.
formulas);
459void PrismParserGrammar::createFormulaIdentifiers(std::vector<storm::prism::Formula>
const& formulas) {
460 STORM_LOG_THROW(formulas.size() == this->formulaExpressions.size(), storm::exceptions::UnexpectedException,
461 "Unexpected number of formulas and formula expressions");
462 this->formulaOrder.clear();
468 bool progress =
true;
471 for (uint64_t formulaIndex = unprocessed.getNextSetIndex(0); formulaIndex < formulas.size();
472 formulaIndex = unprocessed.getNextSetIndex(formulaIndex + 1)) {
476 unprocessed.set(formulaIndex,
false);
477 formulaOrder.push_back(formulaIndex);
481 variable = manager->declareIntegerVariable(formulas[formulaIndex].getName());
483 variable = manager->declareBooleanVariable(formulas[formulaIndex].getName());
486 "Unexpected type for formula expression of formula " << formulas[formulaIndex].getName());
487 variable = manager->declareRationalVariable(formulas[formulaIndex].getName());
489 this->identifiers_.add(formulas[formulaIndex].getName(), variable.
getExpression());
490 }
catch (storm::exceptions::InvalidArgumentException
const& e) {
492 "Parsing error in " << this->getFilename() <<
": illegal identifier '" << formulas[formulaIndex].getName() <<
"' at line '"
493 << formulas[formulaIndex].getLineNumber());
495 this->expressionParser->setIdentifierMapping(&this->identifiers_);
499 if (!unprocessed.empty()) {
500 for (
auto formulaIndex : unprocessed) {
501 STORM_LOG_ERROR(
"Parsing error in " << this->getFilename() <<
": Invalid expression for formula '" << formulas[formulaIndex].getName()
502 <<
"' at line '" << formulas[formulaIndex].getLineNumber() <<
"':\n\t" << formulaExpressions[formulaIndex]);
504 STORM_LOG_THROW(unprocessed.getNumberOfSetBits() == 1, storm::exceptions::WrongFormatException,
505 "Unable to parse expressions for " << unprocessed.getNumberOfSetBits() <<
" formulas. This could be due to circular dependencies");
507 "Unable to parse expression for formula '" << formulas[unprocessed.getNextSetIndex(0)].getName() <<
"'.");
511void PrismParserGrammar::allowDoubleLiterals(
bool flag) {
512 this->expressionParser->setAcceptDoubleLiterals(flag);
515std::string
const& PrismParserGrammar::getFilename()
const {
516 return this->filename;
519bool PrismParserGrammar::isValidIdentifier(std::string
const& identifier) {
520 if (this->keywords_.find(identifier) !=
nullptr) {
526bool PrismParserGrammar::isKnownModuleName(std::string
const& moduleName,
bool inSecondRun) {
527 if ((this->secondRun == inSecondRun) && this->globalProgramInformation.
moduleToIndexMap.count(moduleName) == 0) {
528 STORM_LOG_ERROR(
"Parsing error in " << this->getFilename() <<
": Unknown module '" << moduleName <<
"'.");
534bool PrismParserGrammar::isFreshModuleName(std::string
const& moduleName) {
535 if (!this->secondRun && this->globalProgramInformation.
moduleToIndexMap.count(moduleName) != 0) {
536 STORM_LOG_ERROR(
"Parsing error in " << this->getFilename() <<
": Duplicate module name '" << moduleName <<
"'.");
542bool PrismParserGrammar::isKnownActionName(std::string
const& actionName,
bool inSecondRun) {
543 if ((this->secondRun == inSecondRun) && this->globalProgramInformation.
actionIndices.count(actionName) == 0) {
544 STORM_LOG_ERROR(
"Parsing error in " << this->getFilename() <<
": Unknown action label '" << actionName <<
"'.");
550bool PrismParserGrammar::isFreshIdentifier(std::string
const& identifier) {
551 if (!this->secondRun && this->manager->hasVariable(identifier)) {
552 STORM_LOG_ERROR(
"Parsing error in " << this->getFilename() <<
": Duplicate identifier '" << identifier <<
"'.");
558bool PrismParserGrammar::isFreshLabelName(std::string
const& labelName) {
559 if (!this->secondRun) {
560 for (
auto const& existingLabel : this->globalProgramInformation.labels) {
561 if (labelName == existingLabel.getName()) {
562 STORM_LOG_ERROR(
"Parsing error in " << this->getFilename() <<
": Duplicate label name '" << identifier <<
"'.");
570bool PrismParserGrammar::isFreshObservationLabelName(std::string
const& labelName) {
571 if (!this->secondRun) {
572 for (
auto const& existingLabel : this->globalProgramInformation.observationLabels) {
573 if (labelName == existingLabel.getName()) {
574 STORM_LOG_ERROR(
"Parsing error in " << this->getFilename() <<
": Duplicate observable name '" << identifier <<
"'.");
582bool PrismParserGrammar::isFreshRewardModelName(std::string
const& rewardModelName) {
583 if (!this->secondRun) {
584 for (
auto const& existingRewardModel : this->globalProgramInformation.rewardModels) {
585 if (rewardModelName == existingRewardModel.getName()) {
586 STORM_LOG_ERROR(
"Parsing error in " << this->getFilename() <<
": Duplicate reward model name '" << identifier <<
"'.");
594bool PrismParserGrammar::isFreshPlayerName(std::string
const& playerName) {
611 GlobalProgramInformation& globalProgramInformation) {
612 STORM_LOG_THROW(!globalProgramInformation.hasInitialConstruct, storm::exceptions::WrongFormatException,
613 "Parsing error in " << this->getFilename() <<
": Program must not define two initial constructs.");
614 if (globalProgramInformation.hasInitialConstruct) {
617 globalProgramInformation.hasInitialConstruct =
true;
622bool PrismParserGrammar::addSystemCompositionConstruct(std::shared_ptr<storm::prism::Composition>
const& composition,
623 GlobalProgramInformation& globalProgramInformation) {
630 "Parsing error in " << this->getFilename() <<
": Program must not set model type multiple times.");
631 globalProgramInformation.modelType = modelType;
634std::shared_ptr<storm::prism::Composition> PrismParserGrammar::createModuleComposition(std::string
const& moduleName)
const {
635 return std::make_shared<storm::prism::ModuleComposition>(moduleName);
638std::shared_ptr<storm::prism::Composition> PrismParserGrammar::createRenamingComposition(std::shared_ptr<storm::prism::Composition>
const& subcomposition,
639 std::map<std::string, std::string>
const& renaming)
const {
640 return std::make_shared<storm::prism::RenamingComposition>(subcomposition, renaming);
643std::shared_ptr<storm::prism::Composition> PrismParserGrammar::createHidingComposition(std::shared_ptr<storm::prism::Composition>
const& subcomposition,
644 std::set<std::string>
const& actionsToHide)
const {
645 return std::make_shared<storm::prism::HidingComposition>(subcomposition, actionsToHide);
648std::shared_ptr<storm::prism::Composition> PrismParserGrammar::createSynchronizingParallelComposition(
649 std::shared_ptr<storm::prism::Composition>
const& left, std::shared_ptr<storm::prism::Composition>
const& right)
const {
650 return std::make_shared<storm::prism::SynchronizingParallelComposition>(left, right);
653std::shared_ptr<storm::prism::Composition> PrismParserGrammar::createInterleavingParallelComposition(
654 std::shared_ptr<storm::prism::Composition>
const& left, std::shared_ptr<storm::prism::Composition>
const& right)
const {
655 return std::make_shared<storm::prism::InterleavingParallelComposition>(left, right);
658std::shared_ptr<storm::prism::Composition> PrismParserGrammar::createRestrictedParallelComposition(
659 std::shared_ptr<storm::prism::Composition>
const& left, std::set<std::string>
const& synchronizingActions,
660 std::shared_ptr<storm::prism::Composition>
const& right)
const {
661 return std::make_shared<storm::prism::RestrictedParallelComposition>(left, synchronizingActions, right);
664storm::prism::Constant PrismParserGrammar::createUndefinedBooleanConstant(std::string
const& newConstant)
const {
665 if (!this->secondRun) {
668 this->identifiers_.add(newConstant, newVariable.
getExpression());
669 }
catch (storm::exceptions::InvalidArgumentException
const& e) {
671 "Parsing error in " << this->getFilename() <<
": illegal identifier '" << newConstant <<
"'.");
677storm::prism::Constant PrismParserGrammar::createUndefinedIntegerConstant(std::string
const& newConstant)
const {
678 if (!this->secondRun) {
681 this->identifiers_.add(newConstant, newVariable.
getExpression());
682 }
catch (storm::exceptions::InvalidArgumentException
const& e) {
684 "Parsing error in " << this->getFilename() <<
": illegal identifier '" << newConstant <<
"'.");
690storm::prism::Constant PrismParserGrammar::createUndefinedDoubleConstant(std::string
const& newConstant)
const {
691 if (!this->secondRun) {
694 this->identifiers_.add(newConstant, newVariable.
getExpression());
695 }
catch (storm::exceptions::InvalidArgumentException
const& e) {
697 "Parsing error in " << this->getFilename() <<
": illegal identifier '" << newConstant <<
"'.");
704 if (!this->secondRun) {
707 this->identifiers_.add(newConstant, newVariable.
getExpression());
708 }
catch (storm::exceptions::InvalidArgumentException
const& e) {
710 "Parsing error in " << this->getFilename() <<
": illegal identifier '" << newConstant <<
"'.");
717 if (!this->secondRun) {
720 this->identifiers_.add(newConstant, newVariable.
getExpression());
721 }
catch (storm::exceptions::InvalidArgumentException
const& e) {
723 "Parsing error in " << this->getFilename() <<
": illegal identifier '" << newConstant <<
"'.");
730 if (!this->secondRun) {
733 this->identifiers_.add(newConstant, newVariable.
getExpression());
734 }
catch (storm::exceptions::InvalidArgumentException
const& e) {
736 "Parsing error in " << this->getFilename() <<
": illegal identifier '" << newConstant <<
"'.");
742storm::prism::Formula PrismParserGrammar::createFormulaFirstRun(std::string
const& formulaName, std::string
const& expression) {
745 STORM_LOG_ASSERT(!this->secondRun,
"This constructor should have only been called during the first run.");
746 formulaExpressions.push_back(expression);
752 STORM_LOG_ASSERT(this->secondRun,
"This constructor should have only been called during the second run.");
765storm::prism::RewardModel PrismParserGrammar::createRewardModel(std::string
const& rewardModelName, std::vector<storm::prism::StateReward>
const& stateRewards,
766 std::vector<storm::prism::StateActionReward>
const& stateActionRewards,
767 std::vector<storm::prism::TransitionReward>
const& transitionRewards)
const {
768 return storm::prism::RewardModel(rewardModelName, stateRewards, stateActionRewards, transitionRewards, this->getFilename());
773 if (this->secondRun) {
783 GlobalProgramInformation& globalProgramInformation)
const {
784 if (this->secondRun) {
785 std::string realActionName = actionName ? actionName.get() :
"";
787 auto const& nameIndexPair = globalProgramInformation.actionIndices.find(realActionName);
788 STORM_LOG_THROW(nameIndexPair != globalProgramInformation.actionIndices.end(), storm::exceptions::WrongFormatException,
789 "Action reward refers to illegal action '" << realActionName <<
"'.");
800 GlobalProgramInformation& globalProgramInformation)
const {
801 if (this->secondRun) {
802 std::string realActionName = actionName ? actionName.get() :
"";
804 auto const& nameIndexPair = globalProgramInformation.actionIndices.find(realActionName);
805 STORM_LOG_THROW(nameIndexPair != globalProgramInformation.actionIndices.end(), storm::exceptions::WrongFormatException,
806 "Transition reward refers to illegal action '" << realActionName <<
"'.");
808 rewardValueExpression, this->getFilename());
819 std::vector<storm::prism::Assignment>
const& assignments,
820 GlobalProgramInformation& globalProgramInformation)
const {
821 ++globalProgramInformation.currentUpdateIndex;
822 if (!likelihoodExpressions.first.isInitialized()) {
823 likelihoodExpressions.first = manager->rational(1);
825 return storm::prism::Update(globalProgramInformation.currentUpdateIndex - 1, likelihoodExpressions, assignments, this->getFilename());
828storm::prism::Command PrismParserGrammar::createCommand(
bool markovian, boost::optional<std::string>
const& actionName,
830 GlobalProgramInformation& globalProgramInformation)
const {
831 ++globalProgramInformation.currentCommandIndex;
832 std::string realActionName = actionName ? actionName.get() :
"";
834 uint_fast64_t actionIndex = 0;
837 auto nameIndexPair = globalProgramInformation.actionIndices.find(realActionName);
838 if (nameIndexPair == globalProgramInformation.actionIndices.end()) {
839 std::size_t nextIndex = globalProgramInformation.actionIndices.size();
840 globalProgramInformation.actionIndices.emplace(realActionName, nextIndex);
841 actionIndex = nextIndex;
843 actionIndex = nameIndexPair->second;
845 return storm::prism::Command(globalProgramInformation.currentCommandIndex - 1, markovian, actionIndex, realActionName, guardExpression, updates,
846 this->getFilename());
849storm::prism::Command PrismParserGrammar::createDummyCommand(boost::optional<std::string>
const& actionName,
850 GlobalProgramInformation& globalProgramInformation)
const {
851 STORM_LOG_ASSERT(!this->secondRun,
"Dummy procedure must not be called in second run.");
852 std::string realActionName = actionName ? actionName.get() :
"";
855 auto nameIndexPair = globalProgramInformation.actionIndices.find(realActionName);
856 if (nameIndexPair == globalProgramInformation.actionIndices.end()) {
857 std::size_t nextIndex = globalProgramInformation.actionIndices.size();
858 globalProgramInformation.actionIndices.emplace(realActionName, nextIndex);
866 if (!this->secondRun) {
869 this->identifiers_.add(variableName, newVariable.
getExpression());
870 }
catch (storm::exceptions::InvalidArgumentException
const& e) {
872 "Parsing error in " << this->getFilename() <<
": illegal identifier '" << variableName <<
"'.");
875 bool observable = this->observables.count(variableName) > 0;
877 this->observables.erase(variableName);
885 if (!this->secondRun) {
888 this->identifiers_.add(variableName, newVariable.
getExpression());
889 }
catch (storm::exceptions::InvalidArgumentException
const& e) {
891 "Parsing error in " << this->getFilename() <<
": illegal identifier '" << variableName <<
"'.");
894 bool observable = this->observables.count(variableName) > 0;
896 this->observables.erase(variableName);
899 return storm::prism::IntegerVariable(manager->getVariable(variableName), lowerBoundExpression, upperBoundExpression, initialValueExpression, observable,
900 this->getFilename());
904 if (!this->secondRun) {
907 this->identifiers_.add(variableName, newVariable.
getExpression());
908 }
catch (storm::exceptions::InvalidArgumentException
const& e) {
910 "Parsing error in " << this->getFilename() <<
": illegal identifier '" << variableName <<
"'.");
913 bool observable = this->observables.count(variableName) > 0;
915 this->observables.erase(variableName);
921void PrismParserGrammar::createObservablesList(std::vector<std::string>
const& observables) {
922 this->observables.insert(observables.begin(), observables.end());
926storm::prism::Player PrismParserGrammar::createPlayer(std::string
const& playerName, std::vector<std::string>
const& moduleNames,
927 std::vector<std::string>
const& actionNames) {
928 if (this->secondRun) {
929 std::unordered_set<std::string> controlledModules;
930 std::unordered_set<std::string> controlledActions;
931 for (
auto const& moduleName : moduleNames) {
932 auto moduleIndexPair = globalProgramInformation.moduleToIndexMap.find(moduleName);
933 STORM_LOG_ASSERT(moduleIndexPair != globalProgramInformation.moduleToIndexMap.end(),
934 "Parsing error in " << this->getFilename() <<
" for player " << playerName <<
": No module named '" << moduleName <<
"' present.");
935 controlledModules.insert(moduleIndexPair->first);
936 bool moduleNotYetControlled = globalProgramInformation.playerControlledModules.insert(moduleIndexPair->second).second;
937 STORM_LOG_THROW(moduleNotYetControlled, storm::exceptions::WrongFormatException,
938 "Parsing error in " << this->getFilename() <<
" for player " << playerName <<
": Module '" << moduleName
939 <<
"' already controlled by another player.");
941 for (std::string actionName : actionNames) {
942 auto actionIndexPair = globalProgramInformation.actionIndices.find(actionName);
943 STORM_LOG_ASSERT(actionIndexPair != globalProgramInformation.actionIndices.end(),
944 "Parsing error in " << this->getFilename() <<
" for player " << playerName <<
": No action named '" << actionName <<
"' present.");
945 controlledActions.insert(actionIndexPair->first);
946 bool actionNotYetControlled = globalProgramInformation.playerControlledActions.insert(actionIndexPair->second).second;
947 STORM_LOG_THROW(actionNotYetControlled, storm::exceptions::WrongFormatException,
948 "Parsing error in " << this->getFilename() <<
" for player " << playerName <<
": Command '" << actionName
949 <<
"' already controlled by another player.");
957storm::prism::Module PrismParserGrammar::createModule(std::string
const& moduleName, std::vector<storm::prism::BooleanVariable>
const& booleanVariables,
958 std::vector<storm::prism::IntegerVariable>
const& integerVariables,
959 std::vector<storm::prism::ClockVariable>
const& clockVariables,
960 boost::optional<storm::expressions::Expression>
const& invariant,
961 std::vector<storm::prism::Command>
const& commands,
962 GlobalProgramInformation& globalProgramInformation)
const {
963 if (!this->secondRun) {
964 globalProgramInformation.moduleToIndexMap[moduleName] = globalProgramInformation.modules.size();
967 STORM_LOG_ASSERT(!this->secondRun || globalProgramInformation.moduleToIndexMap.count(moduleName) > 0,
"Module name '" << moduleName <<
"' was not found.");
968 STORM_LOG_ASSERT(!this->secondRun || globalProgramInformation.moduleToIndexMap[moduleName] == globalProgramInformation.modules.size(),
969 "The index for module '" << moduleName <<
"' does not match the index from the first parsing run.");
971 invariant.is_initialized() ? invariant.get() :
storm::expressions::Expression(), commands, this->getFilename());
975 GlobalProgramInformation
const& globalProgramInformation)
const {
976 if (!this->secondRun) {
977 auto const& renaming = moduleRenaming.
getRenaming();
978 auto const& moduleIndexPair = globalProgramInformation.moduleToIndexMap.find(oldModuleName);
979 if (moduleIndexPair == globalProgramInformation.moduleToIndexMap.end()) {
980 STORM_LOG_ERROR(
"Parsing error in " << this->getFilename() <<
": No module named '" << oldModuleName <<
"' to rename.");
983 storm::prism::Module const& moduleToRename = globalProgramInformation.modules[moduleIndexPair->second];
985 for (
auto const& variable : moduleToRename.getBooleanVariables()) {
986 auto const& renamingPair = renaming.find(variable.
getName());
987 if (renamingPair == renaming.end()) {
988 STORM_LOG_ERROR(
"Parsing error in renaming of module '" << oldModuleName <<
"': Boolean variable '" << variable.
getName()
989 <<
"' was not renamed.");
993 for (
auto const& variable : moduleToRename.getIntegerVariables()) {
994 auto const& renamingPair = renaming.find(variable.
getName());
995 if (renamingPair == renaming.end()) {
996 STORM_LOG_ERROR(
"Parsing error in renaming of module '" << oldModuleName <<
"': Integer variable '" << variable.
getName()
997 <<
"' was not renamed.");
1001 for (
auto const& variable : moduleToRename.getClockVariables()) {
1002 auto const& renamingPair = renaming.find(variable.
getName());
1003 if (renamingPair == renaming.end()) {
1004 STORM_LOG_ERROR(
"Parsing error in renaming of module '" << oldModuleName <<
"': Clock variable '" << variable.
getName()
1005 <<
"' was not renamed.");
1017storm::prism::Module PrismParserGrammar::createRenamedModule(std::string
const& newModuleName, std::string
const& oldModuleName,
1019 GlobalProgramInformation& globalProgramInformation)
const {
1021 auto const& moduleIndexPair = globalProgramInformation.moduleToIndexMap.find(oldModuleName);
1022 STORM_LOG_THROW(moduleIndexPair != globalProgramInformation.moduleToIndexMap.end(), storm::exceptions::WrongFormatException,
1023 "Parsing error in " << this->getFilename() <<
": No module named '" << oldModuleName <<
"' to rename.");
1024 storm::prism::Module const& moduleToRename = globalProgramInformation.modules[moduleIndexPair->second];
1026 "Parsing error in " << this->getFilename() <<
": The module '" << newModuleName <<
"' can not be created from module '" << oldModuleName
1027 <<
"' through module renaming because '" << oldModuleName <<
"' is also a renamed module. Create '" << newModuleName
1028 <<
"' via a renaming from base module '" << moduleToRename.
getBaseModule() <<
"' instead.");
1029 auto const& renaming = moduleRenaming.
getRenaming();
1030 if (!this->secondRun) {
1032 globalProgramInformation.moduleToIndexMap[newModuleName] = globalProgramInformation.modules.size();
1036 for (
auto const& variable : moduleToRename.getBooleanVariables()) {
1037 auto const& renamingPair = renaming.find(variable.
getName());
1038 STORM_LOG_THROW(renamingPair != renaming.end(), storm::exceptions::WrongFormatException,
1039 "Parsing error in " << this->getFilename() <<
": Boolean 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.getIntegerVariables()) {
1047 auto const& renamingPair = renaming.find(variable.
getName());
1048 STORM_LOG_THROW(renamingPair != renaming.end(), storm::exceptions::WrongFormatException,
1049 "Parsing error in " << this->getFilename() <<
": Integer 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);
1056 for (
auto const& variable : moduleToRename.getClockVariables()) {
1057 auto const& renamingPair = renaming.find(variable.
getName());
1058 STORM_LOG_THROW(renamingPair != renaming.end(), storm::exceptions::WrongFormatException,
1059 "Parsing error in " << this->getFilename() <<
": Clock variable '" << variable.
getName() <<
" was not renamed.");
1061 this->identifiers_.add(renamingPair->second, renamedVariable.
getExpression());
1062 if (this->observables.count(renamingPair->second) > 0) {
1063 this->observables.erase(renamingPair->second);
1067 for (
auto const& command : moduleToRename.getCommands()) {
1068 std::string newActionName = command.getActionName();
1069 auto const& renamingPair = renaming.find(command.getActionName());
1070 if (renamingPair != renaming.end()) {
1071 newActionName = renamingPair->second;
1075 auto nameIndexPair = globalProgramInformation.actionIndices.find(newActionName);
1076 if (nameIndexPair == globalProgramInformation.actionIndices.end()) {
1077 std::size_t nextIndex = globalProgramInformation.actionIndices.size();
1078 globalProgramInformation.actionIndices.emplace(newActionName, nextIndex);
1086 STORM_LOG_ASSERT(globalProgramInformation.moduleToIndexMap.count(newModuleName) > 0,
"Module name '" << newModuleName <<
"' was not found.");
1087 STORM_LOG_ASSERT(globalProgramInformation.moduleToIndexMap[newModuleName] == globalProgramInformation.modules.size(),
1088 "The index for module " << newModuleName <<
" does not match the index from the first parsing run.");
1091 std::map<storm::expressions::Variable, storm::expressions::Expression> expressionRenaming;
1092 for (
auto const& namePair : renaming) {
1095 if (substitutedExpression !=
nullptr) {
1096 expressionRenaming.emplace(manager->getVariable(namePair.first), *substitutedExpression);
1101 std::vector<storm::prism::BooleanVariable> booleanVariables;
1102 for (
auto const& variable : moduleToRename.getBooleanVariables()) {
1103 auto const& renamingPair = renaming.find(variable.
getName());
1104 STORM_LOG_THROW(renamingPair != renaming.end(), storm::exceptions::WrongFormatException,
1105 "Parsing error in " << this->getFilename() <<
": Boolean variable '" << variable.
getName() <<
" was not renamed.");
1106 bool observable = this->observables.count(renamingPair->second) > 0;
1108 this->observables.erase(renamingPair->second);
1111 manager->getVariable(renamingPair->second),
1112 variable.hasInitialValue() ? variable.getInitialValueExpression().substitute(expressionRenaming) : variable.getInitialValueExpression(),
1113 observable, this->getFilename(), moduleRenaming.getLineNumber()));
1117 std::vector<storm::prism::IntegerVariable> integerVariables;
1118 for (
auto const& variable : moduleToRename.getIntegerVariables()) {
1119 auto const& renamingPair = renaming.find(variable.
getName());
1120 STORM_LOG_THROW(renamingPair != renaming.end(), storm::exceptions::WrongFormatException,
1121 "Parsing error in " << this->getFilename() <<
": Integer variable '" << variable.
getName() <<
" was not renamed.");
1122 bool observable = this->observables.count(renamingPair->second) > 0;
1124 this->observables.erase(renamingPair->second);
1127 manager->getVariable(renamingPair->second), variable.getLowerBoundExpression().substitute(expressionRenaming),
1128 variable.getUpperBoundExpression().substitute(expressionRenaming),
1129 variable.hasInitialValue() ? variable.getInitialValueExpression().substitute(expressionRenaming) : variable.getInitialValueExpression(),
1130 observable, this->getFilename(), moduleRenaming.getLineNumber()));
1134 std::vector<storm::prism::ClockVariable> clockVariables;
1135 for (
auto const& variable : moduleToRename.getClockVariables()) {
1136 auto const& renamingPair = renaming.find(variable.
getName());
1137 STORM_LOG_THROW(renamingPair != renaming.end(), storm::exceptions::WrongFormatException,
1138 "Parsing error in " << this->getFilename() <<
": Clock variable '" << variable.
getName() <<
" was not renamed.");
1139 bool observable = this->observables.count(renamingPair->second) > 0;
1141 this->observables.erase(renamingPair->second);
1143 clockVariables.push_back(
1154 std::vector<storm::prism::Command> commands;
1155 for (
auto const& command : moduleToRename.getCommands()) {
1156 std::vector<storm::prism::Update> updates;
1157 for (
auto const& update : command.getUpdates()) {
1158 std::vector<storm::prism::Assignment> assignments;
1159 for (
auto const& assignment : update.getAssignments()) {
1160 auto const& renamingPair = renaming.find(assignment.getVariableName());
1161 if (renamingPair != renaming.end()) {
1162 assignments.emplace_back(manager->getVariable(renamingPair->second), assignment.getExpression().substitute(expressionRenaming),
1165 assignments.emplace_back(assignment.getVariable(), assignment.getExpression().substitute(expressionRenaming), this->getFilename(),
1169 if (update.isLikelihoodInterval()) {
1171 update.getLikelihoodExpressionInterval().first.
substitute(expressionRenaming),
1172 update.getLikelihoodExpressionInterval().second.
substitute(expressionRenaming)};
1173 updates.emplace_back(globalProgramInformation.currentUpdateIndex, likelihoodInterval, assignments, this->getFilename(),
1176 updates.emplace_back(globalProgramInformation.currentUpdateIndex, update.getLikelihoodExpression().substitute(expressionRenaming),
1177 assignments, this->getFilename(), moduleRenaming.
getLineNumber());
1179 ++globalProgramInformation.currentUpdateIndex;
1182 std::string newActionName = command.getActionName();
1183 auto const& renamingPair = renaming.find(command.getActionName());
1184 if (renamingPair != renaming.end()) {
1185 newActionName = renamingPair->second;
1188 uint_fast64_t actionIndex = 0;
1189 auto nameIndexPair = globalProgramInformation.actionIndices.find(newActionName);
1190 if (nameIndexPair == globalProgramInformation.actionIndices.end()) {
1191 std::size_t nextIndex = globalProgramInformation.actionIndices.size();
1192 globalProgramInformation.actionIndices.emplace(newActionName, nextIndex);
1193 actionIndex = nextIndex;
1195 actionIndex = nameIndexPair->second;
1198 commands.emplace_back(globalProgramInformation.currentCommandIndex, command.isMarkovian(), actionIndex, newActionName,
1199 command.getGuardExpression().substitute(expressionRenaming), updates, this->getFilename(), moduleRenaming.
getLineNumber());
1200 ++globalProgramInformation.currentCommandIndex;
1203 return storm::prism::Module(newModuleName, booleanVariables, integerVariables, clockVariables, invariant, commands, oldModuleName, renaming);
1207storm::prism::Program PrismParserGrammar::createProgram(GlobalProgramInformation
const& globalProgramInformation)
const {
1210 STORM_LOG_WARN(
"Program does not specify model type. Implicitly assuming 'mdp'.");
1215 std::vector<storm::prism::Formula> orderedFormulas;
1216 if (this->secondRun) {
1217 orderedFormulas.reserve(globalProgramInformation.formulas.size());
1218 for (uint64_t
const& i : formulaOrder) {
1219 orderedFormulas.push_back(std::move(globalProgramInformation.formulas[i]));
1224 manager, finalModelType, globalProgramInformation.constants, globalProgramInformation.globalBooleanVariables,
1225 globalProgramInformation.globalIntegerVariables, orderedFormulas, globalProgramInformation.players, globalProgramInformation.modules,
1226 globalProgramInformation.actionIndices, globalProgramInformation.rewardModels, globalProgramInformation.labels,
1227 globalProgramInformation.observationLabels,
1228 secondRun && !globalProgramInformation.hasInitialConstruct ? boost::none :
boost::make_optional(globalProgramInformation.initialConstruct),
1229 globalProgramInformation.systemCompositionConstruct, prismCompatibility, this->getFilename(), 1, this->secondRun);
1232void 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.
std::pair< storm::expressions::Expression, storm::expressions::Expression > ExpressionPair
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.