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),
93 expressionParser(new
ExpressionParser(*manager, expressionKeywords_, false, false)) {
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 =
233 (qi::lit(
"observables") > (identifier % qi::lit(
",")) >
234 qi::lit(
"endobservables"))[qi::_pass = phoenix::bind(&PrismParserGrammar::addObservablesConstruct, phoenix::ref(*
this), qi::_1, qi::_r1)];
235 observablesConstruct.name(
"observables construct");
237 invariantConstruct = (qi::lit(
"invariant") > boolExpression > qi::lit(
"endinvariant"))[qi::_val = qi::_1];
238 invariantConstruct.name(
"invariant construct");
240 knownModuleName = (identifier[qi::_val = qi::_1])[qi::_pass = phoenix::bind(&PrismParserGrammar::isKnownModuleName, phoenix::ref(*
this), qi::_1,
false)];
241 knownModuleName.name(
"existing module name");
243 freshModuleName = (identifier[qi::_val = qi::_1])[qi::_pass = phoenix::bind(&PrismParserGrammar::isFreshModuleName, phoenix::ref(*
this), qi::_1)];
244 freshModuleName.name(
"fresh module name");
246 systemCompositionConstruct =
247 (qi::lit(
"system") > parallelComposition >
248 qi::lit(
"endsystem"))[phoenix::bind(&PrismParserGrammar::addSystemCompositionConstruct, phoenix::ref(*
this), qi::_1, qi::_r1)];
249 systemCompositionConstruct.name(
"system composition construct");
251 actionNameList %= identifier[phoenix::insert(qi::_val, qi::_1)] >> *(
"," >> identifier[phoenix::insert(qi::_val, qi::_1)]);
252 actionNameList.name(
"action list");
254 parallelComposition =
255 hidingOrRenamingComposition[qi::_val = qi::_1] >>
256 *((interleavingParallelComposition > hidingOrRenamingComposition)[qi::_val = phoenix::bind(&PrismParserGrammar::createInterleavingParallelComposition,
257 phoenix::ref(*
this), qi::_val, qi::_1)] |
258 (synchronizingParallelComposition > hidingOrRenamingComposition)[qi::_val = phoenix::bind(&PrismParserGrammar::createSynchronizingParallelComposition,
259 phoenix::ref(*
this), qi::_val, qi::_1)] |
260 (restrictedParallelComposition > hidingOrRenamingComposition)[qi::_val = phoenix::bind(&PrismParserGrammar::createRestrictedParallelComposition,
261 phoenix::ref(*
this), qi::_val, qi::_1, qi::_2)]);
262 parallelComposition.name(
"parallel composition");
264 synchronizingParallelComposition = qi::lit(
"||");
265 synchronizingParallelComposition.name(
"synchronizing parallel composition");
267 interleavingParallelComposition = qi::lit(
"|||");
268 interleavingParallelComposition.name(
"interleaving parallel composition");
270 restrictedParallelComposition = qi::lit(
"|[") > actionNameList > qi::lit(
"]|");
271 restrictedParallelComposition.name(
"restricted parallel composition");
273 hidingOrRenamingComposition = hidingComposition | renamingComposition | atomicComposition;
274 hidingOrRenamingComposition.name(
"hiding/renaming composition");
277 (atomicComposition >>
278 (qi::lit(
"/") > (qi::lit(
"{") > actionNameList >
279 qi::lit(
"}"))))[qi::_val = phoenix::bind(&PrismParserGrammar::createHidingComposition, phoenix::ref(*
this), qi::_1, qi::_2)];
280 hidingComposition.name(
"hiding composition");
283 +(identifier >> (qi::lit(
"<-") >> identifier))[phoenix::insert(qi::_val, phoenix::construct<std::pair<std::string, std::string>>(qi::_1, qi::_2))];
284 actionRenamingList.name(
"action renaming list");
286 renamingComposition =
287 (atomicComposition >>
289 (actionRenamingList > qi::lit(
"}"))))[qi::_val = phoenix::bind(&PrismParserGrammar::createRenamingComposition, phoenix::ref(*
this), qi::_1, qi::_2)];
290 renamingComposition.name(
"renaming composition");
292 atomicComposition = (qi::lit(
"(") > parallelComposition > qi::lit(
")")) | moduleComposition;
293 atomicComposition.name(
"atomic composition");
295 moduleComposition = identifier[qi::_val = phoenix::bind(&PrismParserGrammar::createModuleComposition, phoenix::ref(*
this), qi::_1)];
296 moduleComposition.name(
"module composition");
298 freshLabelName = (identifier[qi::_val = qi::_1])[qi::_pass = phoenix::bind(&PrismParserGrammar::isFreshLabelName, phoenix::ref(*
this), qi::_1)];
299 freshLabelName.name(
"fresh label name");
301 labelDefinition = (qi::lit(
"label") > -qi::lit(
"\"") > freshLabelName > -qi::lit(
"\"") > qi::lit(
"=") > boolExpression >
302 qi::lit(
";"))[qi::_val = phoenix::bind(&PrismParserGrammar::createLabel, phoenix::ref(*
this), qi::_1, qi::_2)];
303 labelDefinition.name(
"label definition");
305 freshObservationLabelName =
306 (identifier[qi::_val = qi::_1])[qi::_pass = phoenix::bind(&PrismParserGrammar::isFreshObservationLabelName, phoenix::ref(*
this), qi::_1)];
307 freshObservationLabelName.name(
"fresh observable name");
309 observableDefinition =
310 (qi::lit(
"observable") > -qi::lit(
"\"") > freshObservationLabelName > -qi::lit(
"\"") > qi::lit(
"=") > (intExpression | boolExpression) >
311 qi::lit(
";"))[qi::_val = phoenix::bind(&PrismParserGrammar::createObservationLabel, phoenix::ref(*
this), qi::_1, qi::_2)];
312 observableDefinition.name(
"observable definition");
314 assignmentDefinition = ((qi::lit(
"(") >> identifier >> qi::lit(
"'")) > qi::lit(
"=") > expression_ >
315 qi::lit(
")"))[qi::_val = phoenix::bind(&PrismParserGrammar::createAssignment, phoenix::ref(*
this), qi::_1, qi::_2)];
316 assignmentDefinition.name(
"assignment");
318 assignmentDefinitionList =
319 (assignmentDefinition %
"&")[qi::_val = qi::_1] | (qi::lit(
"true"))[qi::_val = phoenix::construct<std::vector<storm::prism::Assignment>>()];
320 assignmentDefinitionList.name(
"assignment list");
322 likelihoodDefinition =
323 (numericalExpression >
325 (qi::lit(
"[") > numericalExpression > qi::lit(
",") > numericalExpression > qi::lit(
"]") >
326 qi::lit(
":"))[qi::_val = phoenix::construct<typename storm::prism::Update::ExpressionPair>(qi::_1, qi::_2)];
329 (assignmentDefinitionList[qi::_val = phoenix::bind(&PrismParserGrammar::createUpdate, phoenix::ref(*
this),
331 ((likelihoodDefinition >
332 assignmentDefinitionList)[qi::_val = phoenix::bind(&PrismParserGrammar::createUpdate, phoenix::ref(*
this), qi::_1, qi::_2, qi::_r1)]));
333 updateDefinition.name(
"update");
335 updateListDefinition %= +updateDefinition(qi::_r1) %
"+";
336 updateListDefinition.name(
"update list");
339 commandDefinition = (((qi::lit(
"[") > -identifier > qi::lit(
"]")) | (qi::lit(
"<") > -identifier > qi::lit(
">")[qi::_a =
true])) >
340 +(qi::char_ - (qi::lit(
";") | qi::lit(
"endmodule"))) >
341 qi::lit(
";"))[qi::_val = phoenix::bind(&PrismParserGrammar::createDummyCommand, phoenix::ref(*
this), qi::_1, qi::_r1)];
342 commandDefinition.name(
"command definition");
346 ((qi::lit(
"module") > freshModuleName > *(variableDefinition(qi::_a, qi::_b, qi::_c))) > -invariantConstruct > (*commandDefinition(qi::_r1)) >
347 qi::lit(
"endmodule"))[qi::_val = phoenix::bind(&PrismParserGrammar::createModule, phoenix::ref(*
this), qi::_1, qi::_a, qi::_b, qi::_c, qi::_2, qi::_3,
349 moduleDefinition.name(
"module definition");
351 freshPlayerName = (identifier[qi::_val = qi::_1])[qi::_pass = phoenix::bind(&PrismParserGrammar::isFreshPlayerName, phoenix::ref(*
this), qi::_1)];
352 freshPlayerName.name(
"fresh player name");
354 playerControlledActionName =
355 ((qi::lit(
"[") > identifier >
356 qi::lit(
"]"))[qi::_val = qi::_1])[qi::_pass = phoenix::bind(&PrismParserGrammar::isKnownActionName, phoenix::ref(*
this), qi::_1,
true)];
357 playerControlledActionName.name(
"player controlled action name");
359 playerControlledModuleName =
360 (identifier[qi::_val = qi::_1])[qi::_pass = phoenix::bind(&PrismParserGrammar::isKnownModuleName, phoenix::ref(*
this), qi::_1,
true)];
361 playerControlledModuleName.name(
"player controlled module name");
364 (qi::lit(
"player") > freshPlayerName[qi::_a = qi::_1] >
365 +((playerControlledActionName[phoenix::push_back(qi::_c, qi::_1)] | playerControlledModuleName[phoenix::push_back(qi::_b, qi::_1)]) %
',') >
366 qi::lit(
"endplayer"))[qi::_val = phoenix::bind(&PrismParserGrammar::createPlayer, phoenix::ref(*
this), qi::_a, qi::_b, qi::_c)];
367 playerConstruct.name(
"player construct");
371 ((identifier > qi::lit(
"=") > identifier)[phoenix::insert(qi::_a, phoenix::construct<std::pair<std::string, std::string>>(qi::_1, qi::_2))] %
",") >
372 qi::lit(
"]"))[qi::_val = phoenix::bind(&PrismParserGrammar::createModuleRenaming, phoenix::ref(*
this), qi::_a)];
373 moduleRenaming.name(
"Module renaming list");
376 (((qi::lit(
"module") > freshModuleName) >> qi::lit(
"=")) > knownModuleName[qi::_a = qi::_1] >
377 (moduleRenaming[qi::_b = qi::_1])[qi::_pass =
378 phoenix::bind(&PrismParserGrammar::isValidModuleRenaming, phoenix::ref(*
this), qi::_a, qi::_b, qi::_r1)] >
379 qi::lit(
"endmodule"))[qi::_val = phoenix::bind(&PrismParserGrammar::createRenamedModule, phoenix::ref(*
this), qi::_1, qi::_a, qi::_b, qi::_r1)];
380 renamedModule.name(
"module definition via renaming");
383 (qi::eps[phoenix::bind(&PrismParserGrammar::removeInitialConstruct, phoenix::ref(*
this), phoenix::ref(globalProgramInformation))] >
384 modelTypeDefinition[phoenix::bind(&PrismParserGrammar::setModelType, phoenix::ref(*
this), phoenix::ref(globalProgramInformation), qi::_1)] >
385 *(observablesConstruct(phoenix::ref(globalProgramInformation)) |
390 globalVariableDefinition(phoenix::ref(globalProgramInformation)) |
391 (renamedModule(phoenix::ref(globalProgramInformation)) | moduleDefinition(phoenix::ref(globalProgramInformation)))[phoenix::push_back(
393 initialStatesConstruct(phoenix::ref(globalProgramInformation)) |
394 rewardModelDefinition(phoenix::ref(globalProgramInformation))[phoenix::push_back(
400 playerConstruct(phoenix::ref(globalProgramInformation))[phoenix::push_back(
402 -(systemCompositionConstruct(phoenix::ref(globalProgramInformation))) >
403 qi::eoi)[qi::_val = phoenix::bind(&PrismParserGrammar::createProgram, phoenix::ref(*
this), phoenix::ref(globalProgramInformation))];
404 start.name(
"probabilistic program");
407 auto setLocationInfoFunction = this->annotate(qi::_val, qi::_1, qi::_3);
408 qi::on_success(undefinedBooleanConstantDefinition, setLocationInfoFunction);
409 qi::on_success(undefinedIntegerConstantDefinition, setLocationInfoFunction);
410 qi::on_success(undefinedDoubleConstantDefinition, setLocationInfoFunction);
411 qi::on_success(definedBooleanConstantDefinition, setLocationInfoFunction);
412 qi::on_success(definedIntegerConstantDefinition, setLocationInfoFunction);
413 qi::on_success(definedDoubleConstantDefinition, setLocationInfoFunction);
414 qi::on_success(booleanVariableDefinition, setLocationInfoFunction);
415 qi::on_success(integerVariableDefinition, setLocationInfoFunction);
416 qi::on_success(clockVariableDefinition, setLocationInfoFunction);
417 qi::on_success(moduleDefinition, setLocationInfoFunction);
418 qi::on_success(moduleRenaming, setLocationInfoFunction);
419 qi::on_success(renamedModule, setLocationInfoFunction);
420 qi::on_success(formulaDefinition, setLocationInfoFunction);
421 qi::on_success(rewardModelDefinition, setLocationInfoFunction);
422 qi::on_success(labelDefinition, setLocationInfoFunction);
423 qi::on_success(observableDefinition, setLocationInfoFunction);
424 qi::on_success(commandDefinition, setLocationInfoFunction);
425 qi::on_success(updateDefinition, setLocationInfoFunction);
426 qi::on_success(assignmentDefinition, setLocationInfoFunction);
429 qi::on_error<qi::fail>(start,
430 (phoenix::bind(&PrismParserGrammar::reportRejectedKeywordIdentifier, phoenix::ref(*
this)), handler(qi::_1, qi::_2, qi::_3, qi::_4)));
433void PrismParserGrammar::moveToSecondRun() {
435 auto const undeclaredObsIt = std::find_if(observables.begin(), observables.end(), [](
auto const& pair) { return !pair.second; });
436 STORM_LOG_THROW(undeclaredObsIt == observables.end(), storm::exceptions::WrongFormatException,
437 "Some variables marked as observable, but never declared, e.g. " << undeclaredObsIt->first);
443 (((qi::lit(
"[") > -identifier > qi::lit(
"]")) | (qi::lit(
"<") > -identifier > qi::lit(
">")[qi::_a =
true])) > *expressionParser > qi::lit(
"->") >
444 updateListDefinition(qi::_r1) >
445 qi::lit(
";"))[qi::_val = phoenix::bind(&PrismParserGrammar::createCommand, phoenix::ref(*
this), qi::_a, qi::_1, qi::_2, qi::_3, qi::_r1)];
447 auto setLocationInfoFunction = this->annotate(qi::_val, qi::_1, qi::_3);
448 qi::on_success(commandDefinition, setLocationInfoFunction);
450 formulaDefinition = (qi::lit(
"formula") > identifier > qi::lit(
"=") > *expressionParser >
451 qi::lit(
";"))[qi::_val = phoenix::bind(&PrismParserGrammar::createFormulaSecondRun, phoenix::ref(*
this), qi::_1, qi::_2)];
452 formulaDefinition.name(
"formula definition");
453 this->secondRun =
true;
454 this->expressionParser->setIdentifierMapping(&this->identifiers_);
459 createFormulaIdentifiers(this->globalProgramInformation.
formulas);
464void PrismParserGrammar::createFormulaIdentifiers(std::vector<storm::prism::Formula>
const& formulas) {
465 STORM_LOG_THROW(formulas.size() == this->formulaExpressions.size(), storm::exceptions::UnexpectedException,
466 "Unexpected number of formulas and formula expressions.");
467 this->formulaOrder.clear();
468 storm::storage::BitVector unprocessed(formulas.size(),
true);
473 bool progress =
true;
476 for (uint64_t formulaIndex = unprocessed.getNextSetIndex(0); formulaIndex < formulas.size();
477 formulaIndex = unprocessed.getNextSetIndex(formulaIndex + 1)) {
478 storm::expressions::Expression expression = this->expressionParser->parseFromString(formulaExpressions[formulaIndex],
true);
481 unprocessed.set(formulaIndex,
false);
482 formulaOrder.push_back(formulaIndex);
483 storm::expressions::Variable variable;
486 variable = manager->declareIntegerVariable(formulas[formulaIndex].getName());
488 variable = manager->declareBooleanVariable(formulas[formulaIndex].getName());
491 "Unexpected type for formula expression of formula " << formulas[formulaIndex].getName());
492 variable = manager->declareRationalVariable(formulas[formulaIndex].getName());
494 this->identifiers_.add(formulas[formulaIndex].getName(), variable.
getExpression());
495 }
catch (storm::exceptions::InvalidArgumentException
const&) {
497 "Parsing error in " << this->getFilename() <<
": illegal identifier '" << formulas[formulaIndex].getName() <<
"' at line '"
498 << formulas[formulaIndex].getLineNumber() <<
".");
500 this->expressionParser->setIdentifierMapping(&this->identifiers_);
504 if (!unprocessed.empty()) {
505 for (uint64_t formulaIndex : unprocessed) {
506 STORM_LOG_ERROR(
"Parsing error in " << this->getFilename() <<
": Invalid expression for formula '" << formulas[formulaIndex].getName()
507 <<
"' at line '" << formulas[formulaIndex].getLineNumber() <<
"':\n\t" << formulaExpressions[formulaIndex]);
509 STORM_LOG_THROW(unprocessed.getNumberOfSetBits() == 1, storm::exceptions::WrongFormatException,
510 "Unable to parse expressions for " << unprocessed.getNumberOfSetBits() <<
" formulas. This could be due to circular dependencies.");
512 "Unable to parse expression for formula '" << formulas[unprocessed.getNextSetIndex(0)].getName() <<
"'.");
516void PrismParserGrammar::allowDoubleLiterals(
bool flag) {
517 this->expressionParser->setAcceptDoubleLiterals(flag);
520std::string
const& PrismParserGrammar::getFilename()
const {
521 return this->filename;
524bool PrismParserGrammar::isValidIdentifier(std::string
const& identifier) {
525 if (this->keywords_.find(identifier) !=
nullptr) {
529 auto const modelType = this->globalProgramInformation.modelType;
532 if (isExemptSmgKeyword || isExemptPtaKeyword) {
537 this->lastRejectedKeywordIdentifier = identifier;
543void PrismParserGrammar::reportRejectedKeywordIdentifier() {
544 if (!this->lastRejectedKeywordIdentifier.empty()) {
545 STORM_LOG_ERROR(
"Parsing error in " << this->getFilename() <<
": '" << this->lastRejectedKeywordIdentifier
546 <<
"' is a reserved keyword and cannot be used as an identifier.");
550bool PrismParserGrammar::isKnownModuleName(std::string
const& moduleName,
bool inSecondRun) {
551 if ((this->secondRun == inSecondRun) && this->globalProgramInformation.moduleToIndexMap.count(moduleName) == 0) {
552 STORM_LOG_ERROR(
"Parsing error in " << this->getFilename() <<
": Unknown module '" << moduleName <<
"'.");
558bool PrismParserGrammar::isFreshModuleName(std::string
const& moduleName) {
559 if (!this->secondRun && this->globalProgramInformation.moduleToIndexMap.count(moduleName) != 0) {
560 STORM_LOG_ERROR(
"Parsing error in " << this->getFilename() <<
": Duplicate module name '" << moduleName <<
"'.");
566bool PrismParserGrammar::isKnownActionName(std::string
const& actionName,
bool inSecondRun) {
567 if ((this->secondRun == inSecondRun) && this->globalProgramInformation.actionIndices.count(actionName) == 0) {
568 STORM_LOG_ERROR(
"Parsing error in " << this->getFilename() <<
": Unknown action label '" << actionName <<
"'.");
574bool PrismParserGrammar::isFreshIdentifier(std::string
const& identifier) {
575 if (!this->secondRun && this->manager->hasVariable(identifier)) {
576 STORM_LOG_ERROR(
"Parsing error in " << this->getFilename() <<
": Duplicate identifier '" << identifier <<
"'.");
582bool PrismParserGrammar::isFreshLabelName(std::string
const& labelName) {
583 if (!this->secondRun) {
584 for (
auto const& existingLabel : this->globalProgramInformation.labels) {
585 if (labelName == existingLabel.getName()) {
586 STORM_LOG_ERROR(
"Parsing error in " << this->getFilename() <<
": Duplicate label name '" << identifier <<
"'.");
594bool PrismParserGrammar::isFreshObservationLabelName(std::string
const& labelName) {
595 if (!this->secondRun) {
597 if (std::any_of(this->globalProgramInformation.observationLabels.begin(), this->globalProgramInformation.observationLabels.end(),
598 [&labelName](
auto const& existingLabel) { return labelName == existingLabel.getName(); })) {
599 STORM_LOG_ERROR(
"Parsing error in " << this->getFilename() <<
": Duplicate observation label name '" << labelName <<
"'.");
604 if (std::any_of(this->observables.begin(), this->observables.end(),
605 [&labelName](
auto const& observableVariable) { return labelName == observableVariable.first; })) {
606 STORM_LOG_ERROR(
"Parsing error in " << this->getFilename() <<
": Observation label name '" << labelName
607 <<
"' coincides with the name of an observable variable.");
614bool PrismParserGrammar::isFreshRewardModelName(std::string
const& rewardModelName) {
615 if (!this->secondRun) {
616 for (
auto const& existingRewardModel : this->globalProgramInformation.rewardModels) {
617 if (rewardModelName == existingRewardModel.getName()) {
618 STORM_LOG_ERROR(
"Parsing error in " << this->getFilename() <<
": Duplicate reward model name '" << identifier <<
"'.");
626bool PrismParserGrammar::isFreshPlayerName(std::string
const& playerName) {
630bool PrismParserGrammar::isOfBoolType(storm::expressions::Expression
const& expression) {
634bool PrismParserGrammar::isOfIntType(storm::expressions::Expression
const& expression) {
638bool PrismParserGrammar::isOfNumericalType(storm::expressions::Expression
const& expression) {
642bool PrismParserGrammar::addInitialStatesConstruct(storm::expressions::Expression
const& initialStatesExpression,
644 STORM_LOG_THROW(!globalProgramInformation.hasInitialConstruct, storm::exceptions::WrongFormatException,
645 "Parsing error in " << this->getFilename() <<
": Program must not define two initial constructs.");
646 if (globalProgramInformation.hasInitialConstruct) {
649 globalProgramInformation.hasInitialConstruct =
true;
650 globalProgramInformation.initialConstruct = storm::prism::InitialConstruct(initialStatesExpression, this->getFilename(), get_line(qi::_3));
654bool PrismParserGrammar::addSystemCompositionConstruct(std::shared_ptr<storm::prism::Composition>
const& composition,
656 globalProgramInformation.systemCompositionConstruct = storm::prism::SystemCompositionConstruct(composition, this->getFilename(), get_line(qi::_3));
662 "Parsing error in " << this->getFilename() <<
": Program must not set model type multiple times.");
663 globalProgramInformation.modelType = modelType;
666std::shared_ptr<storm::prism::Composition> PrismParserGrammar::createModuleComposition(std::string
const& moduleName)
const {
667 return std::make_shared<storm::prism::ModuleComposition>(moduleName);
670std::shared_ptr<storm::prism::Composition> PrismParserGrammar::createRenamingComposition(std::shared_ptr<storm::prism::Composition>
const& subcomposition,
671 std::map<std::string, std::string>
const& renaming)
const {
672 return std::make_shared<storm::prism::RenamingComposition>(subcomposition, renaming);
675std::shared_ptr<storm::prism::Composition> PrismParserGrammar::createHidingComposition(std::shared_ptr<storm::prism::Composition>
const& subcomposition,
676 std::set<std::string>
const& actionsToHide)
const {
677 return std::make_shared<storm::prism::HidingComposition>(subcomposition, actionsToHide);
680std::shared_ptr<storm::prism::Composition> PrismParserGrammar::createSynchronizingParallelComposition(
681 std::shared_ptr<storm::prism::Composition>
const& left, std::shared_ptr<storm::prism::Composition>
const& right)
const {
682 return std::make_shared<storm::prism::SynchronizingParallelComposition>(left, right);
685std::shared_ptr<storm::prism::Composition> PrismParserGrammar::createInterleavingParallelComposition(
686 std::shared_ptr<storm::prism::Composition>
const& left, std::shared_ptr<storm::prism::Composition>
const& right)
const {
687 return std::make_shared<storm::prism::InterleavingParallelComposition>(left, right);
690std::shared_ptr<storm::prism::Composition> PrismParserGrammar::createRestrictedParallelComposition(
691 std::shared_ptr<storm::prism::Composition>
const& left, std::set<std::string>
const& synchronizingActions,
692 std::shared_ptr<storm::prism::Composition>
const& right)
const {
693 return std::make_shared<storm::prism::RestrictedParallelComposition>(left, synchronizingActions, right);
696storm::prism::Constant PrismParserGrammar::createUndefinedBooleanConstant(std::string
const& newConstant)
const {
697 if (!this->secondRun) {
699 storm::expressions::Variable newVariable = manager->declareBooleanVariable(newConstant,
true);
700 this->identifiers_.add(newConstant, newVariable.
getExpression());
701 }
catch (storm::exceptions::InvalidArgumentException
const&) {
703 "Parsing error in " << this->getFilename() <<
": illegal identifier '" << newConstant <<
"'.");
706 return storm::prism::Constant(manager->getVariable(newConstant), this->getFilename());
709storm::prism::Constant PrismParserGrammar::createUndefinedIntegerConstant(std::string
const& newConstant)
const {
710 if (!this->secondRun) {
712 storm::expressions::Variable newVariable = manager->declareIntegerVariable(newConstant,
true);
713 this->identifiers_.add(newConstant, newVariable.
getExpression());
714 }
catch (storm::exceptions::InvalidArgumentException
const&) {
716 "Parsing error in " << this->getFilename() <<
": illegal identifier '" << newConstant <<
"'.");
719 return storm::prism::Constant(manager->getVariable(newConstant), this->getFilename());
722storm::prism::Constant PrismParserGrammar::createUndefinedDoubleConstant(std::string
const& newConstant)
const {
723 if (!this->secondRun) {
725 storm::expressions::Variable newVariable = manager->declareRationalVariable(newConstant,
true);
726 this->identifiers_.add(newConstant, newVariable.
getExpression());
727 }
catch (storm::exceptions::InvalidArgumentException
const&) {
729 "Parsing error in " << this->getFilename() <<
": illegal identifier '" << newConstant <<
"'.");
732 return storm::prism::Constant(manager->getVariable(newConstant), this->getFilename());
735storm::prism::Constant PrismParserGrammar::createDefinedBooleanConstant(std::string
const& newConstant, storm::expressions::Expression expression)
const {
736 if (!this->secondRun) {
738 storm::expressions::Variable newVariable = manager->declareBooleanVariable(newConstant,
true);
739 this->identifiers_.add(newConstant, newVariable.
getExpression());
740 }
catch (storm::exceptions::InvalidArgumentException
const&) {
742 "Parsing error in " << this->getFilename() <<
": illegal identifier '" << newConstant <<
"'.");
745 return storm::prism::Constant(manager->getVariable(newConstant), expression, this->getFilename());
748storm::prism::Constant PrismParserGrammar::createDefinedIntegerConstant(std::string
const& newConstant, storm::expressions::Expression expression)
const {
749 if (!this->secondRun) {
751 storm::expressions::Variable newVariable = manager->declareIntegerVariable(newConstant,
true);
752 this->identifiers_.add(newConstant, newVariable.
getExpression());
753 }
catch (storm::exceptions::InvalidArgumentException
const&) {
755 "Parsing error in " << this->getFilename() <<
": illegal identifier '" << newConstant <<
"'.");
758 return storm::prism::Constant(manager->getVariable(newConstant), expression, this->getFilename());
761storm::prism::Constant PrismParserGrammar::createDefinedDoubleConstant(std::string
const& newConstant, storm::expressions::Expression expression)
const {
762 if (!this->secondRun) {
764 storm::expressions::Variable newVariable = manager->declareRationalVariable(newConstant,
true);
765 this->identifiers_.add(newConstant, newVariable.
getExpression());
766 }
catch (storm::exceptions::InvalidArgumentException
const&) {
768 "Parsing error in " << this->getFilename() <<
": illegal identifier '" << newConstant <<
"'.");
771 return storm::prism::Constant(manager->getVariable(newConstant), expression, this->getFilename());
774storm::prism::Formula PrismParserGrammar::createFormulaFirstRun(std::string
const& formulaName, std::string
const& expression) {
777 STORM_LOG_ASSERT(!this->secondRun,
"This constructor should have only been called during the first run.");
778 formulaExpressions.push_back(expression);
779 return storm::prism::Formula(formulaName, this->getFilename());
782storm::prism::Formula PrismParserGrammar::createFormulaSecondRun(std::string
const& formulaName, storm::expressions::Expression
const& expression) {
784 STORM_LOG_ASSERT(this->secondRun,
"This constructor should have only been called during the second run.");
785 storm::expressions::Expression lhsExpression = *this->identifiers_.find(formulaName);
789storm::prism::Label PrismParserGrammar::createLabel(std::string
const& labelName, storm::expressions::Expression expression)
const {
790 return storm::prism::Label(labelName, expression, this->getFilename());
793storm::prism::ObservationLabel PrismParserGrammar::createObservationLabel(std::string
const& labelName, storm::expressions::Expression expression)
const {
794 return storm::prism::ObservationLabel(labelName, expression, this->getFilename());
797storm::prism::RewardModel PrismParserGrammar::createRewardModel(std::string
const& rewardModelName, std::vector<storm::prism::StateReward>
const& stateRewards,
798 std::vector<storm::prism::StateActionReward>
const& stateActionRewards,
799 std::vector<storm::prism::TransitionReward>
const& transitionRewards)
const {
800 return storm::prism::RewardModel(rewardModelName, stateRewards, stateActionRewards, transitionRewards, this->getFilename());
803storm::prism::StateReward PrismParserGrammar::createStateReward(storm::expressions::Expression statePredicateExpression,
804 storm::expressions::Expression rewardValueExpression)
const {
805 if (this->secondRun) {
806 return storm::prism::StateReward(statePredicateExpression, rewardValueExpression, this->getFilename());
808 return storm::prism::StateReward();
812storm::prism::StateActionReward PrismParserGrammar::createStateActionReward(boost::optional<std::string>
const& actionName,
813 storm::expressions::Expression statePredicateExpression,
814 storm::expressions::Expression rewardValueExpression,
816 if (this->secondRun) {
817 std::string realActionName = actionName ? actionName.get() :
"";
819 auto const& nameIndexPair = globalProgramInformation.actionIndices.find(realActionName);
820 STORM_LOG_THROW(nameIndexPair != globalProgramInformation.actionIndices.end(), storm::exceptions::WrongFormatException,
821 "Action reward refers to illegal action '" << realActionName <<
"'.");
822 return storm::prism::StateActionReward(nameIndexPair->second, realActionName, statePredicateExpression, rewardValueExpression, this->getFilename());
824 return storm::prism::StateActionReward();
828storm::prism::TransitionReward PrismParserGrammar::createTransitionReward(boost::optional<std::string>
const& actionName,
829 storm::expressions::Expression sourceStatePredicateExpression,
830 storm::expressions::Expression targetStatePredicateExpression,
831 storm::expressions::Expression rewardValueExpression,
833 if (this->secondRun) {
834 std::string realActionName = actionName ? actionName.get() :
"";
836 auto const& nameIndexPair = globalProgramInformation.actionIndices.find(realActionName);
837 STORM_LOG_THROW(nameIndexPair != globalProgramInformation.actionIndices.end(), storm::exceptions::WrongFormatException,
838 "Transition reward refers to illegal action '" << realActionName <<
"'.");
839 return storm::prism::TransitionReward(nameIndexPair->second, realActionName, sourceStatePredicateExpression, targetStatePredicateExpression,
840 rewardValueExpression, this->getFilename());
842 return storm::prism::TransitionReward();
846storm::prism::Assignment PrismParserGrammar::createAssignment(std::string
const& variableName, storm::expressions::Expression assignedExpression)
const {
847 return storm::prism::Assignment(manager->getVariable(variableName), assignedExpression, this->getFilename());
851 std::vector<storm::prism::Assignment>
const& assignments,
853 ++globalProgramInformation.currentUpdateIndex;
854 if (!likelihoodExpressions.first.isInitialized()) {
855 likelihoodExpressions.first = manager->rational(1);
857 return storm::prism::Update(globalProgramInformation.currentUpdateIndex - 1, likelihoodExpressions, assignments, this->getFilename());
860storm::prism::Command PrismParserGrammar::createCommand(
bool markovian, boost::optional<std::string>
const& actionName,
861 storm::expressions::Expression guardExpression, std::vector<storm::prism::Update>
const& updates,
863 ++globalProgramInformation.currentCommandIndex;
864 std::string realActionName = actionName ? actionName.get() :
"";
866 uint_fast64_t actionIndex = 0;
869 auto nameIndexPair = globalProgramInformation.actionIndices.find(realActionName);
870 if (nameIndexPair == globalProgramInformation.actionIndices.end()) {
871 std::size_t nextIndex = globalProgramInformation.actionIndices.size();
872 globalProgramInformation.actionIndices.emplace(realActionName, nextIndex);
873 actionIndex = nextIndex;
875 actionIndex = nameIndexPair->second;
877 return storm::prism::Command(globalProgramInformation.currentCommandIndex - 1, markovian, actionIndex, realActionName, guardExpression, updates,
878 this->getFilename());
881storm::prism::Command PrismParserGrammar::createDummyCommand(boost::optional<std::string>
const& actionName,
883 STORM_LOG_ASSERT(!this->secondRun,
"Dummy procedure must not be called in second run.");
884 std::string realActionName = actionName ? actionName.get() :
"";
887 auto nameIndexPair = globalProgramInformation.actionIndices.find(realActionName);
888 if (nameIndexPair == globalProgramInformation.actionIndices.end()) {
889 std::size_t nextIndex = globalProgramInformation.actionIndices.size();
890 globalProgramInformation.actionIndices.emplace(realActionName, nextIndex);
893 return storm::prism::Command();
896storm::prism::BooleanVariable PrismParserGrammar::createBooleanVariable(std::string
const& variableName,
897 storm::expressions::Expression initialValueExpression)
const {
898 if (!this->secondRun) {
900 storm::expressions::Variable newVariable = manager->declareBooleanVariable(variableName);
901 this->identifiers_.add(variableName, newVariable.
getExpression());
902 }
catch (storm::exceptions::InvalidArgumentException
const&) {
904 "Parsing error in " << this->getFilename() <<
": illegal identifier '" << variableName <<
"'.");
907 bool const observable = this->observables.count(variableName) > 0;
909 this->observables.at(variableName) =
true;
911 return storm::prism::BooleanVariable(manager->getVariable(variableName), initialValueExpression, observable, this->getFilename());
914storm::prism::IntegerVariable PrismParserGrammar::createIntegerVariable(std::string
const& variableName, storm::expressions::Expression lowerBoundExpression,
915 storm::expressions::Expression upperBoundExpression,
916 storm::expressions::Expression initialValueExpression)
const {
917 if (!this->secondRun) {
919 storm::expressions::Variable newVariable = manager->declareIntegerVariable(variableName);
920 this->identifiers_.add(variableName, newVariable.
getExpression());
921 }
catch (storm::exceptions::InvalidArgumentException
const&) {
923 "Parsing error in " << this->getFilename() <<
": illegal identifier '" << variableName <<
"'.");
926 bool const observable = this->observables.count(variableName) > 0;
928 this->observables.at(variableName) =
true;
931 return storm::prism::IntegerVariable(manager->getVariable(variableName), lowerBoundExpression, upperBoundExpression, initialValueExpression, observable,
932 this->getFilename());
935storm::prism::ClockVariable PrismParserGrammar::createClockVariable(std::string
const& variableName)
const {
936 if (!this->secondRun) {
938 storm::expressions::Variable newVariable = manager->declareRationalVariable(variableName);
939 this->identifiers_.add(variableName, newVariable.
getExpression());
940 }
catch (storm::exceptions::InvalidArgumentException
const&) {
942 "Parsing error in " << this->getFilename() <<
": illegal identifier '" << variableName <<
"'.");
945 bool const observable = this->observables.count(variableName) > 0;
947 this->observables.at(variableName) =
true;
950 return storm::prism::ClockVariable(manager->getVariable(variableName), observable, this->getFilename());
953bool PrismParserGrammar::addObservablesConstruct(std::vector<std::string>
const& observables,
GlobalProgramInformation& globalProgramInformation) {
954 STORM_LOG_THROW(!globalProgramInformation.hasObservablesConstruct, storm::exceptions::WrongFormatException,
955 "Parsing error in " << this->getFilename() <<
": Program must not define two observables constructs.");
956 if (globalProgramInformation.hasObservablesConstruct) {
959 globalProgramInformation.hasObservablesConstruct =
true;
960 for (
auto const& observable : observables) {
961 this->observables[observable] =
false;
966storm::prism::Player PrismParserGrammar::createPlayer(std::string
const& playerName, std::vector<std::string>
const& moduleNames,
967 std::vector<std::string>
const& actionNames) {
968 if (this->secondRun) {
969 std::unordered_set<std::string> controlledModules;
970 std::unordered_set<std::string> controlledActions;
971 for (
auto const& moduleName : moduleNames) {
972 auto moduleIndexPair = globalProgramInformation.moduleToIndexMap.find(moduleName);
973 STORM_LOG_ASSERT(moduleIndexPair != globalProgramInformation.moduleToIndexMap.end(),
974 "Parsing error in " << this->getFilename() <<
" for player " << playerName <<
": No module named '" << moduleName <<
"' present.");
975 controlledModules.insert(moduleIndexPair->first);
976 bool moduleNotYetControlled = globalProgramInformation.playerControlledModules.insert(moduleIndexPair->second).second;
977 STORM_LOG_THROW(moduleNotYetControlled, storm::exceptions::WrongFormatException,
978 "Parsing error in " << this->getFilename() <<
" for player " << playerName <<
": Module '" << moduleName
979 <<
"' already controlled by another player.");
981 for (std::string actionName : actionNames) {
982 auto actionIndexPair = globalProgramInformation.actionIndices.find(actionName);
983 STORM_LOG_ASSERT(actionIndexPair != globalProgramInformation.actionIndices.end(),
984 "Parsing error in " << this->getFilename() <<
" for player " << playerName <<
": No action named '" << actionName <<
"' present.");
985 controlledActions.insert(actionIndexPair->first);
986 bool actionNotYetControlled = globalProgramInformation.playerControlledActions.insert(actionIndexPair->second).second;
987 STORM_LOG_THROW(actionNotYetControlled, storm::exceptions::WrongFormatException,
988 "Parsing error in " << this->getFilename() <<
" for player " << playerName <<
": Command '" << actionName
989 <<
"' already controlled by another player.");
991 return storm::prism::Player(playerName, controlledModules, controlledActions);
993 return storm::prism::Player();
997storm::prism::Module PrismParserGrammar::createModule(std::string
const& moduleName, std::vector<storm::prism::BooleanVariable>
const& booleanVariables,
998 std::vector<storm::prism::IntegerVariable>
const& integerVariables,
999 std::vector<storm::prism::ClockVariable>
const& clockVariables,
1000 boost::optional<storm::expressions::Expression>
const& invariant,
1001 std::vector<storm::prism::Command>
const& commands,
1003 if (!this->secondRun) {
1004 globalProgramInformation.moduleToIndexMap[moduleName] = globalProgramInformation.modules.size();
1007 STORM_LOG_ASSERT(!this->secondRun || globalProgramInformation.moduleToIndexMap.count(moduleName) > 0,
"Module name '" << moduleName <<
"' was not found.");
1008 STORM_LOG_ASSERT(!this->secondRun || globalProgramInformation.moduleToIndexMap[moduleName] == globalProgramInformation.modules.size(),
1009 "The index for module '" << moduleName <<
"' does not match the index from the first parsing run.");
1010 return storm::prism::Module(moduleName, booleanVariables, integerVariables, clockVariables,
1011 invariant.is_initialized() ? invariant.get() : storm::expressions::Expression(), commands, this->getFilename());
1014bool PrismParserGrammar::isValidModuleRenaming(std::string
const& oldModuleName, storm::prism::ModuleRenaming
const& moduleRenaming,
1016 if (!this->secondRun) {
1017 auto const& renaming = moduleRenaming.getRenaming();
1018 auto const& moduleIndexPair = globalProgramInformation.moduleToIndexMap.find(oldModuleName);
1019 if (moduleIndexPair == globalProgramInformation.moduleToIndexMap.end()) {
1020 STORM_LOG_ERROR(
"Parsing error in " << this->getFilename() <<
": No module named '" << oldModuleName <<
"' to rename.");
1023 storm::prism::Module
const& moduleToRename = globalProgramInformation.modules[moduleIndexPair->second];
1026 auto const& renamingPair = renaming.find(variable.
getName());
1027 if (renamingPair == renaming.end()) {
1028 STORM_LOG_ERROR(
"Parsing error in renaming of module '" << oldModuleName <<
"': Boolean variable '" << variable.
getName()
1029 <<
"' was not renamed.");
1034 auto const& renamingPair = renaming.find(variable.
getName());
1035 if (renamingPair == renaming.end()) {
1036 STORM_LOG_ERROR(
"Parsing error in renaming of module '" << oldModuleName <<
"': Integer variable '" << variable.
getName()
1037 <<
"' was not renamed.");
1042 auto const& renamingPair = renaming.find(variable.
getName());
1043 if (renamingPair == renaming.end()) {
1044 STORM_LOG_ERROR(
"Parsing error in renaming of module '" << oldModuleName <<
"': Clock variable '" << variable.
getName()
1045 <<
"' was not renamed.");
1053storm::prism::ModuleRenaming PrismParserGrammar::createModuleRenaming(std::map<std::string, std::string>
const& renaming)
const {
1054 return storm::prism::ModuleRenaming(renaming);
1057storm::prism::Module PrismParserGrammar::createRenamedModule(std::string
const& newModuleName, std::string
const& oldModuleName,
1058 storm::prism::ModuleRenaming
const& moduleRenaming,
1061 auto const& moduleIndexPair = globalProgramInformation.moduleToIndexMap.find(oldModuleName);
1062 STORM_LOG_THROW(moduleIndexPair != globalProgramInformation.moduleToIndexMap.end(), storm::exceptions::WrongFormatException,
1063 "Parsing error in " << this->getFilename() <<
": No module named '" << oldModuleName <<
"' to rename.");
1064 storm::prism::Module
const& moduleToRename = globalProgramInformation.modules[moduleIndexPair->second];
1066 "Parsing error in " << this->getFilename() <<
": The module '" << newModuleName <<
"' can not be created from module '" << oldModuleName
1067 <<
"' through module renaming because '" << oldModuleName <<
"' is also a renamed module. Create '" << newModuleName
1068 <<
"' via a renaming from base module '" << moduleToRename.
getBaseModule() <<
"' instead.");
1069 auto const& renaming = moduleRenaming.getRenaming();
1070 if (!this->secondRun) {
1072 globalProgramInformation.moduleToIndexMap[newModuleName] = globalProgramInformation.modules.size();
1077 auto const& renamingPair = renaming.find(variable.
getName());
1078 STORM_LOG_THROW(renamingPair != renaming.end(), storm::exceptions::WrongFormatException,
1079 "Parsing error in " << this->getFilename() <<
": Boolean variable '" << variable.
getName() <<
" was not renamed.");
1080 storm::expressions::Variable renamedVariable = manager->declareBooleanVariable(renamingPair->second);
1081 this->identifiers_.add(renamingPair->second, renamedVariable.
getExpression());
1082 if (this->observables.count(renamingPair->second) > 0) {
1083 this->observables.at(renamingPair->second) =
true;
1087 auto const& renamingPair = renaming.find(variable.
getName());
1088 STORM_LOG_THROW(renamingPair != renaming.end(), storm::exceptions::WrongFormatException,
1089 "Parsing error in " << this->getFilename() <<
": Integer variable '" << variable.
getName() <<
" was not renamed.");
1090 storm::expressions::Variable renamedVariable = manager->declareIntegerVariable(renamingPair->second);
1091 this->identifiers_.add(renamingPair->second, renamedVariable.
getExpression());
1092 if (this->observables.count(renamingPair->second) > 0) {
1093 this->observables.at(renamingPair->second) =
true;
1097 auto const& renamingPair = renaming.find(variable.
getName());
1098 STORM_LOG_THROW(renamingPair != renaming.end(), storm::exceptions::WrongFormatException,
1099 "Parsing error in " << this->getFilename() <<
": Clock variable '" << variable.
getName() <<
" was not renamed.");
1100 storm::expressions::Variable renamedVariable = manager->declareRationalVariable(renamingPair->second);
1101 this->identifiers_.add(renamingPair->second, renamedVariable.
getExpression());
1102 if (this->observables.count(renamingPair->second) > 0) {
1103 this->observables.at(renamingPair->second) =
true;
1107 for (
auto const& command : moduleToRename.
getCommands()) {
1108 std::string newActionName = command.getActionName();
1109 auto const& renamingPair = renaming.find(command.getActionName());
1110 if (renamingPair != renaming.end()) {
1111 newActionName = renamingPair->second;
1115 auto nameIndexPair = globalProgramInformation.actionIndices.find(newActionName);
1116 if (nameIndexPair == globalProgramInformation.actionIndices.end()) {
1117 std::size_t nextIndex = globalProgramInformation.actionIndices.size();
1118 globalProgramInformation.actionIndices.emplace(newActionName, nextIndex);
1123 return storm::prism::Module();
1126 STORM_LOG_ASSERT(globalProgramInformation.moduleToIndexMap.count(newModuleName) > 0,
"Module name '" << newModuleName <<
"' was not found.");
1127 STORM_LOG_ASSERT(globalProgramInformation.moduleToIndexMap[newModuleName] == globalProgramInformation.modules.size(),
1128 "The index for module " << newModuleName <<
" does not match the index from the first parsing run.");
1131 std::map<storm::expressions::Variable, storm::expressions::Expression> expressionRenaming;
1132 for (
auto const& namePair : renaming) {
1133 storm::expressions::Expression
const* substitutedExpression = this->identifiers_.find(namePair.second);
1135 if (substitutedExpression !=
nullptr) {
1136 expressionRenaming.emplace(manager->getVariable(namePair.first), *substitutedExpression);
1141 std::vector<storm::prism::BooleanVariable> booleanVariables;
1143 auto const& renamingPair = renaming.find(variable.
getName());
1144 STORM_LOG_THROW(renamingPair != renaming.end(), storm::exceptions::WrongFormatException,
1145 "Parsing error in " << this->getFilename() <<
": Boolean variable '" << variable.
getName() <<
" was not renamed.");
1146 bool const observable = this->observables.count(renamingPair->second) > 0;
1148 this->observables.at(renamingPair->second) =
true;
1150 booleanVariables.push_back(storm::prism::BooleanVariable(
1151 manager->getVariable(renamingPair->second),
1152 variable.hasInitialValue() ? variable.getInitialValueExpression().substitute(expressionRenaming) : variable.getInitialValueExpression(),
1153 observable, this->getFilename(), moduleRenaming.getLineNumber()));
1157 std::vector<storm::prism::IntegerVariable> integerVariables;
1159 auto const& renamingPair = renaming.find(variable.
getName());
1160 STORM_LOG_THROW(renamingPair != renaming.end(), storm::exceptions::WrongFormatException,
1161 "Parsing error in " << this->getFilename() <<
": Integer variable '" << variable.
getName() <<
" was not renamed.");
1162 bool const observable = this->observables.count(renamingPair->second) > 0;
1164 this->observables.at(renamingPair->second) =
true;
1166 integerVariables.push_back(storm::prism::IntegerVariable(
1167 manager->getVariable(renamingPair->second), variable.getLowerBoundExpression().substitute(expressionRenaming),
1168 variable.getUpperBoundExpression().substitute(expressionRenaming),
1169 variable.hasInitialValue() ? variable.getInitialValueExpression().substitute(expressionRenaming) : variable.getInitialValueExpression(),
1170 observable, this->getFilename(), moduleRenaming.getLineNumber()));
1174 std::vector<storm::prism::ClockVariable> clockVariables;
1176 auto const& renamingPair = renaming.find(variable.
getName());
1177 STORM_LOG_THROW(renamingPair != renaming.end(), storm::exceptions::WrongFormatException,
1178 "Parsing error in " << this->getFilename() <<
": Clock variable '" << variable.
getName() <<
" was not renamed.");
1179 bool const observable = this->observables.count(renamingPair->second) > 0;
1181 this->observables.at(renamingPair->second) =
true;
1183 clockVariables.push_back(
1184 storm::prism::ClockVariable(manager->getVariable(renamingPair->second), observable, this->getFilename(), moduleRenaming.getLineNumber()));
1188 storm::expressions::Expression invariant;
1194 std::vector<storm::prism::Command> commands;
1195 for (
auto const& command : moduleToRename.
getCommands()) {
1196 std::vector<storm::prism::Update> updates;
1197 for (
auto const& update : command.getUpdates()) {
1198 std::vector<storm::prism::Assignment> assignments;
1199 for (
auto const& assignment : update.getAssignments()) {
1200 auto const& renamingPair = renaming.find(assignment.getVariableName());
1201 if (renamingPair != renaming.end()) {
1202 assignments.emplace_back(manager->getVariable(renamingPair->second), assignment.getExpression().substitute(expressionRenaming),
1203 this->getFilename(), moduleRenaming.getLineNumber());
1205 assignments.emplace_back(assignment.getVariable(), assignment.getExpression().substitute(expressionRenaming), this->getFilename(),
1206 moduleRenaming.getLineNumber());
1209 if (update.isLikelihoodInterval()) {
1211 update.getLikelihoodExpressionInterval().first.substitute(expressionRenaming),
1212 update.getLikelihoodExpressionInterval().second.substitute(expressionRenaming)};
1213 updates.emplace_back(globalProgramInformation.currentUpdateIndex, likelihoodInterval, assignments, this->getFilename(),
1214 moduleRenaming.getLineNumber());
1216 updates.emplace_back(globalProgramInformation.currentUpdateIndex, update.getLikelihoodExpression().substitute(expressionRenaming),
1217 assignments, this->getFilename(), moduleRenaming.getLineNumber());
1219 ++globalProgramInformation.currentUpdateIndex;
1222 std::string newActionName = command.getActionName();
1223 auto const& renamingPair = renaming.find(command.getActionName());
1224 if (renamingPair != renaming.end()) {
1225 newActionName = renamingPair->second;
1228 uint_fast64_t actionIndex = 0;
1229 auto nameIndexPair = globalProgramInformation.actionIndices.find(newActionName);
1230 if (nameIndexPair == globalProgramInformation.actionIndices.end()) {
1231 std::size_t nextIndex = globalProgramInformation.actionIndices.size();
1232 globalProgramInformation.actionIndices.emplace(newActionName, nextIndex);
1233 actionIndex = nextIndex;
1235 actionIndex = nameIndexPair->second;
1238 commands.emplace_back(globalProgramInformation.currentCommandIndex, command.isMarkovian(), actionIndex, newActionName,
1239 command.getGuardExpression().substitute(expressionRenaming), updates, this->getFilename(), moduleRenaming.getLineNumber());
1240 ++globalProgramInformation.currentCommandIndex;
1243 return storm::prism::Module(newModuleName, booleanVariables, integerVariables, clockVariables, invariant, commands, oldModuleName, renaming);
1247storm::prism::Program PrismParserGrammar::createProgram(
GlobalProgramInformation const& globalProgramInformation)
const {
1250 STORM_LOG_WARN(
"Program does not specify model type. Implicitly assuming 'mdp'.");
1255 std::vector<storm::prism::Formula> orderedFormulas;
1256 if (this->secondRun) {
1257 orderedFormulas.reserve(globalProgramInformation.formulas.size());
1258 for (uint64_t
const& i : formulaOrder) {
1259 orderedFormulas.push_back(std::move(globalProgramInformation.formulas[i]));
1263 return storm::prism::Program(
1264 manager, finalModelType, globalProgramInformation.constants, globalProgramInformation.globalBooleanVariables,
1265 globalProgramInformation.globalIntegerVariables, orderedFormulas, globalProgramInformation.players, globalProgramInformation.modules,
1266 globalProgramInformation.actionIndices, globalProgramInformation.rewardModels, globalProgramInformation.labels,
1267 globalProgramInformation.observationLabels,
1268 secondRun && !globalProgramInformation.hasInitialConstruct ? boost::none : boost::make_optional(globalProgramInformation.initialConstruct),
1269 globalProgramInformation.systemCompositionConstruct, prismCompatibility, this->getFilename(), 1, this->secondRun);
1273 globalProgramInformation.hasInitialConstruct =
false;
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::vector< storm::prism::Command > const & getCommands() const
Retrieves the commands of the module.
std::string const & getBaseModule() const
If the module was created via renaming, this method retrieves the name of the module that was used as...
std::vector< storm::prism::IntegerVariable > const & getIntegerVariables() const
Retrieves the integer variables of the module.
std::vector< storm::prism::BooleanVariable > const & getBooleanVariables() const
Retrieves the boolean variables of the module.
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::vector< storm::prism::ClockVariable > const & getClockVariables() const
Retrieves the clock variables of the module.
ModelType
An enum for the different model types.
std::pair< storm::expressions::Expression, storm::expressions::Expression > ExpressionPair
#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.
Contains all file parsers and helper classes.