#include "src/parser/FormulaParser.h" #include #include "src/parser/SpiritErrorHandler.h" // If the parser fails due to ill-formed data, this exception is thrown. #include "src/exceptions/WrongFormatException.h" namespace storm { namespace parser { class FormulaParserGrammar : public qi::grammar>(), Skipper> { public: FormulaParserGrammar(std::shared_ptr const& manager = std::shared_ptr(new storm::expressions::ExpressionManager())); 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: struct keywordsStruct : qi::symbols { keywordsStruct() { add ("true", 1) ("false", 2) ("min", 3) ("max", 4) ("F", 5) ("G", 6) ("X", 7); } }; // 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_; // 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; 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(), 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> 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, uint_fast64_t>(), Skipper> timeBound; qi::rule(), Skipper> rewardPathFormula; qi::rule(), Skipper> cumulativeRewardFormula; qi::rule(), Skipper> instantaneousRewardFormula; qi::rule(), Skipper> longRunAverageRewardFormula; // Parser that is used to recognize doubles only (as opposed to Spirit's double_ parser). boost::spirit::qi::real_parser> strict_double; // Methods that actually create the expression objects. std::shared_ptr createInstantaneousRewardFormula(boost::variant const& timeBound) const; std::shared_ptr createCumulativeRewardFormula(boost::variant const& timeBound) 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, uint_fast64_t>> const& timeBound, 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, uint_fast64_t>> const& timeBound, 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); // An error handler function. phoenix::function handler; }; FormulaParser::FormulaParser(std::shared_ptr const& manager) : manager(manager->getSharedPointer()), grammar(new FormulaParserGrammar(manager)) { // Intentionally left empty. } FormulaParser::FormulaParser(storm::prism::Program const& program) : manager(program.getManager().getSharedPointer()), grammar(new FormulaParserGrammar(manager)) { // Make the formulas of the program available to the parser. for (auto const& formula : program.getFormulas()) { this->addIdentifierExpression(formula.getName(), formula.getExpression()); } } FormulaParser::FormulaParser(FormulaParser const& other) : FormulaParser(other.manager) { other.identifiers_.for_each([=] (std::string const& name, storm::expressions::Expression const& expression) { this->addIdentifierExpression(name, expression); }); } FormulaParser& FormulaParser::operator=(FormulaParser const& other) { this->manager = other.manager; this->grammar = std::shared_ptr(new FormulaParserGrammar(this->manager)); other.identifiers_.for_each([=] (std::string const& name, storm::expressions::Expression const& expression) { this->addIdentifierExpression(name, expression); }); return *this; } std::shared_ptr FormulaParser::parseSingleFormulaFromString(std::string const& formulaString) const { std::vector> formulas = parseFromString(formulaString); STORM_LOG_THROW(formulas.size() == 1, storm::exceptions::WrongFormatException, "Expected exactly one formula, but found " << formulas.size() << " instead."); return formulas.front(); } std::vector> FormulaParser::parseFromFile(std::string const& filename) const { // Open file and initialize result. std::ifstream inputFileStream(filename, std::ios::in); STORM_LOG_THROW(inputFileStream.good(), storm::exceptions::WrongFormatException, "Unable to read from file '" << filename << "'."); std::vector> formulas; // Now try to parse the contents of the file. try { std::string fileContent((std::istreambuf_iterator(inputFileStream)), (std::istreambuf_iterator())); formulas = parseFromString(fileContent); } catch(std::exception& e) { // In case of an exception properly close the file before passing exception. inputFileStream.close(); throw e; } // Close the stream in case everything went smoothly and return result. inputFileStream.close(); return formulas; } std::vector> FormulaParser::parseFromString(std::string const& formulaString) const { PositionIteratorType first(formulaString.begin()); PositionIteratorType iter = first; PositionIteratorType last(formulaString.end()); // Create empty result; std::vector> result; // Create grammar. try { // Start parsing. bool succeeded = qi::phrase_parse(iter, last, *grammar, boost::spirit::ascii::space | qi::lit("//") >> *(qi::char_ - (qi::eol | qi::eoi)) >> (qi::eol | qi::eoi), result); STORM_LOG_THROW(succeeded, storm::exceptions::WrongFormatException, "Could not parse formula."); STORM_LOG_DEBUG("Parsed formula successfully."); } catch (qi::expectation_failure const& e) { STORM_LOG_THROW(false, storm::exceptions::WrongFormatException, e.what_); } return result; } void FormulaParser::addIdentifierExpression(std::string const& identifier, storm::expressions::Expression const& expression) { // Record the mapping and hand it over to the grammar. this->identifiers_.add(identifier, expression); grammar->addIdentifierExpression(identifier, expression); } FormulaParserGrammar::FormulaParserGrammar(std::shared_ptr const& manager) : FormulaParserGrammar::base_type(start), expressionParser(*manager, keywords_, true, true) { // Register all variables so we can parse them in the expressions. for (auto variableTypePair : *manager) { identifiers_.add(variableTypePair.first.getName(), variableTypePair.first); } // Set the identifier mapping to actually generate expressions. expressionParser.setIdentifierMapping(&identifiers_); longRunAverageRewardFormula = (qi::lit("LRA") | qi::lit("S"))[qi::_val = phoenix::bind(&FormulaParserGrammar::createLongRunAverageRewardFormula, phoenix::ref(*this))]; longRunAverageRewardFormula.name("long run average reward formula"); instantaneousRewardFormula = (qi::lit("I=") >> strict_double)[qi::_val = phoenix::bind(&FormulaParserGrammar::createInstantaneousRewardFormula, phoenix::ref(*this), qi::_1)] | (qi::lit("I=") > qi::uint_)[qi::_val = phoenix::bind(&FormulaParserGrammar::createInstantaneousRewardFormula, phoenix::ref(*this), qi::_1)]; instantaneousRewardFormula.name("instantaneous reward formula"); cumulativeRewardFormula = (qi::lit("C<=") >> strict_double)[qi::_val = phoenix::bind(&FormulaParserGrammar::createCumulativeRewardFormula, phoenix::ref(*this), qi::_1)] | (qi::lit("C<=") > qi::uint_)[qi::_val = phoenix::bind(&FormulaParserGrammar::createCumulativeRewardFormula, phoenix::ref(*this), qi::_1)]; cumulativeRewardFormula.name("cumulative reward formula"); rewardPathFormula = conditionalFormula(storm::logic::FormulaContext::Reward) | eventuallyFormula(storm::logic::FormulaContext::Reward) | cumulativeRewardFormula | instantaneousRewardFormula | longRunAverageRewardFormula; rewardPathFormula.name("reward path formula"); expressionFormula = expressionParser[qi::_val = phoenix::bind(&FormulaParserGrammar::createAtomicExpressionFormula, phoenix::ref(*this), qi::_1)]; expressionFormula.name("expression formula"); label = qi::as_string[qi::raw[qi::lexeme[((qi::alpha | qi::char_('_')) >> *(qi::alnum | qi::char_('_')))]]]; label.name("label"); labelFormula = (qi::lit("\"") >> label >> qi::lit("\""))[qi::_val = phoenix::bind(&FormulaParserGrammar::createAtomicLabelFormula, phoenix::ref(*this), qi::_1)]; labelFormula.name("label formula"); booleanLiteralFormula = (qi::lit("true")[qi::_a = true] | qi::lit("false")[qi::_a = false])[qi::_val = phoenix::bind(&FormulaParserGrammar::createBooleanLiteralFormula, phoenix::ref(*this), qi::_a)]; booleanLiteralFormula.name("boolean literal formula"); operatorFormula = probabilityOperator | rewardOperator | longRunAverageOperator; operatorFormula.name("operator formulas"); atomicStateFormula = booleanLiteralFormula | labelFormula | expressionFormula | (qi::lit("(") > stateFormula > qi::lit(")")) | operatorFormula; atomicStateFormula.name("atomic state formula"); notStateFormula = (-unaryBooleanOperator_ >> atomicStateFormula)[qi::_val = phoenix::bind(&FormulaParserGrammar::createUnaryBooleanStateFormula, phoenix::ref(*this), qi::_2, qi::_1)]; notStateFormula.name("negation formula"); eventuallyFormula = (qi::lit("F") >> -timeBound >> pathFormulaWithoutUntil(qi::_r1))[qi::_val = phoenix::bind(&FormulaParserGrammar::createEventuallyFormula, phoenix::ref(*this), qi::_1, qi::_r1, qi::_2)]; eventuallyFormula.name("eventually formula"); globallyFormula = (qi::lit("G") >> pathFormulaWithoutUntil(qi::_r1))[qi::_val = phoenix::bind(&FormulaParserGrammar::createGloballyFormula, phoenix::ref(*this), qi::_1)]; globallyFormula.name("globally formula"); nextFormula = (qi::lit("X") >> pathFormulaWithoutUntil(qi::_r1))[qi::_val = phoenix::bind(&FormulaParserGrammar::createNextFormula, phoenix::ref(*this), qi::_1)]; nextFormula.name("next formula"); pathFormulaWithoutUntil = eventuallyFormula(qi::_r1) | globallyFormula(qi::_r1) | nextFormula(qi::_r1) | stateFormula; pathFormulaWithoutUntil.name("path formula"); untilFormula = pathFormulaWithoutUntil(qi::_r1)[qi::_val = qi::_1] >> *(qi::lit("U") >> -timeBound >> pathFormulaWithoutUntil(qi::_r1))[qi::_val = phoenix::bind(&FormulaParserGrammar::createUntilFormula, phoenix::ref(*this), qi::_val, qi::_1, qi::_2)]; untilFormula.name("until formula"); conditionalFormula = untilFormula(qi::_r1)[qi::_val = qi::_1] >> *(qi::lit("||") >> untilFormula(storm::logic::FormulaContext::Probability))[qi::_val = phoenix::bind(&FormulaParserGrammar::createConditionalFormula, phoenix::ref(*this), qi::_val, qi::_1, qi::_r1)]; conditionalFormula.name("conditional formula"); timeBound = (qi::lit("[") > qi::double_ > qi::lit(",") > qi::double_ > qi::lit("]"))[qi::_val = phoenix::construct>(qi::_1, qi::_2)] | (qi::lit("<=") >> strict_double)[qi::_val = phoenix::construct>(0, qi::_1)] | (qi::lit("<=") > qi::uint_)[qi::_val = qi::_1]; timeBound.name("time bound"); pathFormula = conditionalFormula(qi::_r1); pathFormula.name("path formula"); rewardMeasureType = qi::lit("[") >> rewardMeasureType_ >> qi::lit("]"); rewardMeasureType.name("reward measure type"); operatorInformation = (-optimalityOperator_[qi::_a = qi::_1] >> ((relationalOperator_[qi::_b = qi::_1] > qi::double_[qi::_c = qi::_1]) | (qi::lit("=") > qi::lit("?"))))[qi::_val = phoenix::bind(&FormulaParserGrammar::createOperatorInformation, phoenix::ref(*this), qi::_a, qi::_b, qi::_c)]; operatorInformation.name("operator information"); longRunAverageOperator = ((qi::lit("LRA") | qi::lit("S")) > operatorInformation > qi::lit("[") > stateFormula > qi::lit("]"))[qi::_val = phoenix::bind(&FormulaParserGrammar::createLongRunAverageOperatorFormula, phoenix::ref(*this), qi::_1, qi::_2)]; longRunAverageOperator.name("long-run average operator"); rewardModelName = qi::lit("{\"") > label > qi::lit("\"}"); rewardModelName.name("reward model name"); rewardOperator = (qi::lit("R") > -rewardMeasureType > -rewardModelName > operatorInformation > qi::lit("[") > rewardPathFormula > qi::lit("]"))[qi::_val = phoenix::bind(&FormulaParserGrammar::createRewardOperatorFormula, phoenix::ref(*this), qi::_1, qi::_2, qi::_3, qi::_4)]; rewardOperator.name("reward operator"); timeOperator = (qi::lit("T") > -rewardMeasureType > operatorInformation > qi::lit("[") > eventuallyFormula(storm::logic::FormulaContext::Time) > qi::lit("]"))[qi::_val = phoenix::bind(&FormulaParserGrammar::createTimeOperatorFormula, phoenix::ref(*this), qi::_1, qi::_2, qi::_3)]; timeOperator.name("time operator"); probabilityOperator = (qi::lit("P") > operatorInformation > qi::lit("[") > pathFormula(storm::logic::FormulaContext::Probability) > qi::lit("]"))[qi::_val = phoenix::bind(&FormulaParserGrammar::createProbabilityOperatorFormula, phoenix::ref(*this), qi::_1, qi::_2)]; probabilityOperator.name("probability operator"); andStateFormula = notStateFormula[qi::_val = qi::_1] >> *(qi::lit("&") >> notStateFormula)[qi::_val = phoenix::bind(&FormulaParserGrammar::createBinaryBooleanStateFormula, phoenix::ref(*this), qi::_val, qi::_1, storm::logic::BinaryBooleanStateFormula::OperatorType::And)]; andStateFormula.name("and state formula"); orStateFormula = andStateFormula[qi::_val = qi::_1] >> *(qi::lit("|") >> andStateFormula)[qi::_val = phoenix::bind(&FormulaParserGrammar::createBinaryBooleanStateFormula, phoenix::ref(*this), qi::_val, qi::_1, storm::logic::BinaryBooleanStateFormula::OperatorType::Or)]; orStateFormula.name("or state formula"); stateFormula = (orStateFormula); stateFormula.name("state formula"); start = qi::eps > (stateFormula % +(qi::char_("\n;"))) >> qi::skip(boost::spirit::ascii::space | qi::lit("//") >> *(qi::char_ - (qi::eol | qi::eoi)))[qi::eps] >> qi::eoi; start.name("start"); /*! * Enable the following lines to print debug output for most the rules. debug(start); debug(stateFormula); debug(orStateFormula); debug(andStateFormula); debug(probabilityOperator); debug(rewardOperator); debug(longRunAverageOperator); debug(pathFormulaWithoutUntil); debug(pathFormula); // debug(conditionalFormula); debug(nextFormula); debug(globallyFormula); // debug(eventuallyFormula); debug(atomicStateFormula); debug(booleanLiteralFormula); debug(labelFormula); debug(expressionFormula); debug(rewardPathFormula); debug(cumulativeRewardFormula); debug(instantaneousRewardFormula); */ // Enable error reporting. qi::on_error(start, handler(qi::_1, qi::_2, qi::_3, qi::_4)); qi::on_error(stateFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4)); qi::on_error(orStateFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4)); qi::on_error(andStateFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4)); qi::on_error(probabilityOperator, handler(qi::_1, qi::_2, qi::_3, qi::_4)); qi::on_error(rewardOperator, handler(qi::_1, qi::_2, qi::_3, qi::_4)); qi::on_error(longRunAverageOperator, handler(qi::_1, qi::_2, qi::_3, qi::_4)); qi::on_error(operatorInformation, handler(qi::_1, qi::_2, qi::_3, qi::_4)); qi::on_error(pathFormulaWithoutUntil, handler(qi::_1, qi::_2, qi::_3, qi::_4)); qi::on_error(pathFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4)); qi::on_error(conditionalFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4)); qi::on_error(untilFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4)); qi::on_error(nextFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4)); qi::on_error(globallyFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4)); qi::on_error(eventuallyFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4)); qi::on_error(atomicStateFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4)); qi::on_error(booleanLiteralFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4)); qi::on_error(labelFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4)); qi::on_error(expressionFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4)); qi::on_error(rewardPathFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4)); qi::on_error(cumulativeRewardFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4)); qi::on_error(instantaneousRewardFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4)); } void FormulaParserGrammar::addIdentifierExpression(std::string const& identifier, storm::expressions::Expression const& expression) { this->identifiers_.add(identifier, expression); } std::shared_ptr FormulaParserGrammar::createInstantaneousRewardFormula(boost::variant const& timeBound) const { if (timeBound.which() == 0) { return std::shared_ptr(new storm::logic::InstantaneousRewardFormula(static_cast(boost::get(timeBound)))); } else { double timeBoundAsDouble = boost::get(timeBound); STORM_LOG_THROW(timeBoundAsDouble >= 0, storm::exceptions::WrongFormatException, "Cumulative reward property must have non-negative bound."); return std::shared_ptr(new storm::logic::InstantaneousRewardFormula(static_cast(timeBoundAsDouble))); } } std::shared_ptr FormulaParserGrammar::createCumulativeRewardFormula(boost::variant const& timeBound) const { if (timeBound.which() == 0) { return std::shared_ptr(new storm::logic::CumulativeRewardFormula(static_cast(boost::get(timeBound)))); } else { double timeBoundAsDouble = boost::get(timeBound); STORM_LOG_THROW(timeBoundAsDouble >= 0, storm::exceptions::WrongFormatException, "Cumulative reward property must have non-negative bound."); return std::shared_ptr(new storm::logic::CumulativeRewardFormula(static_cast(timeBoundAsDouble))); } } std::shared_ptr FormulaParserGrammar::createLongRunAverageRewardFormula() const { return std::shared_ptr(new storm::logic::LongRunAverageRewardFormula()); } std::shared_ptr FormulaParserGrammar::createAtomicExpressionFormula(storm::expressions::Expression const& expression) const { STORM_LOG_THROW(expression.hasBooleanType(), storm::exceptions::WrongFormatException, "Expected expression of boolean type."); return std::shared_ptr(new storm::logic::AtomicExpressionFormula(expression)); } std::shared_ptr FormulaParserGrammar::createBooleanLiteralFormula(bool literal) const { return std::shared_ptr(new storm::logic::BooleanLiteralFormula(literal)); } std::shared_ptr FormulaParserGrammar::createAtomicLabelFormula(std::string const& label) const { return std::shared_ptr(new storm::logic::AtomicLabelFormula(label)); } std::shared_ptr FormulaParserGrammar::createEventuallyFormula(boost::optional, uint_fast64_t>> const& timeBound, storm::logic::FormulaContext context, std::shared_ptr const& subformula) const { if (timeBound) { if (timeBound.get().which() == 0) { std::pair const& bounds = boost::get>(timeBound.get()); return std::shared_ptr(new storm::logic::BoundedUntilFormula(createBooleanLiteralFormula(true), subformula, bounds.first, bounds.second)); } else { return std::shared_ptr(new storm::logic::BoundedUntilFormula(createBooleanLiteralFormula(true), subformula, static_cast(boost::get(timeBound.get())))); } } else { return std::shared_ptr(new storm::logic::EventuallyFormula(subformula, context)); } } std::shared_ptr FormulaParserGrammar::createGloballyFormula(std::shared_ptr const& subformula) const { return std::shared_ptr(new storm::logic::GloballyFormula(subformula)); } std::shared_ptr FormulaParserGrammar::createNextFormula(std::shared_ptr const& subformula) const { return std::shared_ptr(new storm::logic::NextFormula(subformula)); } std::shared_ptr FormulaParserGrammar::createUntilFormula(std::shared_ptr const& leftSubformula, boost::optional, uint_fast64_t>> const& timeBound, std::shared_ptr const& rightSubformula) { if (timeBound) { if (timeBound.get().which() == 0) { std::pair const& bounds = boost::get>(timeBound.get()); return std::shared_ptr(new storm::logic::BoundedUntilFormula(leftSubformula, rightSubformula, bounds.first, bounds.second)); } else { return std::shared_ptr(new storm::logic::BoundedUntilFormula(leftSubformula, rightSubformula, static_cast(boost::get(timeBound.get())))); } } else { return std::shared_ptr(new storm::logic::UntilFormula(leftSubformula, rightSubformula)); } } std::shared_ptr FormulaParserGrammar::createConditionalFormula(std::shared_ptr const& leftSubformula, std::shared_ptr const& rightSubformula, storm::logic::FormulaContext context) const { return std::shared_ptr(new storm::logic::ConditionalFormula(leftSubformula, rightSubformula, context)); } storm::logic::OperatorInformation FormulaParserGrammar::createOperatorInformation(boost::optional const& optimizationDirection, boost::optional const& comparisonType, boost::optional const& threshold) const { if (comparisonType && threshold) { return storm::logic::OperatorInformation(optimizationDirection, storm::logic::Bound(comparisonType.get(), threshold.get())); } else { return storm::logic::OperatorInformation(optimizationDirection, boost::none); } } std::shared_ptr FormulaParserGrammar::createLongRunAverageOperatorFormula(storm::logic::OperatorInformation const& operatorInformation, std::shared_ptr const& subformula) const { return std::shared_ptr(new storm::logic::LongRunAverageOperatorFormula(subformula, operatorInformation)); } std::shared_ptr FormulaParserGrammar::createRewardOperatorFormula(boost::optional const& rewardMeasureType, boost::optional const& rewardModelName, storm::logic::OperatorInformation const& operatorInformation, std::shared_ptr const& subformula) const { storm::logic::RewardMeasureType measureType = storm::logic::RewardMeasureType::Expectation; if (rewardMeasureType) { measureType = rewardMeasureType.get(); } return std::shared_ptr(new storm::logic::RewardOperatorFormula(subformula, rewardModelName, operatorInformation, measureType)); } std::shared_ptr FormulaParserGrammar::createTimeOperatorFormula(boost::optional const& rewardMeasureType, storm::logic::OperatorInformation const& operatorInformation, std::shared_ptr const& subformula) const { storm::logic::RewardMeasureType measureType = storm::logic::RewardMeasureType::Expectation; if (rewardMeasureType) { measureType = rewardMeasureType.get(); } return std::shared_ptr(new storm::logic::TimeOperatorFormula(subformula, operatorInformation, measureType)); } std::shared_ptr FormulaParserGrammar::createProbabilityOperatorFormula(storm::logic::OperatorInformation const& operatorInformation, std::shared_ptr const& subformula) { return std::shared_ptr(new storm::logic::ProbabilityOperatorFormula(subformula, operatorInformation)); } std::shared_ptr FormulaParserGrammar::createBinaryBooleanStateFormula(std::shared_ptr const& leftSubformula, std::shared_ptr const& rightSubformula, storm::logic::BinaryBooleanStateFormula::OperatorType operatorType) { return std::shared_ptr(new storm::logic::BinaryBooleanStateFormula(operatorType, leftSubformula, rightSubformula)); } std::shared_ptr FormulaParserGrammar::createUnaryBooleanStateFormula(std::shared_ptr const& subformula, boost::optional const& operatorType) { if (operatorType) { return std::shared_ptr(new storm::logic::UnaryBooleanStateFormula(operatorType.get(), subformula)); } else { return subformula; } } } // namespace parser } // namespace storm