#pragma once #include #include #include "storm-parsers/parser/SpiritErrorHandler.h" #include "storm/exceptions/WrongFormatException.h" #include "storm/storage/jani/Property.h" #include "storm/logic/Formulas.h" #include "storm-parsers/parser/ExpressionParser.h" #include "storm/modelchecker/results/FilterType.h" #include "storm/storage/expressions/ExpressionEvaluator.h" namespace storm { namespace logic { class Formula; } namespace parser { class FormulaParserGrammar : public qi::grammar(), Skipper> { public: FormulaParserGrammar(std::shared_ptr const& manager); FormulaParserGrammar(std::shared_ptr const& manager); FormulaParserGrammar(FormulaParserGrammar const& other) = default; FormulaParserGrammar& operator=(FormulaParserGrammar const& other) = default; /*! * Adds an identifier and the expression it is supposed to be replaced with. This can, for example be used * to substitute special identifiers in the formula by expressions. * * @param identifier The identifier that is supposed to be substituted. * @param expression The expression it is to be substituted with. */ void addIdentifierExpression(std::string const& identifier, storm::expressions::Expression const& expression); private: void initialize(); struct keywordsStruct : qi::symbols { keywordsStruct() { add ("true", 1) ("false", 2) ("min", 3) ("max", 4) ("F", 5) ("G", 6) ("X", 7) ("multi", 8); } }; // A parser used for recognizing the keywords. keywordsStruct keywords_; struct relationalOperatorStruct : qi::symbols { relationalOperatorStruct() { add (">=", storm::logic::ComparisonType::GreaterEqual) (">", storm::logic::ComparisonType::Greater) ("<=", storm::logic::ComparisonType::LessEqual) ("<", storm::logic::ComparisonType::Less); } }; // A parser used for recognizing the operators at the "relational" precedence level. relationalOperatorStruct relationalOperator_; struct binaryBooleanOperatorStruct : qi::symbols { binaryBooleanOperatorStruct() { add ("&", storm::logic::BinaryBooleanStateFormula::OperatorType::And) ("|", storm::logic::BinaryBooleanStateFormula::OperatorType::Or); } }; // A parser used for recognizing the operators at the "binary" precedence level. binaryBooleanOperatorStruct binaryBooleanOperator_; struct unaryBooleanOperatorStruct : qi::symbols { unaryBooleanOperatorStruct() { add ("!", storm::logic::UnaryBooleanStateFormula::OperatorType::Not); } }; // A parser used for recognizing the operators at the "unary" precedence level. unaryBooleanOperatorStruct unaryBooleanOperator_; struct optimalityOperatorStruct : qi::symbols { optimalityOperatorStruct() { add ("min", storm::OptimizationDirection::Minimize) ("max", storm::OptimizationDirection::Maximize); } }; // A parser used for recognizing the optimality operators. optimalityOperatorStruct optimalityOperator_; struct rewardMeasureTypeStruct : qi::symbols { rewardMeasureTypeStruct() { add ("exp", storm::logic::RewardMeasureType::Expectation) ("var", storm::logic::RewardMeasureType::Variance); } }; // A parser used for recognizing the reward measure types. rewardMeasureTypeStruct rewardMeasureType_; struct filterTypeStruct : qi::symbols { filterTypeStruct() { add ("min", storm::modelchecker::FilterType::MIN) ("max", storm::modelchecker::FilterType::MAX) ("sum", storm::modelchecker::FilterType::SUM) ("avg", storm::modelchecker::FilterType::AVG) ("count", storm::modelchecker::FilterType::COUNT) ("forall", storm::modelchecker::FilterType::FORALL) ("exists", storm::modelchecker::FilterType::EXISTS) ("argmin", storm::modelchecker::FilterType::ARGMIN) ("argmax", storm::modelchecker::FilterType::ARGMAX) ("values", storm::modelchecker::FilterType::VALUES); } }; // A parser used for recognizing the filter type. filterTypeStruct filterType_; // The manager used to parse expressions. std::shared_ptr constManager; std::shared_ptr manager; // Parser and manager used for recognizing expressions. storm::parser::ExpressionParser expressionParser; // A symbol table that is a mapping from identifiers that can be used in expressions to the expressions // they are to be replaced with. qi::symbols identifiers_; qi::rule(), Skipper> start; enum class ConstantDataType { Bool, Integer, Rational }; qi::rule, Skipper> constantDefinition; qi::rule identifier; qi::rule formulaName; qi::rule, boost::optional, boost::optional>, Skipper> operatorInformation; qi::rule rewardMeasureType; qi::rule(), Skipper> probabilityOperator; qi::rule(), Skipper> rewardOperator; qi::rule(), Skipper> timeOperator; qi::rule(), Skipper> longRunAverageOperator; qi::rule filterProperty; qi::rule(), Skipper> simpleFormula; qi::rule(), Skipper> stateFormula; qi::rule(storm::logic::FormulaContext), Skipper> pathFormula; qi::rule(storm::logic::FormulaContext), Skipper> pathFormulaWithoutUntil; qi::rule(), Skipper> simplePathFormula; qi::rule(), Skipper> atomicStateFormula; qi::rule(), Skipper> atomicStateFormulaWithoutExpression; qi::rule(), Skipper> operatorFormula; qi::rule label; qi::rule rewardModelName; qi::rule(), Skipper> andStateFormula; qi::rule(), Skipper> orStateFormula; qi::rule(), Skipper> notStateFormula; qi::rule(), Skipper> labelFormula; qi::rule(), Skipper> expressionFormula; qi::rule(), qi::locals, Skipper> booleanLiteralFormula; qi::rule(storm::logic::FormulaContext), Skipper> conditionalFormula; qi::rule(storm::logic::FormulaContext), Skipper> eventuallyFormula; qi::rule(storm::logic::FormulaContext), Skipper> nextFormula; qi::rule(storm::logic::FormulaContext), Skipper> globallyFormula; qi::rule(storm::logic::FormulaContext), Skipper> untilFormula; qi::rule, Skipper> timeBoundReference; qi::rule, boost::optional, std::shared_ptr>(), qi::locals, Skipper> timeBound; qi::rule, boost::optional, std::shared_ptr>>(), qi::locals, Skipper> timeBounds; qi::rule(), Skipper> rewardPathFormula; qi::rule(), qi::locals, Skipper> cumulativeRewardFormula; qi::rule(), Skipper> totalRewardFormula; qi::rule(), Skipper> instantaneousRewardFormula; qi::rule(), Skipper> longRunAverageRewardFormula; qi::rule(), Skipper> multiFormula; // Parser that is used to recognize doubles only (as opposed to Spirit's double_ parser). boost::spirit::qi::real_parser> strict_double; bool areConstantDefinitionsAllowed() const; void addConstant(std::string const& name, ConstantDataType type, boost::optional const& expression); void addProperty(std::vector& properties, boost::optional const& name, std::shared_ptr const& formula); std::shared_ptr createTimeBoundReference(storm::logic::TimeBoundType const& type, boost::optional const& rewardModelName) const; std::tuple, boost::optional, std::shared_ptr> createTimeBoundFromInterval(storm::expressions::Expression const& lowerBound, storm::expressions::Expression const& upperBound, std::shared_ptr const& timeBoundReference) const; std::tuple, boost::optional, std::shared_ptr> createTimeBoundFromSingleBound(storm::expressions::Expression const& bound, bool upperBound, bool strict, std::shared_ptr const& timeBoundReference) const; // Methods that actually create the expression objects. std::shared_ptr createInstantaneousRewardFormula(storm::expressions::Expression const& timeBound) const; std::shared_ptr createCumulativeRewardFormula(std::vector, boost::optional, std::shared_ptr>> const& timeBounds) const; std::shared_ptr createTotalRewardFormula() const; std::shared_ptr createLongRunAverageRewardFormula() const; std::shared_ptr createAtomicExpressionFormula(storm::expressions::Expression const& expression) const; std::shared_ptr createBooleanLiteralFormula(bool literal) const; std::shared_ptr createAtomicLabelFormula(std::string const& label) const; std::shared_ptr createEventuallyFormula(boost::optional, boost::optional, std::shared_ptr>>> const& timeBounds, storm::logic::FormulaContext context, std::shared_ptr const& subformula) const; std::shared_ptr createGloballyFormula(std::shared_ptr const& subformula) const; std::shared_ptr createNextFormula(std::shared_ptr const& subformula) const; std::shared_ptr createUntilFormula(std::shared_ptr const& leftSubformula, boost::optional, boost::optional, std::shared_ptr>>> const& timeBounds, std::shared_ptr const& rightSubformula); std::shared_ptr createConditionalFormula(std::shared_ptr const& leftSubformula, std::shared_ptr const& rightSubformula, storm::logic::FormulaContext context) const; storm::logic::OperatorInformation createOperatorInformation(boost::optional const& optimizationDirection, boost::optional const& comparisonType, boost::optional const& threshold) const; std::shared_ptr createLongRunAverageOperatorFormula(storm::logic::OperatorInformation const& operatorInformation, std::shared_ptr const& subformula) const; std::shared_ptr createRewardOperatorFormula(boost::optional const& rewardMeasureType, boost::optional const& rewardModelName, storm::logic::OperatorInformation const& operatorInformation, std::shared_ptr const& subformula) const; std::shared_ptr createTimeOperatorFormula(boost::optional const& rewardMeasureType, storm::logic::OperatorInformation const& operatorInformation, std::shared_ptr const& subformula) const; std::shared_ptr createProbabilityOperatorFormula(storm::logic::OperatorInformation const& operatorInformation, std::shared_ptr const& subformula); std::shared_ptr createBinaryBooleanStateFormula(std::shared_ptr const& leftSubformula, std::shared_ptr const& rightSubformula, storm::logic::BinaryBooleanStateFormula::OperatorType operatorType); std::shared_ptr createUnaryBooleanStateFormula(std::shared_ptr const& subformula, boost::optional const& operatorType); std::shared_ptr createMultiFormula(std::vector> const& subformulas); std::set getUndefinedConstants(std::shared_ptr const& formula) const; storm::jani::Property createProperty(boost::optional const& propertyName, storm::modelchecker::FilterType const& filterType, std::shared_ptr const& formula, std::shared_ptr const& states); storm::jani::Property createPropertyWithDefaultFilterTypeAndStates(boost::optional const& propertyName, std::shared_ptr const& formula); // An error handler function. phoenix::function handler; uint64_t propertyCount; std::set undefinedConstants; }; } }