#ifndef STORM_PARSER_PRISMPARSER_H_ #define STORM_PARSER_PRISMPARSER_H_ // Include files for file input. #include #include #include #include "storm-parsers/parser/SpiritParserDefinitions.h" #include "storm-parsers/parser/SpiritErrorHandler.h" #include "storm/storage/prism/Program.h" #include "storm/storage/expressions/Expression.h" namespace storm { namespace expressions { class ExpressionManager; } } namespace storm { namespace parser { class ExpressionParser; // A class that stores information about the parsed program. class GlobalProgramInformation { public: // Default construct the header information. GlobalProgramInformation() : modelType(storm::prism::Program::ModelType::UNDEFINED), constants(), formulas(), globalBooleanVariables(), globalIntegerVariables(), moduleToIndexMap(), actionIndices(), modules(), rewardModels(), labels(), hasInitialConstruct(false), initialConstruct(), systemCompositionConstruct(boost::none), currentCommandIndex(0), currentUpdateIndex(0) { // Map the empty action to index 0. actionIndices.emplace("", 0); } void moveToSecondRun() { // Clear all data except the action to indices mapping. modelType = storm::prism::Program::ModelType::UNDEFINED; constants.clear(); formulas.clear(); globalBooleanVariables.clear(); globalIntegerVariables.clear(); players.clear(); playerControlledModules.clear(); playerControlledActions.clear(); modules.clear(); rewardModels.clear(); labels.clear(); observationLabels.clear(); hasInitialConstruct = false; initialConstruct = storm::prism::InitialConstruct(); systemCompositionConstruct = boost::none; currentCommandIndex = 0; currentUpdateIndex = 0; } // Members for all essential information that needs to be collected. storm::prism::Program::ModelType modelType; std::vector constants; std::vector formulas; std::vector globalBooleanVariables; std::vector globalIntegerVariables; std::map moduleToIndexMap; std::map actionIndices; std::vector modules; std::vector rewardModels; std::vector labels; std::vector observationLabels; std::vector players; std::set playerControlledModules; std::set playerControlledActions; bool hasInitialConstruct; storm::prism::InitialConstruct initialConstruct; boost::optional systemCompositionConstruct; // Counters to provide unique indexing for commands and updates. uint_fast64_t currentCommandIndex; uint_fast64_t currentUpdateIndex; }; class PrismParser : public qi::grammar { public: /*! * Parses the given file into the PRISM storage classes assuming it complies with the PRISM syntax. * * @param filename the name of the file to parse. * @return The resulting PRISM program. */ static storm::prism::Program parse(std::string const& filename, bool prismCompatability = false); /*! * Parses the given input stream into the PRISM storage classes assuming it complies with the PRISM syntax. * * @param input The input string to parse. * @param filename The name of the file from which the input was read. * @return The resulting PRISM program. */ static storm::prism::Program parseFromString(std::string const& input, std::string const& filename, bool prismCompatability = false); private: struct modelTypeStruct : qi::symbols { modelTypeStruct() { add ("dtmc", storm::prism::Program::ModelType::DTMC) ("ctmc", storm::prism::Program::ModelType::CTMC) ("mdp", storm::prism::Program::ModelType::MDP) ("ctmdp", storm::prism::Program::ModelType::CTMDP) ("ma", storm::prism::Program::ModelType::MA) ("pomdp", storm::prism::Program::ModelType::POMDP) ("pta", storm::prism::Program::ModelType::PTA) ("smg", storm::prism::Program::ModelType::SMG); } }; struct keywordsStruct : qi::symbols { keywordsStruct() { add ("dtmc", 1) ("ctmc", 2) ("mdp", 3) ("ctmdp", 4) ("ma", 5) ("pomdp", 6) ("pta", 7) ("smg", 8) ("const", 9) ("int", 10) ("bool", 11) ("module", 12) ("endmodule", 13) ("rewards", 14) ("endrewards", 15) ("true", 16) ("false", 17) ("min", 18) ("max", 19) ("floor", 20) ("ceil", 21) ("init", 22) ("atLeastOneOf", 23) ("atMostOneOf", 24) ("exactlyOneOf", 25) ("endinit", 26) ("invariant", 27) ("endinvariant", 28) ("player", 29) ("endplayer", 30); } }; // Functor used for annotating entities with line number information. class PositionAnnotation { public: typedef void result_type; PositionAnnotation(Iterator first) : first(first) { // Intentionally left empty. } template result_type operator()(Entity& entity, First f, Last) const { entity.setLineNumber(get_line(f)); } private: std::string filename; Iterator const first; }; /*! * Creates a grammar for the given filename and the iterator to the first input to parse. * * @param filename The filename that is to be read. This is used for proper error reporting. * @param first The iterator to the beginning of the input. */ PrismParser(std::string const& filename, Iterator first, bool prismCompatibility); /*! * Sets an internal flag that indicates the second run is now taking place. */ void moveToSecondRun(); /*! * Parses the stored formula Expressions. */ void createFormulaIdentifiers(std::vector const& formulas); // A flag that stores whether the grammar is currently doing the second run. bool secondRun; bool prismCompatibility; /*! * Sets whether doubles literals are allowed in the parsed expression. * * @param flag Indicates whether to allow or forbid double literals in the parsed expression. */ void allowDoubleLiterals(bool flag); // The name of the file being parsed. std::string filename; /*! * Retrieves the name of the file currently being parsed. * * @return The name of the file currently being parsed. */ std::string const& getFilename() const; mutable std::set observables; // Store the expressions of formulas. They have to be parsed after the first and before the second run std::vector formulaExpressions; // Stores a proper order in which formulas can be evaluated. This is necessary since formulas might depend on each other. // E.g. for "formula x = y; formula y = z;" we have to swap the order of the two formulas. std::vector formulaOrder; // A function used for annotating the entities with their position. phoenix::function annotate; // An object gathering information about the program while parsing. GlobalProgramInformation globalProgramInformation; // The starting point of the grammar. qi::rule start; // Rules for model type. qi::rule modelTypeDefinition; // Rules for parsing expressions of specific type qi::rule boolExpression; qi::rule intExpression; qi::rule numericalExpression; // Rules for parsing the program header. qi::rule undefinedConstantDefinition; qi::rule undefinedBooleanConstantDefinition; qi::rule undefinedIntegerConstantDefinition; qi::rule undefinedDoubleConstantDefinition; qi::rule definedConstantDefinition; qi::rule definedBooleanConstantDefinition; qi::rule definedIntegerConstantDefinition; qi::rule definedDoubleConstantDefinition; // Rules for global variable definitions. qi::rule globalVariableDefinition; // Rules for modules definition. qi::rule knownModuleName; qi::rule freshModuleName; qi::rule, std::vector, std::vector>, Skipper> moduleDefinition; qi::rule>, Skipper> moduleRenaming; qi::rule, Skipper> renamedModule; // Rules for variable definitions. qi::rule&, std::vector&, std::vector&), Skipper> variableDefinition; qi::rule, Skipper> booleanVariableDefinition; qi::rule, Skipper> integerVariableDefinition; qi::rule, Skipper> boundedIntegerVariableDefinition; qi::rule, Skipper> unboundedIntegerVariableDefinition; qi::rule, Skipper> clockVariableDefinition; // Rules for command definitions. qi::rule, Skipper> commandDefinition; qi::rule(GlobalProgramInformation&), Skipper> updateListDefinition; qi::rule updateDefinition; qi::rule(), Skipper> assignmentDefinitionList; qi::rule assignmentDefinition; qi::rule knownActionName; // Rules for reward definitions. qi::rule freshRewardModelName; qi::rule, std::vector, std::vector>, Skipper> rewardModelDefinition; qi::rule stateRewardDefinition; qi::rule stateActionRewardDefinition; qi::rule, Skipper> transitionRewardDefinition; // Rules for player definitions qi::rule freshPlayerName; qi::rule, Skipper> playerControlledActionName; qi::rule, Skipper> playerControlledModuleName; qi::rule, std::vector>, Skipper> playerConstruct; // Rules for initial states expression. qi::rule initialStatesConstruct; // Rules for POMDP observables (standard prism) qi::rule observablesConstruct; // Rules for invariant constructs qi::rule invariantConstruct; // Rules for the system composition. qi::rule systemCompositionConstruct; qi::rule(), Skipper> parallelComposition; qi::rule synchronizingParallelComposition; qi::rule interleavingParallelComposition; qi::rule(), Skipper> restrictedParallelComposition; qi::rule(), Skipper> hidingOrRenamingComposition; qi::rule(), Skipper> hidingComposition; qi::rule(), Skipper> renamingComposition; qi::rule(), Skipper> atomicComposition; qi::rule(), Skipper> moduleComposition; qi::rule(), Skipper> actionNameList; qi::rule(), Skipper> actionRenamingList; // Rules for label definitions. qi::rule labelDefinition; qi::rule freshLabelName; // Rules for observable (observation-label) definitions. qi::rule observableDefinition; qi::rule freshObservationLabelName; // Rules for formula definitions. qi::rule formulaDefinitionRhs; qi::rule formulaDefinition; // Rules for identifier parsing. qi::rule identifier; qi::rule freshIdentifier; // Parsers that recognize special keywords and model types. storm::parser::PrismParser::keywordsStruct keywords_; storm::parser::PrismParser::modelTypeStruct modelType_; qi::symbols identifiers_; // Parser and manager used for recognizing expressions. std::shared_ptr manager; std::shared_ptr expressionParser; // Helper methods used in the grammar. bool isValidIdentifier(std::string const& identifier); bool isFreshIdentifier(std::string const& identifier); bool isKnownModuleName(std::string const& moduleName, bool inSecondRun); bool isFreshModuleName(std::string const& moduleName); bool isKnownActionName(std::string const& actionName, bool inSecondRun); bool isFreshLabelName(std::string const& moduleName); bool isFreshObservationLabelName(std::string const& labelName); bool isFreshRewardModelName(std::string const& moduleName); bool isFreshPlayerName(std::string const& playerName); bool isOfBoolType(storm::expressions::Expression const& expression); bool isOfIntType(storm::expressions::Expression const& expression); bool isOfNumericalType(storm::expressions::Expression const& expression); bool isValidModuleRenaming(std::string const& oldModuleName, storm::prism::ModuleRenaming const& renaming, GlobalProgramInformation const& globalProgramInformation) const; bool addInitialStatesConstruct(storm::expressions::Expression const& initialStatesExpression, GlobalProgramInformation& globalProgramInformation); bool addSystemCompositionConstruct(std::shared_ptr const& composition, GlobalProgramInformation& globalProgramInformation); void setModelType(GlobalProgramInformation& globalProgramInformation, storm::prism::Program::ModelType const& modelType); std::shared_ptr createModuleComposition(std::string const& moduleName) const; std::shared_ptr createRenamingComposition(std::shared_ptr const& subcomposition, std::map const& renaming) const; std::shared_ptr createHidingComposition(std::shared_ptr const& subcomposition, std::set const& actionsToHide) const; std::shared_ptr createSynchronizingParallelComposition(std::shared_ptr const& left, std::shared_ptr const& right) const; std::shared_ptr createInterleavingParallelComposition(std::shared_ptr const& left, std::shared_ptr const& right) const; std::shared_ptr createRestrictedParallelComposition(std::shared_ptr const& left, std::set const& synchronizingActions, std::shared_ptr const& right) const; storm::prism::Constant createUndefinedBooleanConstant(std::string const& newConstant) const; storm::prism::Constant createUndefinedIntegerConstant(std::string const& newConstant) const; storm::prism::Constant createUndefinedDoubleConstant(std::string const& newConstant) const; storm::prism::Constant createDefinedBooleanConstant(std::string const& newConstant, storm::expressions::Expression expression) const; storm::prism::Constant createDefinedIntegerConstant(std::string const& newConstant, storm::expressions::Expression expression) const; storm::prism::Constant createDefinedDoubleConstant(std::string const& newConstant, storm::expressions::Expression expression) const; storm::prism::Formula createFormulaFirstRun(std::string const& formulaName, std::string const& expression); storm::prism::Formula createFormulaSecondRun(std::string const& formulaName, storm::expressions::Expression const& expression); storm::prism::Label createLabel(std::string const& labelName, storm::expressions::Expression expression) const; storm::prism::ObservationLabel createObservationLabel(std::string const& labelName, storm::expressions::Expression expression) const; storm::prism::RewardModel createRewardModel(std::string const& rewardModelName, std::vector const& stateRewards, std::vector const& stateActionRewards, std::vector const& transitionRewards) const; storm::prism::StateReward createStateReward(storm::expressions::Expression statePredicateExpression, storm::expressions::Expression rewardValueExpression) const; storm::prism::StateActionReward createStateActionReward(boost::optional const& actionName, storm::expressions::Expression statePredicateExpression, storm::expressions::Expression rewardValueExpression, GlobalProgramInformation& globalProgramInformation) const; storm::prism::TransitionReward createTransitionReward(boost::optional const& actionName, storm::expressions::Expression sourceStatePredicateExpression, storm::expressions::Expression targetStatePredicateExpression, storm::expressions::Expression rewardValueExpression, GlobalProgramInformation& globalProgramInformation) const; storm::prism::Assignment createAssignment(std::string const& variableName, storm::expressions::Expression assignedExpression) const; storm::prism::Update createUpdate(storm::expressions::Expression likelihoodExpression, std::vector const& assignments, GlobalProgramInformation& globalProgramInformation) const; storm::prism::Command createCommand(bool markovianCommand, boost::optional const& actionName, storm::expressions::Expression guardExpression, std::vector const& updates, GlobalProgramInformation& globalProgramInformation) const; storm::prism::Command createDummyCommand(boost::optional const& actionName, GlobalProgramInformation& globalProgramInformation) const; storm::prism::BooleanVariable createBooleanVariable(std::string const& variableName, storm::expressions::Expression initialValueExpression) const; storm::prism::IntegerVariable createIntegerVariable(std::string const& variableName, storm::expressions::Expression lowerBoundExpression, storm::expressions::Expression upperBoundExpression, storm::expressions::Expression initialValueExpression) const; storm::prism::ClockVariable createClockVariable(std::string const& variableName) const; storm::prism::Module createModule(std::string const& moduleName, std::vector const& booleanVariables, std::vector const& integerVariables, std::vector const& clockVariables, boost::optional const& invariant, std::vector const& commands, GlobalProgramInformation& globalProgramInformation) const; storm::prism::ModuleRenaming createModuleRenaming(std::map const& renaming) const; storm::prism::Module createRenamedModule(std::string const& newModuleName, std::string const& oldModuleName, storm::prism::ModuleRenaming const& renaming, GlobalProgramInformation& globalProgramInformation) const; storm::prism::Player createPlayer(std::string const& playerName, std::vector const& moduleNames, std::vector const & commandNames); storm::prism::Program createProgram(GlobalProgramInformation const& globalProgramInformation) const; void createObservablesList(std::vector const& observables); void removeInitialConstruct(GlobalProgramInformation& globalProgramInformation) const; // An error handler function. phoenix::function handler; }; } // namespace parser } // namespace storm #endif /* STORM_PARSER_PRISMPARSER_H_ */