From 7610bc8e76d5927f02693d2bb01dca0fa216733d Mon Sep 17 00:00:00 2001
From: dehnert <dehnert@cs.rwth-aachen.de>
Date: Tue, 8 Apr 2014 20:52:15 +0200
Subject: [PATCH] Started reducing the complexity in the PRISM grammar.

Former-commit-id: c17dc6d27bf1ca822cbe7510825b2f5aa9c9e1a8
---
 src/parser/prismparser/PrismGrammar.cpp   | 285 +++++++---------------
 src/parser/prismparser/PrismGrammar.h     | 207 +++++-----------
 src/parser/prismparser/Tokens.h           |  79 ++++--
 src/storage/expressions/Expression.h      |   2 +-
 src/storage/expressions/Expressions.h     |  13 +
 src/storage/prism/Program.cpp             |   8 +-
 src/storage/prism/Program.h               |  17 +-
 src/storage/prism/Update.cpp              |  63 ++---
 src/storage/prism/Update.h                |  48 +---
 test/functional/parser/ParsePrismTest.cpp |  32 ---
 10 files changed, 269 insertions(+), 485 deletions(-)
 create mode 100644 src/storage/expressions/Expressions.h
 delete mode 100644 test/functional/parser/ParsePrismTest.cpp

diff --git a/src/parser/prismparser/PrismGrammar.cpp b/src/parser/prismparser/PrismGrammar.cpp
index b6de4f0f4..7c81b31ce 100644
--- a/src/parser/prismparser/PrismGrammar.cpp
+++ b/src/parser/prismparser/PrismGrammar.cpp
@@ -1,152 +1,96 @@
-/*
- * PrismGrammar.cpp
- *
- *  Created on: 11.01.2013
- *      Author: chris
- */
-
-// Needed for file IO.
-#include <fstream>
-#include <iomanip>
-#include <limits>
-
-#include "PrismGrammar.h"
-
-#include "src/utility/OsDetection.h"
-
-#include "src/parser/prismparser/Includes.h"
-#include "src/parser/prismparser/BooleanExpressionGrammar.h"
-#include "src/parser/prismparser/ConstBooleanExpressionGrammar.h"
-#include "src/parser/prismparser/ConstDoubleExpressionGrammar.h"
-#include "src/parser/prismparser/ConstIntegerExpressionGrammar.h"
-#include "src/parser/prismparser/IntegerExpressionGrammar.h"
-#include "src/parser/prismparser/IdentifierGrammars.h"
-#include "src/parser/prismparser/VariableState.h"
+#include "src/parser/prismparser/PrismGrammar.h"
 #include "src/exceptions/InvalidArgumentException.h"
 
-#include "log4cplus/logger.h"
-#include "log4cplus/loggingmacros.h"
-extern log4cplus::Logger logger;
-
-// Some typedefs and namespace definitions to reduce code size.
-typedef std::string::const_iterator BaseIteratorType;
-typedef boost::spirit::classic::position_iterator2<BaseIteratorType> PositionIteratorType;
-namespace qi = boost::spirit::qi;
-namespace phoenix = boost::phoenix;
-
 namespace storm {
     namespace parser {
         namespace prism {
-            
-            void PrismGrammar::addLabel(std::string const& name, std::shared_ptr<BaseExpression> const& value, std::map<std::string, std::unique_ptr<BaseExpression>>& nameToExpressionMap) {
-                this->state->labelNames_.add(name, name);
-                nameToExpressionMap[name] = value->clone();
-            }
-            
-            void PrismGrammar::addIntegerAssignment(std::string const& variable, std::shared_ptr<BaseExpression> const& value, std::map<std::string, Assignment>& variableToAssignmentMap) {
-                this->state->assignedIntegerVariables_.add(variable, variable);
-                variableToAssignmentMap[variable] = Assignment(variable, value->clone());
-            }
-            
-            void PrismGrammar::addBooleanAssignment(std::string const& variable, std::shared_ptr<BaseExpression> const& value, std::map<std::string, Assignment>& variableToAssigmentMap) {
-                this->state->assignedBooleanVariables_.add(variable, variable);
-                variableToAssigmentMap[variable] = Assignment(variable, value->clone());
-            }
-            
-            void PrismGrammar::addUndefinedBooleanConstant(std::string const& name, std::map<std::string, std::unique_ptr<BooleanConstantExpression>>& nameToExpressionMap) {
-                this->state->booleanConstants_.add(name, std::shared_ptr<BaseExpression>(new BooleanConstantExpression(name)));
-                this->state->allConstantNames_.add(name, name);
-                nameToExpressionMap.emplace(name, std::unique_ptr<BooleanConstantExpression>(new BooleanConstantExpression(dynamic_cast<BooleanConstantExpression&>(*this->state->booleanConstants_.at(name)))));
-            }
-            
-            void PrismGrammar::addUndefinedIntegerConstant(std::string const& name, std::map<std::string, std::unique_ptr<IntegerConstantExpression>>& nameToExpressionMap) {
-                this->state->integerConstants_.add(name, std::shared_ptr<BaseExpression>(new IntegerConstantExpression(name)));
-                this->state->allConstantNames_.add(name, name);
-                nameToExpressionMap.emplace(name, std::unique_ptr<IntegerConstantExpression>(new IntegerConstantExpression(dynamic_cast<IntegerConstantExpression&>(*this->state->integerConstants_.at(name)))));
-            }
-            
-            void PrismGrammar::addUndefinedDoubleConstant(std::string const& name, std::map<std::string, std::unique_ptr<DoubleConstantExpression>>& nameToExpressionMap) {
-                this->state->doubleConstants_.add(name, std::shared_ptr<BaseExpression>(new DoubleConstantExpression(name)));
-                this->state->allConstantNames_.add(name, name);
-                nameToExpressionMap.emplace(name, std::unique_ptr<DoubleConstantExpression>(new DoubleConstantExpression(dynamic_cast<DoubleConstantExpression&>(*this->state->doubleConstants_.at(name)))));
-            }
-            
-            Module PrismGrammar::renameModule(std::string const& newName, std::string const& oldName, std::map<std::string, std::string> const& renaming) {
-                this->state->moduleNames_.add(newName, newName);
-                Module* old = this->moduleMap_.find(oldName);
-                if (old == nullptr) {
-                    LOG4CPLUS_ERROR(logger, "Renaming module failed: module " << oldName << " does not exist.");
-                    throw storm::exceptions::InvalidArgumentException() << "Renaming module failed: module " << oldName << " does not exist.";
-                }
-                Module res(*old, newName, renaming, *this->state);
-                this->moduleMap_.at(newName) = res;
-                return res;
-            }
-            
-            Module PrismGrammar::createModule(std::string const& name, std::vector<BooleanVariable> const& bools, std::vector<IntegerVariable> const& ints, std::map<std::string, uint_fast64_t> const& boolids, std::map<std::string, uint_fast64_t> const& intids, std::vector<storm::ir::Command> const& commands) {
-                this->state->moduleNames_.add(name, name);
-                Module res(name, bools, ints, boolids, intids, commands);
-                this->moduleMap_.at(name) = res;
-                return res;
-            }
-            
-            void PrismGrammar::createIntegerVariable(std::string const& name, std::shared_ptr<BaseExpression> const& lower, std::shared_ptr<BaseExpression> const& upper, std::shared_ptr<BaseExpression> const& init, std::vector<IntegerVariable>& vars, std::map<std::string, uint_fast64_t>& varids, bool isGlobalVariable) {
-                uint_fast64_t id = this->state->addIntegerVariable(name);
-                uint_fast64_t newLocalIndex = this->state->nextLocalIntegerVariableIndex;
-                vars.emplace_back(newLocalIndex, id, name, lower != nullptr ? lower->clone() : nullptr, upper != nullptr ? upper->clone() : nullptr, init != nullptr ? init->clone() : nullptr);
-                varids[name] = newLocalIndex;
-                ++this->state->nextLocalIntegerVariableIndex;
-                this->state->localIntegerVariables_.add(name, name);
-                if (isGlobalVariable) {
-                    this->state->globalIntegerVariables_.add(name, name);
-                }
-            }
-            
-            void PrismGrammar::createBooleanVariable(std::string const& name, std::shared_ptr<BaseExpression> const& init, std::vector<BooleanVariable>& vars, std::map<std::string, uint_fast64_t>& varids, bool isGlobalVariable) {
-                uint_fast64_t id = this->state->addBooleanVariable(name);
-                uint_fast64_t newLocalIndex = this->state->nextLocalBooleanVariableIndex;
-                vars.emplace_back(newLocalIndex, id, name, init != nullptr ? init->clone() : nullptr);
-                varids[name] = newLocalIndex;
-                ++this->state->nextLocalBooleanVariableIndex;
-                this->state->localBooleanVariables_.add(name, name);
-                if (isGlobalVariable) {
-                    this->state->globalBooleanVariables_.add(name, name);
-                }
-            }
-            
-            StateReward createStateReward(std::shared_ptr<BaseExpression> const& guard, std::shared_ptr<BaseExpression> const& reward) {
-                return StateReward(guard->clone(), reward->clone());
-            }
-            TransitionReward createTransitionReward(std::string const& label, std::shared_ptr<BaseExpression> const& guard, std::shared_ptr<BaseExpression> const& reward) {
-                return TransitionReward(label, guard->clone(), reward->clone());
-            }
-            void createRewardModel(std::string const& name, std::vector<StateReward>& stateRewards, std::vector<TransitionReward>& transitionRewards, std::map<std::string, RewardModel>& mapping) {
-                mapping[name] = RewardModel(name, stateRewards, transitionRewards);
-            }
-            Update PrismGrammar::createUpdate(std::shared_ptr<BaseExpression> const& likelihood, std::map<std::string, Assignment> const& bools, std::map<std::string, Assignment> const& ints) {
-                this->state->nextGlobalUpdateIndex++;
-                return Update(this->state->getNextGlobalUpdateIndex() - 1, likelihood != nullptr ? likelihood->clone() : nullptr, bools, ints);
-            }
-            Command PrismGrammar::createCommand(std::string const& label, std::shared_ptr<BaseExpression> const& guard, std::vector<Update> const& updates) {
-                this->state->nextGlobalCommandIndex++;
-                return Command(this->state->getNextGlobalCommandIndex() - 1, label, guard->clone(), updates);
-            }
-            Program createProgram(
-                                  Program::ModelType modelType,
-                                  std::map<std::string, std::unique_ptr<BooleanConstantExpression>> const& undefBoolConst,
-                                  std::map<std::string, std::unique_ptr<IntegerConstantExpression>> const& undefIntConst,
-                                  std::map<std::string, std::unique_ptr<DoubleConstantExpression>> const& undefDoubleConst,
-                                  GlobalVariableInformation const& globalVariableInformation,
-                                  std::vector<Module> const& modules,
-                                  std::map<std::string, RewardModel> const& rewards,
-                                  std::map<std::string, std::unique_ptr<BaseExpression>> const& labels) {
-                return Program(modelType, undefBoolConst, undefIntConst, undefDoubleConst,
-                               globalVariableInformation.booleanVariables, globalVariableInformation.integerVariables,
-                               globalVariableInformation.booleanVariableToIndexMap,
-                               globalVariableInformation.integerVariableToIndexMap, modules, rewards, labels);
-            }
-            
-            PrismGrammar::PrismGrammar() : PrismGrammar::base_type(start), state(new VariableState()) {
+            PrismGrammar::PrismGrammar() : PrismGrammar::base_type(start) {
+                // Parse simple identifier.
+                identifier %= qi::as_string[qi::raw[qi::lexeme[((qi::alpha | qi::char_('_')) >> *(qi::alnum | qi::char_('_')))]]] - keywords_;
+                identifier.name("identifier");
+                
+                // Parse a composed expression.
+                expression %= (booleanExpression | numericalExpression);
+                expression.name("expression");
+                
+                booleanExpression %= orExpression;
+                expression.name("boolean expression");
+                
+                orExpression = andExpression[qi::_val = qi::_1] >> *(qi::lit("|") >> andExpression)[qi::_val = qi::_val * qi::_1];
+                orExpression.name("boolean expression");
+                
+                andExpression = notExpression[qi::_val = qi::_1] >> *(qi::lit("&") >> notExpression)[qi::_val = qi::_val * qi::_1];
+                andExpression.name("boolean expression");
+                
+                notExpression = atomicBooleanExpression[qi::_val = qi::_1] | (qi::lit("!") >> atomicBooleanExpression)[qi::_val = !qi::_1];
+                notExpression.name("boolean expression");
+                
+                atomicBooleanExpression %= relativeExpression | booleanVariableExpression | qi::lit("(") >> booleanExpression >> qi::lit(")");
+                atomicBooleanExpression.name("boolean expression");
+                
+                relativeExpression = ((numericalExpression >> ">") > numericalExpression)[qi::_val = qi::_1 > qi::_2] | ((numericalExpression >> ">=") > numericalExpression)[qi::_val = qi::_1 >= qi::_2] | ((numericalExpression >> "<") > numericalExpression)[qi::_val = qi::_1 < qi::_2] | ((numericalExpression >> "<=") > numericalExpression)[qi::_val = qi::_1 <= qi::_2];
+                relativeExpression.name("relative expression");
+                
+                booleanVariableExpression = identifier[qi::_val = phoenix::bind(&storm::expressions::Expression::createBooleanVariable, qi::_1)];
+                booleanVariableExpression.name("boolean variable");
+                
+                numericalExpression %= plusExpression;
+                numericalExpression.name("numerical expression");
+                
+                plusExpression = multiplicationExpression[qi::_val = qi::_1] >> *((qi::lit("+")[qi::_a = true] | qi::lit("-")[qi::_a = false]) >> multiplicationExpression)[phoenix::if_(qi::_a) [qi::_val = qi::_val + qi::_1] .else_ [qi::_val = qi::_val - qi::_1]];
+                plusExpression.name("numerical expression");
+                
+                multiplicationExpression = atomicNumericalExpression[qi::_val = qi::_1] >> *(qi::lit("*") >> atomicNumericalExpression[qi::_val = qi::_val * qi::_1]);
+                multiplicationExpression.name("numerical expression");
+                
+                atomicNumericalExpression %= minMaxExpression | floorCeilExpression | numericalVariableExpression | qi::lit("(") >> numericalExpression >> qi::lit(")");
+                atomicNumericalExpression.name("numerical expression");
+                
+                minMaxExpression %= ((qi::lit("min")[qi::_a = true] | qi::lit("max")[qi::_a = false]) >> qi::lit("(") >> numericalExpression >> qi::lit(",") >> numericalExpression >> qi::lit(")"))[phoenix::if_(qi::_a) [qi::_val = phoenix::bind(&storm::expressions::Expression::minimum, qi::_1, qi::_2)] .else_ [qi::_val = phoenix::bind(&storm::expressions::Expression::maximum, qi::_1, qi::_2)]];
+                minMaxExpression.name("min/max expression");
+                
+                floorCeilExpression %= ((qi::lit("floor")[qi::_a = true] | qi::lit("ceil")[qi::_a = false]) >> qi::lit("(") >> numericalExpression >> qi::lit(")"))[phoenix::if_(qi::_a) [qi::_val = phoenix::bind(&storm::expressions::Expression::floor, qi::_1)] .else_ [qi::_val = phoenix::bind(&storm::expressions::Expression::ceil, qi::_1)]];
+                floorCeilExpression.name("integer floor/ceil expression");
+
+                numericalVariableExpression = identifier[qi::_val = phoenix::bind(&storm::expressions::Expression::createDoubleVariable, qi::_1)];
+                numericalVariableExpression.name("numerical variable");
+                
+                // Parse a model type.
+                modelTypeDefinition = modelType_;
+                modelTypeDefinition.name("model type");
+                
+                // This block defines all entities that are needed for parsing constant definitions.
+                definedBooleanConstantDefinition = (qi::lit("const") >> qi::lit("bool") >> identifier >> qi::lit("=") > expression > qi::lit(";"))[phoenix::bind(this->state->booleanConstants_.add, qi::_1, qi::_2), phoenix::bind(this->state->allConstantNames_.add, qi::_1, qi::_1), qi::_val = qi::_2];
+                definedBooleanConstantDefinition.name("defined boolean constant declaration");
+                
+                definedIntegerConstantDefinition = (qi::lit("const") >> qi::lit("int") >> FreeIdentifierGrammar::instance(this->state) >> qi::lit("=") >> ConstIntegerExpressionGrammar::instance(this->state) >> qi::lit(";"))[phoenix::bind(this->state->integerConstants_.add, qi::_1, qi::_2), phoenix::bind(this->state->allConstantNames_.add, qi::_1, qi::_1), qi::_val = qi::_2];
+                definedIntegerConstantDefinition.name("defined integer constant declaration");
+                definedDoubleConstantDefinition = (qi::lit("const") >> qi::lit("double") >> FreeIdentifierGrammar::instance(this->state) >> qi::lit("=") > ConstDoubleExpressionGrammar::instance(this->state) > qi::lit(";"))[phoenix::bind(this->state->doubleConstants_.add, qi::_1, qi::_2), phoenix::bind(this->state->allConstantNames_.add, qi::_1, qi::_1), qi::_val = qi::_2];
+                definedDoubleConstantDefinition.name("defined double constant declaration");
+                undefinedBooleanConstantDefinition = (qi::lit("const") >> qi::lit("bool") > FreeIdentifierGrammar::instance(this->state) > qi::lit(";"))[phoenix::bind(&PrismGrammar::addUndefinedBooleanConstant, this, qi::_1, qi::_r1)];
+                undefinedBooleanConstantDefinition.name("undefined boolean constant declaration");
+                undefinedIntegerConstantDefinition = (qi::lit("const") >> qi::lit("int") > FreeIdentifierGrammar::instance(this->state) > qi::lit(";"))[phoenix::bind(&PrismGrammar::addUndefinedIntegerConstant, this, qi::_1, qi::_r1)];
+                undefinedIntegerConstantDefinition.name("undefined integer constant declaration");
+                undefinedDoubleConstantDefinition = (qi::lit("const") >> qi::lit("double") > FreeIdentifierGrammar::instance(this->state) > qi::lit(";"))[phoenix::bind(&PrismGrammar::addUndefinedDoubleConstant, this, qi::_1, qi::_r1)];
+                undefinedDoubleConstantDefinition.name("undefined double constant definition");
+                definedConstantDefinition %= (definedBooleanConstantDefinition(qi::_r1) | definedIntegerConstantDefinition(qi::_r2) | definedDoubleConstantDefinition(qi::_r3));
+                definedConstantDefinition.name("defined constant definition");
+                undefinedConstantDefinition = (undefinedBooleanConstantDefinition(qi::_r1) | undefinedIntegerConstantDefinition(qi::_r2) | undefinedDoubleConstantDefinition(qi::_r3));
+                undefinedConstantDefinition.name("undefined constant definition");
+                constantDefinitionList = *(undefinedConstantDefinition(qi::_r1, qi::_r2, qi::_r3) | definedConstantDefinition(qi::_r4, qi::_r5, qi::_r6));
+                constantDefinitionList.name("constant definition list");
+                
+                // Parse the ingredients of a probabilistic program.
+                start = (qi::eps >
+                         modelTypeDefinition >
+                         constantDefinitionList(qi::_a, qi::_b, qi::_c, qi::_d, qi::_e, qi::_f) >
+                         formulaDefinitionList >
+                         globalVariableDefinitionList(qi::_d) >
+                         moduleDefinitionList >
+                         rewardDefinitionList(qi::_e) >
+                         labelDefinitionList(qi::_f))[qi::_val = phoenix::bind(&createProgram, qi::_1, qi::_a, qi::_b, qi::_c, qi::_d, qi::_2, qi::_e, qi::_f)];
+                start.name("probabilistic program declaration");
+
                 
                 labelDefinition = (qi::lit("label") >> -qi::lit("\"") >> FreeIdentifierGrammar::instance(this->state) >> -qi::lit("\"") >> qi::lit("=") >> BooleanExpressionGrammar::instance(this->state) >> qi::lit(";"))
                 [phoenix::bind(&PrismGrammar::addLabel, this, qi::_1, qi::_2, qi::_r1)];
@@ -222,26 +166,6 @@ namespace storm {
                 globalVariableDefinitionList = *(qi::lit("global") > (booleanVariableDefinition(bind(&GlobalVariableInformation::booleanVariables, qi::_r1), bind(&GlobalVariableInformation::booleanVariableToIndexMap, qi::_r1), true) | integerVariableDefinition(bind(&GlobalVariableInformation::integerVariables, qi::_r1), bind(&GlobalVariableInformation::integerVariableToIndexMap, qi::_r1), true)));
                 globalVariableDefinitionList.name("global variable declaration list");
                 
-                // This block defines all entities that are needed for parsing constant definitions.
-                definedBooleanConstantDefinition = (qi::lit("const") >> qi::lit("bool") >> FreeIdentifierGrammar::instance(this->state) >> qi::lit("=") > ConstBooleanExpressionGrammar::instance(this->state) > qi::lit(";"))[phoenix::bind(this->state->booleanConstants_.add, qi::_1, qi::_2), phoenix::bind(this->state->allConstantNames_.add, qi::_1, qi::_1), qi::_val = qi::_2];
-                definedBooleanConstantDefinition.name("defined boolean constant declaration");
-                definedIntegerConstantDefinition = (qi::lit("const") >> qi::lit("int") >> FreeIdentifierGrammar::instance(this->state) >> qi::lit("=") >> ConstIntegerExpressionGrammar::instance(this->state) >> qi::lit(";"))[phoenix::bind(this->state->integerConstants_.add, qi::_1, qi::_2), phoenix::bind(this->state->allConstantNames_.add, qi::_1, qi::_1), qi::_val = qi::_2];
-                definedIntegerConstantDefinition.name("defined integer constant declaration");
-                definedDoubleConstantDefinition = (qi::lit("const") >> qi::lit("double") >> FreeIdentifierGrammar::instance(this->state) >> qi::lit("=") > ConstDoubleExpressionGrammar::instance(this->state) > qi::lit(";"))[phoenix::bind(this->state->doubleConstants_.add, qi::_1, qi::_2), phoenix::bind(this->state->allConstantNames_.add, qi::_1, qi::_1), qi::_val = qi::_2];
-                definedDoubleConstantDefinition.name("defined double constant declaration");
-                undefinedBooleanConstantDefinition = (qi::lit("const") >> qi::lit("bool") > FreeIdentifierGrammar::instance(this->state) > qi::lit(";"))[phoenix::bind(&PrismGrammar::addUndefinedBooleanConstant, this, qi::_1, qi::_r1)];
-                undefinedBooleanConstantDefinition.name("undefined boolean constant declaration");
-                undefinedIntegerConstantDefinition = (qi::lit("const") >> qi::lit("int") > FreeIdentifierGrammar::instance(this->state) > qi::lit(";"))[phoenix::bind(&PrismGrammar::addUndefinedIntegerConstant, this, qi::_1, qi::_r1)]; 
-                undefinedIntegerConstantDefinition.name("undefined integer constant declaration");
-                undefinedDoubleConstantDefinition = (qi::lit("const") >> qi::lit("double") > FreeIdentifierGrammar::instance(this->state) > qi::lit(";"))[phoenix::bind(&PrismGrammar::addUndefinedDoubleConstant, this, qi::_1, qi::_r1)];
-                undefinedDoubleConstantDefinition.name("undefined double constant declaration");
-                definedConstantDefinition %= (definedBooleanConstantDefinition | definedIntegerConstantDefinition | definedDoubleConstantDefinition);
-                definedConstantDefinition.name("defined constant declaration");
-                undefinedConstantDefinition = (undefinedBooleanConstantDefinition(qi::_r1) | undefinedIntegerConstantDefinition(qi::_r2) | undefinedDoubleConstantDefinition(qi::_r3));
-                undefinedConstantDefinition.name("undefined constant declaration");
-                constantDefinitionList = *(definedConstantDefinition | undefinedConstantDefinition(qi::_r1, qi::_r2, qi::_r3));
-                constantDefinitionList.name("constant declaration list");
-                
                 constantBooleanFormulaDefinition = (qi::lit("formula") >> FreeIdentifierGrammar::instance(this->state) >> qi::lit("=") >> ConstBooleanExpressionGrammar::instance(this->state) >> qi::lit(";"))[phoenix::bind(this->state->constantBooleanFormulas_.add, qi::_1, qi::_2)];
                 constantBooleanFormulaDefinition.name("constant boolean formula definition");
                 booleanFormulaDefinition = (qi::lit("formula") >> FreeIdentifierGrammar::instance(this->state) >> qi::lit("=") >> BooleanExpressionGrammar::instance(this->state) >> qi::lit(";"))[phoenix::bind(this->state->booleanFormulas_.add, qi::_1, qi::_2)];
@@ -256,40 +180,7 @@ namespace storm {
                 formulaDefinition.name("formula definition");
                 formulaDefinitionList = *formulaDefinition;
                 formulaDefinitionList.name("formula definition list");
-
-                // This block defines all entities that are needed for parsing a program.
-                modelTypeDefinition = modelType_;
-                modelTypeDefinition.name("model type");
-                start = (qi::eps >
-                         modelTypeDefinition >
-                         constantDefinitionList(qi::_a, qi::_b, qi::_c) >
-                         formulaDefinitionList >
-                         globalVariableDefinitionList(qi::_d) >
-                         moduleDefinitionList >
-                         rewardDefinitionList(qi::_e) >
-                         labelDefinitionList(qi::_f))[qi::_val = phoenix::bind(&createProgram, qi::_1, qi::_a, qi::_b, qi::_c, qi::_d, qi::_2, qi::_e, qi::_f)];
-                start.name("probabilistic program declaration");
-            }
-            
-            void PrismGrammar::prepareForSecondRun() {
-                LOG4CPLUS_INFO(logger, "Preparing parser for second run.");
-                this->state->prepareForSecondRun();
-                BooleanExpressionGrammar::secondRun();
-                ConstBooleanExpressionGrammar::secondRun();
-                ConstDoubleExpressionGrammar::secondRun();
-                ConstIntegerExpressionGrammar::secondRun();
-                IntegerExpressionGrammar::secondRun();
-            }
-            
-            void PrismGrammar::resetGrammars() {
-                LOG4CPLUS_INFO(logger, "Resetting grammars.");
-                BooleanExpressionGrammar::resetInstance();
-                ConstBooleanExpressionGrammar::resetInstance();
-                ConstDoubleExpressionGrammar::resetInstance();
-                ConstIntegerExpressionGrammar::resetInstance();
-                IntegerExpressionGrammar::resetInstance();
             }
-            
         } // namespace prism
     } // namespace parser
 } // namespace storm
diff --git a/src/parser/prismparser/PrismGrammar.h b/src/parser/prismparser/PrismGrammar.h
index c73420057..77a5406fc 100644
--- a/src/parser/prismparser/PrismGrammar.h
+++ b/src/parser/prismparser/PrismGrammar.h
@@ -34,7 +34,7 @@ using namespace storm::expressions;
 namespace storm {
     namespace parser {
         namespace prism {
-            class PrismGrammar : public qi::grammar<Iterator, Program(), Skipper> {
+            class PrismGrammar : public qi::grammar<Iterator, Program(), qi::locals<std::set<std::string>, std::set<std::string>, std::set<std::string>, std::map<std::string, storm::expressions::Expression>, std::map<std::string, storm::expressions::Expression>, std::map<std::string, storm::expressions::Expression>, std::map<std::string, Module>>, Skipper> {
             public:
                 /*!
                  * Default constructor that creates an empty and functional grammar.
@@ -43,182 +43,89 @@ namespace storm {
                 
             private:
                 // The starting point of the grammar.
-                qi::rule<Iterator, Program(), Skipper> start;
+                // The locals are used for: (a) undefined boolean constants, (b) undefined integer constants, (c) undefined double constants, (d) defined boolean constants, (e) defined integer constants, (f) defined double constants, (g) module name to module map
+                qi::rule<Iterator, Program(), qi::locals<std::set<std::string>, std::set<std::string>, std::set<std::string>, std::map<std::string, storm::expressions::Expression>, std::map<std::string, storm::expressions::Expression>, std::map<std::string, storm::expressions::Expression>, std::map<std::string, Module>>, Skipper> start;
                 
                 // Rules for model type.
                 qi::rule<Iterator, Program::ModelType(), Skipper> modelTypeDefinition;
                 
-                // Rules for global constant definitions.
-                qi::rule<Iterator, qi::unused_type(std::set<std::string>&, std::set<std::string>&, std::set<std::string>&, std::map<std::string, storm::expression::Expression>&, std::map<std::string, storm::expression::Expression>&, std::map<std::string, storm::expression::Expression>&), Skipper> constantDefinitionList;
-                
-                // Rules for global variable definitions
+                // Rules for constant definitions.
+                qi::rule<Iterator, qi::unused_type(std::set<std::string>&, std::set<std::string>&, std::set<std::string>&, std::map<std::string, storm::expressions::Expression>&, std::map<std::string, storm::expressions::Expression>&, std::map<std::string, storm::expressions::Expression>&), Skipper> constantDefinitionList;
+                qi::rule<Iterator, qi::unused_type(std::set<std::string>&, std::set<std::string>&, std::set<std::string>&), Skipper> undefinedConstantDefinition;
+                qi::rule<Iterator, qi::unused_type(std::map<std::string, storm::expressions::Expression>&, std::map<std::string, storm::expressions::Expression>&, std::map<std::string, storm::expressions::Expression>&), Skipper> definedConstantDefinition;
+                qi::rule<Iterator, qi::unused_type(std::set<std::string>&), Skipper> undefinedBooleanConstantDefinition;
+                qi::rule<Iterator, qi::unused_type(std::set<std::string>&), Skipper> undefinedIntegerConstantDefinition;
+                qi::rule<Iterator, qi::unused_type(std::set<std::string>&), Skipper> undefinedDoubleConstantDefinition;
+                qi::rule<Iterator, qi::unused_type(std::map<std::string, storm::expressions::Expression>&), Skipper> definedBooleanConstantDefinition;
+                qi::rule<Iterator, qi::unused_type(std::map<std::string, storm::expressions::Expression>&), Skipper> definedIntegerConstantDefinition;
+                qi::rule<Iterator, qi::unused_type(std::map<std::string, storm::expressions::Expression>&), Skipper> definedDoubleConstantDefinition;
+                
+                // Rules for global variable definitions.
                 qi::rule<Iterator, qi::unused_type(std::map<std::string, BooleanVariable>&, std::map<std::string, IntegerVariable>), Skipper> globalVariableDefinitionList;
                 
                 // Rules for modules definition.
                 qi::rule<Iterator, std::vector<Module>(), Skipper> moduleDefinitionList;
-                qi::rule<Iterator, Module(), qi::locals<std::vector<BooleanVariable>, std::vector<IntegerVariable>, std::map<std::string, uint_fast64_t>, std::map<std::string, uint_fast64_t>>, Skipper> moduleDefinition;
-                qi::rule<Iterator, Module(), qi::locals<std::map<std::string, std::string>>, Skipper> moduleRenaming;
+                qi::rule<Iterator, Module(), qi::locals<std::map<std::string, BooleanVariable>, std::map<std::string, IntegerVariable>>, Skipper> moduleDefinition;
+                qi::rule<Iterator, Module(std::map<std::string, Module>&), qi::locals<std::map<std::string, std::string>>, Skipper> moduleRenaming;
                 
                 // Rules for variable definitions.
-                qi::rule<Iterator, qi::unused_type(std::vector<BooleanVariable>&, std::vector<IntegerVariable>&, std::map<std::string, uint_fast64_t>&, std::map<std::string, uint_fast64_t>&), Skipper> variableDefinition;
-                qi::rule<Iterator, qi::unused_type(std::vector<BooleanVariable>&, std::map<std::string, uint_fast64_t>&, bool), qi::locals<uint_fast64_t, std::shared_ptr<BaseExpression>>, Skipper> booleanVariableDefinition;
-                qi::rule<Iterator, qi::unused_type(std::vector<IntegerVariable>&, std::map<std::string, uint_fast64_t>&, bool), qi::locals<uint_fast64_t, std::shared_ptr<BaseExpression>>, Skipper> integerVariableDefinition;
+                qi::rule<Iterator, qi::unused_type(std::map<std::string, BooleanVariable>&, std::map<std::string, IntegerVariable>&), Skipper> variableDefinition;
+                qi::rule<Iterator, qi::unused_type(std::map<std::string, BooleanVariable>&), Skipper> booleanVariableDefinition;
+                qi::rule<Iterator, qi::unused_type(std::map<std::string, IntegerVariable>&), Skipper> integerVariableDefinition;
                 
                 // Rules for command definitions.
                 qi::rule<Iterator, Command(), qi::locals<std::string>, Skipper> commandDefinition;
                 qi::rule<Iterator, std::vector<Update>(), Skipper> updateListDefinition;
-                qi::rule<Iterator, Update(), qi::locals<std::map<std::string, Assignment>, std::map<std::string, Assignment>>, Skipper> updateDefinition;
-                qi::rule<Iterator, qi::unused_type(std::map<std::string, Assignment>&, std::map<std::string, Assignment>&), Skipper> assignmentDefinitionList;
-                qi::rule<Iterator, qi::unused_type(std::map<std::string, Assignment>&, std::map<std::string, Assignment>&), Skipper> assignmentDefinition;
-                
-                // Rules for variable/command names.
-                qi::rule<Iterator, std::string(), Skipper> commandName;
-                qi::rule<Iterator, std::string(), Skipper> unassignedLocalBooleanVariableName;
-                qi::rule<Iterator, std::string(), Skipper> unassignedLocalIntegerVariableName;
+                qi::rule<Iterator, Update(), qi::locals<std::map<std::string, Assignment>>, Skipper> updateDefinition;
+                qi::rule<Iterator, qi::unused_type(std::map<std::string, Assignment>&), Skipper> assignmentDefinitionList;
+                qi::rule<Iterator, Assignment(), Skipper> assignmentDefinition;
                 
                 // Rules for reward definitions.
-                qi::rule<Iterator, qi::unused_type(std::map<std::string, RewardModel>&), Skipper> rewardDefinitionList;
+                qi::rule<Iterator, std::map<std::string, RewardModel>(), Skipper> rewardDefinitionList;
                 qi::rule<Iterator, qi::unused_type(std::map<std::string, RewardModel>&), qi::locals<std::vector<StateReward>, std::vector<TransitionReward>>, Skipper> rewardDefinition;
                 qi::rule<Iterator, StateReward(), Skipper> stateRewardDefinition;
-                qi::rule<Iterator, TransitionReward(), qi::locals<std::string>, Skipper> transitionRewardDefinition;
+                qi::rule<Iterator, TransitionReward(), Skipper> transitionRewardDefinition;
                 
                 // Rules for label definitions.
-                qi::rule<Iterator, qi::unused_type(std::map<std::string, std::unique_ptr<BaseExpression>>&), Skipper> labelDefinitionList;
-                qi::rule<Iterator, qi::unused_type(std::map<std::string, std::unique_ptr<BaseExpression>>&), Skipper> labelDefinition;
-                
-                // Rules for constant definitions.
-                qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper> constantDefinition;
-                qi::rule<Iterator, qi::unused_type(std::map<std::string, std::unique_ptr<BooleanConstantExpression>>&, std::map<std::string, std::unique_ptr<IntegerConstantExpression>>&, std::map<std::string, std::unique_ptr<DoubleConstantExpression>>&), Skipper> undefinedConstantDefinition;
-                qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper> definedConstantDefinition;
-                qi::rule<Iterator, qi::unused_type(std::map<std::string, std::unique_ptr<BooleanConstantExpression>>&), Skipper> undefinedBooleanConstantDefinition;
-                qi::rule<Iterator, qi::unused_type(std::map<std::string, std::unique_ptr<IntegerConstantExpression>>&), Skipper> undefinedIntegerConstantDefinition;
-                qi::rule<Iterator, qi::unused_type(std::map<std::string, std::unique_ptr<DoubleConstantExpression>>&), Skipper> undefinedDoubleConstantDefinition;
-                qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper> definedBooleanConstantDefinition;
-                qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper> definedIntegerConstantDefinition;
-                qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper> definedDoubleConstantDefinition;
+                qi::rule<Iterator, std::map<std::string, storm::expressions::Expression>(), Skipper> labelDefinitionList;
+                qi::rule<Iterator, qi::unused_type(std::map<std::string, storm::expressions::Expression>&), Skipper> labelDefinition;
                 
                 // Rules for formula definitions.
-                qi::rule<Iterator, qi::unused_type(), Skipper> formulaDefinitionList;
-                qi::rule<Iterator, qi::unused_type(), Skipper> formulaDefinition;
-                qi::rule<Iterator, qi::unused_type(), Skipper> constantIntegerFormulaDefinition;
-                qi::rule<Iterator, qi::unused_type(), Skipper> integerFormulaDefinition;
-                qi::rule<Iterator, qi::unused_type(), Skipper> constantDoubleFormulaDefinition;
-                qi::rule<Iterator, qi::unused_type(), Skipper> constantBooleanFormulaDefinition;
-                qi::rule<Iterator, qi::unused_type(), Skipper> booleanFormulaDefinition;
-
-                // Rules for variable recognition.
-                qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper> booleanVariableCreatorExpression;
-                qi::rule<Iterator, std::shared_ptr<BaseExpression>(), qi::locals<std::shared_ptr<BaseExpression>>, Skipper> integerVariableCreatorExpression;
-                
+                qi::rule<Iterator, std::map<std::string, storm::expressions::Expression>(), Skipper> formulaDefinitionList;
+                qi::rule<Iterator, qi::unused_type(std::map<std::string, storm::expressions::Expression>&), Skipper> formulaDefinition;
+                
+                // Rules for identifier parsing.
+                qi::rule<Iterator, std::string(), Skipper> identifier;
+                
+                // Rules for parsing a composed expression.
+                qi::rule<Iterator, storm::expressions::Expression(), Skipper> expression;
+                qi::rule<Iterator, storm::expressions::Expression(), Skipper> booleanExpression;
+                qi::rule<Iterator, storm::expressions::Expression(), Skipper> orExpression;
+                qi::rule<Iterator, storm::expressions::Expression(), Skipper> andExpression;
+                qi::rule<Iterator, storm::expressions::Expression(), Skipper> notExpression;
+                qi::rule<Iterator, storm::expressions::Expression(), Skipper> atomicBooleanExpression;
+                qi::rule<Iterator, storm::expressions::Expression(), Skipper> relativeExpression;
+                qi::rule<Iterator, storm::expressions::Expression(), Skipper> booleanVariableExpression;
+                qi::rule<Iterator, storm::expressions::Expression(), Skipper> numericalExpression;
+                qi::rule<Iterator, storm::expressions::Expression(), qi::locals<bool>, Skipper> plusExpression;
+                qi::rule<Iterator, storm::expressions::Expression(), Skipper> multiplicationExpression;
+                qi::rule<Iterator, storm::expressions::Expression(), Skipper> atomicNumericalExpression;
+                qi::rule<Iterator, storm::expressions::Expression(), Skipper> numericalVariableExpression;
+                qi::rule<Iterator, storm::expressions::Expression(), qi::locals<bool>, Skipper> minMaxExpression;
+                qi::rule<Iterator, storm::expressions::Expression(), qi::locals<bool>, Skipper> floorCeilExpression;
+                
+                // Parsers that recognize special keywords and operations.
                 storm::parser::prism::keywordsStruct keywords_;
                 storm::parser::prism::modelTypeStruct modelType_;
-                storm::parser::prism::relationalOperatorStruct relations_;
-                
-                // A mapping from module names to the modules themselves so they can be looked up for renaming later.
-                struct qi::symbols<char, Module> moduleMap_;
+                storm::parser::prism::BinaryRelationOperatorStruct relationOperator_;
+                storm::parser::prism::BinaryBooleanOperatorStruct binaryBooleanOperator_;
+                storm::parser::prism::UnaryBooleanOperatorStruct unaryBooleanOperator_;
+                storm::parser::prism::BinaryNumericalOperatorStruct binaryNumericalOperator_;
+                storm::parser::prism::UnaryNumericalOperatorStruct unaryNumericalOperator_;
                 
-                /*!
-                 * Adds a label with the given name and expression to the given label-to-expression map.
-                 *
-                 * @param name The name of the label.
-                 * @param expression The expression associated with the label.
-                 * @param nameToExpressionMap The map to which the label is added.
-                 */
-                void addLabel(std::string const& name, std::shared_ptr<BaseExpression> const& value, std::map<std::string, std::unique_ptr<BaseExpression>>& nameToExpressionMap);
-                
-                /*!
-                 * Adds a boolean assignment for the given variable with the given expression and adds it to the
-                 * provided variable-to-assignment map.
-                 *
-                 * @param variable The name of the variable that the assignment targets.
-                 * @param expression The expression that is assigned to the variable.
-                 * @param variableToAssignmentMap The map to which the assignment is added.
-                 */
-                void addBooleanAssignment(std::string const& variable, std::shared_ptr<BaseExpression> const& expression, std::map<std::string, Assignment>& variableToAssignmentMap);
-                
-                /*!
-                 * Adds a boolean assignment for the given variable with the given expression and adds it to the
-                 * provided variable-to-assignment map.
-                 *
-                 * @param variable The name of the variable that the assignment targets.
-                 * @param expression The expression that is assigned to the variable.
-                 * @param variableToAssignmentMap The map to which the assignment is added.
-                 */
-                void addIntegerAssignment(std::string const& variable, std::shared_ptr<BaseExpression> const& expression, std::map<std::string, Assignment>& variableToAssignmentMap);
-                
-                void addUndefinedBooleanConstant(std::string const& name, std::map<std::string, std::unique_ptr<BooleanConstantExpression>>& nameToExpressionMap);
-
-                void addUndefinedIntegerConstant(std::string const& name, std::map<std::string, std::unique_ptr<IntegerConstantExpression>>& nameToExpressionMap);
-
-                void addUndefinedDoubleConstant(std::string const& name, std::map<std::string, std::unique_ptr<DoubleConstantExpression>>& nameToExpressionMap);
-
-                /*!
-                 * Creates a module by renaming, i.e. takes the module given by the old name, creates a new module
-                 * with the given name which renames all identifiers according to the given mapping.
-                 *
-                 * @param name The name of the new module.
-                 * @param oldName The name of the module that is to be copied (modulo renaming).
-                 * @param renaming A mapping from identifiers to their new names.
-                 */
-                Module renameModule(std::string const& name, std::string const& oldName, std::map<std::string, std::string> const& renaming);
-                
-                /*!
-                 * Creates a new module with the given name, boolean and integer variables and commands.
-                 *
-                 * @param name The name of the module to create.
-                 * @param booleanVariables The boolean variables of the module.
-                 * @param integerVariables The integer variables of the module.
-                 * @param booleanVariableToLocalIndexMap A mapping of boolean variables to module-local indices.
-                 * @param integerVariableToLocalIndexMap A mapping of boolean variables to module-local indices.
-                 * @param commands The commands associated with this module.
-                 */
-                Module createModule(std::string const& name, std::vector<BooleanVariable> const& booleanVariables, std::vector<IntegerVariable> const& integerVariables, std::map<std::string, uint_fast64_t> const& booleanVariableToLocalIndexMap, std::map<std::string, uint_fast64_t> const& integerVariableToLocalIndexMap, std::vector<storm::ir::Command> const& commands);
-                
-                /*!
-                 * Creates an integer variable with the given name, domain and initial value and adds it to the
-                 * provided list of integer variables and the given mappings.
-                 *
-                 * @param name The name of the integer variable.
-                 * @param lower The expression that defines the lower bound of the domain.
-                 * @param upper The expression that defines the upper bound of the domain.
-                 * @param init The expression that defines the initial value of the variable.
-                 * @param integerVariableToGlobalIndexMap A mapping of integer variables to global indices.
-                 * @param isGlobalVariable A flag indicating whether the variable is supposed to be global or not.
-                 */
-                void createIntegerVariable(std::string const& name, std::shared_ptr<BaseExpression> const& lower, std::shared_ptr<BaseExpression> const& upper, std::shared_ptr<BaseExpression> const& init, std::vector<IntegerVariable>& integerVariables, std::map<std::string, uint_fast64_t>& integerVariableToGlobalIndexMap, bool isGlobalVariable);
-                
-                /*!
-                 * Creates an boolean variable with the given name and initial value and adds it to the
-                 * provided list of boolean variables and the given mappings.
-                 *
-                 * @param name The name of the boolean variable.
-                 * @param init The expression that defines the initial value of the variable.
-                 * @param booleanVariableToGlobalIndexMap A mapping of boolean variables to global indices.
-                 * @param isGlobalVariable A flag indicating whether the variable is supposed to be global or not.
-                 */
-                void createBooleanVariable(std::string const& name, std::shared_ptr<BaseExpression> const& init, std::vector<BooleanVariable>& booleanVariables, std::map<std::string, uint_fast64_t>& booleanVariableToGlobalIndexMap, bool isGlobalVariable);
-                
-                /*!
-                 * Creates a command with the given label, guard and updates.
-                 *
-                 * @param label The label of the command.
-                 * @param guard The guard of the command.
-                 * @param updates The updates associated with the command.
-                 */
-                Command createCommand(std::string const& label, std::shared_ptr<BaseExpression> const& guard, std::vector<Update> const& updates);
-                
-                /*!
-                 * Creates an update with the given likelihood and the given assignments to boolean and integer variables, respectively.
-                 *
-                 * @param likelihood The likelihood of this update being executed.
-                 * @param booleanAssignments The assignments to boolean variables this update involves.
-                 * @param integerAssignments The assignments to integer variables this update involves.
-                 */
-                Update createUpdate(std::shared_ptr<BaseExpression> const& likelihood, std::map<std::string, Assignment> const& booleanAssignments, std::map<std::string, Assignment> const& integerAssignments);
+                // Helper methods that add data to data structures.
                 
             };
-            
-            
         } // namespace prism
     } // namespace parser
 } // namespace storm
diff --git a/src/parser/prismparser/Tokens.h b/src/parser/prismparser/Tokens.h
index bcaefce7b..866bbbf24 100644
--- a/src/parser/prismparser/Tokens.h
+++ b/src/parser/prismparser/Tokens.h
@@ -1,7 +1,8 @@
 #ifndef STORM_PARSER_PRISMPARSER_TOKENS_H_
 #define	STORM_PARSER_PRISMPARSER_TOKENS_H_
 
-#include "src/storage/expressions/Expression.h"
+#include "src/storage/prism/Program.h"
+#include "src/storage/expressions/Expressions.h"
 
 namespace storm {
     namespace parser {
@@ -10,14 +11,14 @@ namespace storm {
              * A structure mapping the textual representation of a model type to the model type
              * representation of the intermediate representation.
              */
-            struct modelTypeStruct : qi::symbols<char, Program::ModelType> {
+            struct modelTypeStruct : qi::symbols<char, storm::prism::Program::ModelType> {
                 modelTypeStruct() {
                     add
-                    ("dtmc", Program::ModelType::DTMC)
-                    ("ctmc", Program::ModelType::CTMC)
-                    ("mdp", Program::ModelType::MDP)
-                    ("ctmdp", Program::ModelType::CTMDP)
-                    ("ma", Program::ModelType::MA);
+                    ("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);
                 }
             };
             
@@ -45,17 +46,63 @@ namespace storm {
             };
             
             /*!
-             * A structure mapping the textual representation of a binary relation.
+             * A structure mapping the textual representation of binary relations to the corresponding enum values.
              */
-            struct relationalOperatorStruct : qi::symbols<char, BinaryRelationExpression::RelationType> {
-                relationalOperatorStruct() {
+            struct BinaryRelationOperatorStruct : qi::symbols<char, storm::expressions::BinaryRelationExpression::RelationType> {
+                BinaryRelationOperatorStruct() {
                     add
-                    ("=", BinaryRelationExpression::RelationType::EQUAL)
-                    ("!=", BinaryRelationExpression::RelationType::NOT_EQUAL)
-                    ("<", BinaryRelationExpression::RelationType::LESS)
-                    ("<=", BinaryRelationExpression::RelationType::LESS_OR_EQUAL)
-                    (">", BinaryRelationExpression::RelationType::GREATER)
-                    (">=", BinaryRelationExpression::RelationType::GREATER_OR_EQUAL);
+                    ("=", storm::expressions::BinaryRelationExpression::RelationType::Equal)
+                    ("!=", storm::expressions::BinaryRelationExpression::RelationType::NotEqual)
+                    ("<", storm::expressions::BinaryRelationExpression::RelationType::Less)
+                    ("<=", storm::expressions::BinaryRelationExpression::RelationType::LessOrEqual)
+                    (">", storm::expressions::BinaryRelationExpression::RelationType::Greater)
+                    (">=", storm::expressions::BinaryRelationExpression::RelationType::GreaterOrEqual);
+                }
+            };
+            
+            /*!
+             * A structure mapping the textual representation of binary operators to the corresponding enum values.
+             */
+            struct BinaryBooleanOperatorStruct : qi::symbols<char, storm::expressions::BinaryBooleanFunctionExpression::OperatorType> {
+                BinaryBooleanOperatorStruct() {
+                    add
+                    ("&", storm::expressions::BinaryBooleanFunctionExpression::OperatorType::And)
+                    ("|", storm::expressions::BinaryBooleanFunctionExpression::OperatorType::Or)
+                    ("=>", storm::expressions::BinaryBooleanFunctionExpression::OperatorType::Implies)
+                    ("<=>", storm::expressions::BinaryBooleanFunctionExpression::OperatorType::Iff);
+                }
+            };
+
+            /*!
+             * A structure mapping the textual representation of binary operators to the corresponding enum values.
+             */
+            struct UnaryBooleanOperatorStruct : qi::symbols<char, storm::expressions::UnaryBooleanFunctionExpression::OperatorType> {
+                UnaryBooleanOperatorStruct() {
+                    add
+                    ("!", storm::expressions::UnaryBooleanFunctionExpression::OperatorType::Not);
+                }
+            };
+            
+            /*!
+             * A structure mapping the textual representation of binary boolean operators to the corresponding enum values.
+             */
+            struct BinaryNumericalOperatorStruct : qi::symbols<char, storm::expressions::BinaryNumericalFunctionExpression::OperatorType> {
+                BinaryNumericalOperatorStruct() {
+                    add
+                    ("+", storm::expressions::BinaryNumericalFunctionExpression::OperatorType::Plus)
+                    ("-", storm::expressions::BinaryNumericalFunctionExpression::OperatorType::Minus)
+                    ("*", storm::expressions::BinaryNumericalFunctionExpression::OperatorType::Times)
+                    ("/", storm::expressions::BinaryNumericalFunctionExpression::OperatorType::Divide);
+                }
+            };
+            
+            /*!
+             * A structure mapping the textual representation of binary operators to the corresponding enum values.
+             */
+            struct UnaryNumericalOperatorStruct : qi::symbols<char, storm::expressions::UnaryNumericalFunctionExpression::OperatorType> {
+                UnaryNumericalOperatorStruct() {
+                    add
+                    ("!", storm::expressions::UnaryNumericalFunctionExpression::OperatorType::Minus);
                 }
             };
         }
diff --git a/src/storage/expressions/Expression.h b/src/storage/expressions/Expression.h
index 875bcfbdc..e7768432d 100644
--- a/src/storage/expressions/Expression.h
+++ b/src/storage/expressions/Expression.h
@@ -1,7 +1,7 @@
 #ifndef STORM_STORAGE_EXPRESSIONS_EXPRESSION_H_
 #define STORM_STORAGE_EXPRESSIONS_EXPRESSION_H_
 
-#include <functional>
+#include <memory>
 
 #include "src/storage/expressions/BaseExpression.h"
 
diff --git a/src/storage/expressions/Expressions.h b/src/storage/expressions/Expressions.h
new file mode 100644
index 000000000..09febb4a4
--- /dev/null
+++ b/src/storage/expressions/Expressions.h
@@ -0,0 +1,13 @@
+#include "src/storage/expressions/BinaryBooleanFunctionExpression.h"
+#include "src/storage/expressions/BinaryNumericalFunctionExpression.h"
+#include "src/storage/expressions/BinaryRelationExpression.h"
+#include "src/storage/expressions/BooleanConstantExpression.h"
+#include "src/storage/expressions/BooleanLiteralExpression.h"
+#include "src/storage/expressions/DoubleConstantExpression.h"
+#include "src/storage/expressions/DoubleLiteralExpression.h"
+#include "src/storage/expressions/IntegerConstantExpression.h"
+#include "src/storage/expressions/IntegerLiteralExpression.h"
+#include "src/storage/expressions/UnaryBooleanFunctionExpression.h"
+#include "src/storage/expressions/UnaryNumericalFunctionExpression.h"
+#include "src/storage/expressions/VariableExpression.h"
+#include "src/storage/expressions/Expression.h"
\ No newline at end of file
diff --git a/src/storage/prism/Program.cpp b/src/storage/prism/Program.cpp
index c01e24c0d..97daf8142 100644
--- a/src/storage/prism/Program.cpp
+++ b/src/storage/prism/Program.cpp
@@ -5,7 +5,7 @@
 
 namespace storm {
     namespace prism {
-        Program::Program(ModelType modelType, std::set<std::string> const& undefinedBooleanConstants, std::map<std::string, storm::expressions::Expression> definedBooleanConstants, std::set<std::string> const& undefinedIntegerConstants, std::map<std::string, storm::expressions::Expression> definedIntegerConstants, std::set<std::string> const& undefinedDoubleConstants, std::map<std::string, storm::expressions::Expression> definedDoubleConstants, std::map<std::string, BooleanVariable> const& globalBooleanVariables, std::map<std::string, IntegerVariable> const& globalIntegerVariables, std::vector<storm::prism::Module> const& modules, std::map<std::string, storm::prism::RewardModel> const& rewardModels, bool hasInitialStatesExpression, storm::expressions::Expression const& initialStatesExpression, std::map<std::string, storm::expressions::Expression> const& labels, std::string const& filename, uint_fast64_t lineNumber) : LocatedInformation(filename, lineNumber), modelType(modelType), undefinedBooleanConstants(undefinedBooleanConstants), definedBooleanConstants(definedBooleanConstants), undefinedIntegerConstants(undefinedIntegerConstants), definedIntegerConstants(definedIntegerConstants), undefinedDoubleConstants(undefinedDoubleConstants), definedDoubleConstants(definedDoubleConstants), globalBooleanVariables(globalBooleanVariables), globalIntegerVariables(globalIntegerVariables), modules(modules), rewardModels(rewardModels), hasInitialStatesExpression(hasInitialStatesExpression), initialStatesExpression(initialStatesExpression), labels(labels), actions(), actionsToModuleIndexMap(), variableToModuleIndexMap() {
+        Program::Program(ModelType modelType, std::set<std::string> const& undefinedBooleanConstants, std::map<std::string, storm::expressions::Expression> const& definedBooleanConstants, std::set<std::string> const& undefinedIntegerConstants, std::map<std::string, storm::expressions::Expression> const& definedIntegerConstants, std::set<std::string> const& undefinedDoubleConstants, std::map<std::string, storm::expressions::Expression> const& definedDoubleConstants, std::map<std::string, BooleanVariable> const& globalBooleanVariables, std::map<std::string, IntegerVariable> const& globalIntegerVariables, std::map<std::string, storm::expressions::Expression>const& formulas, std::vector<storm::prism::Module> const& modules, std::map<std::string, storm::prism::RewardModel> const& rewardModels, bool hasInitialStatesExpression, storm::expressions::Expression const& initialStatesExpression, std::map<std::string, storm::expressions::Expression> const& labels, std::string const& filename, uint_fast64_t lineNumber) : LocatedInformation(filename, lineNumber), modelType(modelType), undefinedBooleanConstants(undefinedBooleanConstants), definedBooleanConstants(definedBooleanConstants), undefinedIntegerConstants(undefinedIntegerConstants), definedIntegerConstants(definedIntegerConstants), undefinedDoubleConstants(undefinedDoubleConstants), definedDoubleConstants(definedDoubleConstants), globalBooleanVariables(globalBooleanVariables), globalIntegerVariables(globalIntegerVariables), formulas(formulas), modules(modules), rewardModels(rewardModels), hasInitialStatesExpression(hasInitialStatesExpression), initialStatesExpression(initialStatesExpression), labels(labels), actions(), actionsToModuleIndexMap(), variableToModuleIndexMap() {
             // Now build the mapping from action names to module indices so that the lookup can later be performed quickly.
             for (unsigned int moduleIndex = 0; moduleIndex < this->getNumberOfModules(); moduleIndex++) {
                 Module const& module = this->getModule(moduleIndex);
@@ -101,6 +101,10 @@ namespace storm {
             return this->getGlobalIntegerVariables().size();
         }
         
+        std::map<std::string, storm::expressions::Expression> const& Program::getFormulas() const {
+            return this->formulas;
+        }
+        
         std::size_t Program::getNumberOfModules() const {
             return this->getModules().size();
         }
@@ -175,7 +179,7 @@ namespace storm {
                 newModules.push_back(module.restrictCommands(indexSet));
             }
             
-            return Program(this->getModelType(), this->getUndefinedBooleanConstants(), this->getUndefinedIntegerConstants(), this->getUndefinedDoubleConstants(), this->getGlobalBooleanVariables(), this->getGlobalIntegerVariables(), newModules, this->getRewardModels(), this->definesInitialStatesExpression(), this->getInitialStatesExpression(), this->getLabels());
+            return Program(this->getModelType(), this->getUndefinedBooleanConstants(), this->getDefinedBooleanConstants(), this->getUndefinedIntegerConstants(), this->getDefinedIntegerConstants(), this->getUndefinedDoubleConstants(), this->getDefinedDoubleConstants(), this->getGlobalBooleanVariables(), this->getGlobalIntegerVariables(), this->getFormulas(), newModules, this->getRewardModels(), this->definesInitialStatesExpression(), this->getInitialStatesExpression(), this->getLabels());
         }
         
         std::ostream& operator<<(std::ostream& stream, Program const& program) {
diff --git a/src/storage/prism/Program.h b/src/storage/prism/Program.h
index 36326b12b..33056833a 100644
--- a/src/storage/prism/Program.h
+++ b/src/storage/prism/Program.h
@@ -32,6 +32,7 @@ namespace storm {
              * @param definedDoubleConstants The defined double constants of the program.
              * @param globalBooleanVariables The global boolean variables of the program.
              * @param globalIntegerVariables The global integer variables of the program.
+             * @param formulas The formulas defined in the program.
              * @param modules The modules of the program.
              * @param hasInitialStatesExpression A flag indicating whether the program specifies its initial states via
              * an explicit initial construct.
@@ -43,7 +44,7 @@ namespace storm {
              * @param filename The filename in which the program is defined.
              * @param lineNumber The line number in which the program is defined.
              */
-            Program(ModelType modelType, std::set<std::string> const& undefinedBooleanConstants, std::map<std::string, storm::expressions::Expression> definedBooleanConstants, std::set<std::string> const& undefinedIntegerConstants, std::map<std::string, storm::expressions::Expression> definedIntegerConstants, std::set<std::string> const& undefinedDoubleConstants, std::map<std::string, storm::expressions::Expression> definedDoubleConstants, std::map<std::string, BooleanVariable> const& globalBooleanVariables, std::map<std::string, IntegerVariable> const& globalIntegerVariables, std::vector<storm::prism::Module> const& modules, std::map<std::string, storm::prism::RewardModel> const& rewardModels, bool hasInitialStatesExpression, storm::expressions::Expression const& initialStatesExpression, std::map<std::string, storm::expressions::Expression> const& labels, std::string const& filename = "", uint_fast64_t lineNumber = 0);
+            Program(ModelType modelType, std::set<std::string> const& undefinedBooleanConstants, std::map<std::string, storm::expressions::Expression> const& definedBooleanConstants, std::set<std::string> const& undefinedIntegerConstants, std::map<std::string, storm::expressions::Expression> const& definedIntegerConstants, std::set<std::string> const& undefinedDoubleConstants, std::map<std::string, storm::expressions::Expression> const& definedDoubleConstants, std::map<std::string, BooleanVariable> const& globalBooleanVariables, std::map<std::string, IntegerVariable> const& globalIntegerVariables, std::map<std::string, storm::expressions::Expression> const& formulas, std::vector<storm::prism::Module> const& modules, std::map<std::string, storm::prism::RewardModel> const& rewardModels, bool hasInitialStatesExpression, storm::expressions::Expression const& initialStatesExpression, std::map<std::string, storm::expressions::Expression> const& labels, std::string const& filename = "", uint_fast64_t lineNumber = 0);
             
             // Provide default implementations for constructors and assignments.
             Program() = default;
@@ -173,6 +174,13 @@ namespace storm {
              */
             std::size_t getNumberOfGlobalIntegerVariables() const;
 
+            /*!
+             * Retrieves the formulas defined in the program.
+             *
+             * @return The formulas defined in the program.
+             */
+            std::map<std::string, storm::expressions::Expression> const& getFormulas() const;
+            
             /*!
              * Retrieves the number of modules in the program.
              *
@@ -286,12 +294,15 @@ namespace storm {
             // A mapping of (defined) double constants to their values (given as expressions).
             std::map<std::string, storm::expressions::Expression> definedDoubleConstants;
 
-            // A list of global boolean variables.
+            // The global boolean variables.
             std::map<std::string, BooleanVariable> globalBooleanVariables;
             
-            // A list of global integer variables.
+            // The global integer variables.
             std::map<std::string, IntegerVariable> globalIntegerVariables;
             
+            // A mapping of formula names to the corresponding expressions.
+            std::map<std::string, storm::expressions::Expression> formulas;
+            
             // The modules associated with the program.
             std::vector<storm::prism::Module> modules;
             
diff --git a/src/storage/prism/Update.cpp b/src/storage/prism/Update.cpp
index da92823bb..edd400ee2 100644
--- a/src/storage/prism/Update.cpp
+++ b/src/storage/prism/Update.cpp
@@ -3,25 +3,17 @@
 
 namespace storm {
     namespace prism {
-        Update::Update(uint_fast64_t globalIndex, storm::expressions::Expression const& likelihoodExpression, std::map<std::string, storm::prism::Assignment> const& booleanAssignments, std::map<std::string, storm::prism::Assignment> const& integerAssignments, std::string const& filename, uint_fast64_t lineNumber) : LocatedInformation(filename, lineNumber), likelihoodExpression(likelihoodExpression), booleanAssignments(booleanAssignments), integerAssignments(integerAssignments), globalIndex(globalIndex) {
+        Update::Update(uint_fast64_t globalIndex, storm::expressions::Expression const& likelihoodExpression, std::map<std::string, storm::prism::Assignment> const& assignments, std::string const& filename, uint_fast64_t lineNumber) : LocatedInformation(filename, lineNumber), likelihoodExpression(likelihoodExpression), assignments(assignments), globalIndex(globalIndex) {
             // Nothing to do here.
         }
         
-        Update::Update(Update const& update, uint_fast64_t newGlobalIndex, std::map<std::string, std::string> const& renaming, std::string const& filename, uint_fast64_t lineNumber) : LocatedInformation(filename, lineNumber), likelihoodExpression(update.getLikelihoodExpression().substitute<std::map>(renaming)), booleanAssignments(), integerAssignments(), globalIndex(newGlobalIndex) {
-            for (auto const& variableAssignmentPair : update.getBooleanAssignments()) {
+        Update::Update(Update const& update, uint_fast64_t newGlobalIndex, std::map<std::string, std::string> const& renaming, std::string const& filename, uint_fast64_t lineNumber) : LocatedInformation(filename, lineNumber), likelihoodExpression(update.getLikelihoodExpression().substitute<std::map>(renaming)), assignments(), globalIndex(newGlobalIndex) {
+            for (auto const& variableAssignmentPair : update.getAssignments()) {
                 auto const& namePair = renaming.find(variableAssignmentPair.first);
                 if (namePair != renaming.end()) {
-                    this->booleanAssignments.emplace(namePair->second, Assignment(variableAssignmentPair.second, renaming, filename, lineNumber));
+                    this->assignments.emplace(namePair->second, Assignment(variableAssignmentPair.second, renaming, filename, lineNumber));
                 } else {
-                    this->booleanAssignments.emplace(variableAssignmentPair.first, Assignment(variableAssignmentPair.second, renaming, filename, lineNumber));
-                }
-            }
-            for (auto const& variableAssignmentPair : update.getIntegerAssignments()) {
-                auto const& namePair = renaming.find(variableAssignmentPair.first);
-                if (renaming.count(variableAssignmentPair.first) > 0) {
-                    this->integerAssignments.emplace(namePair->second, Assignment(variableAssignmentPair.second, renaming, filename, lineNumber));
-                } else {
-                    this->integerAssignments.emplace(variableAssignmentPair.first, Assignment(variableAssignmentPair.second, renaming, filename, lineNumber));
+                    this->assignments.emplace(variableAssignmentPair.first, Assignment(variableAssignmentPair.second, renaming, filename, lineNumber));
                 }
             }
             this->likelihoodExpression = update.getLikelihoodExpression().substitute<std::map>(renaming);
@@ -31,35 +23,18 @@ namespace storm {
             return likelihoodExpression;
         }
         
-        std::size_t Update::getNumberOfBooleanAssignments() const {
-            return booleanAssignments.size();
-        }
-        
-        std::size_t Update::getNumberOfIntegerAssignments() const {
-            return integerAssignments.size();
-        }
-        
-        std::map<std::string, storm::prism::Assignment> const& Update::getBooleanAssignments() const {
-            return booleanAssignments;
-        }
-        
-        std::map<std::string, storm::prism::Assignment> const& Update::getIntegerAssignments() const {
-            return integerAssignments;
+        std::size_t Update::getNumberOfAssignments() const {
+            return this->assignments.size();
         }
         
-        storm::prism::Assignment const& Update::getBooleanAssignment(std::string const& variableName) const {
-            auto variableAssignmentPair = booleanAssignments.find(variableName);
-            if (variableAssignmentPair == booleanAssignments.end()) {
-                throw storm::exceptions::OutOfRangeException() << "Cannot find boolean assignment for variable '" << variableName << "' in update " << *this << ".";
-            }
-            
-            return variableAssignmentPair->second;
+        std::map<std::string, storm::prism::Assignment> const& Update::getAssignments() const {
+            return this->assignments;
         }
         
-        storm::prism::Assignment const& Update::getIntegerAssignment(std::string const& variableName) const {
-            auto variableAssignmentPair = integerAssignments.find(variableName);
-            if (variableAssignmentPair == integerAssignments.end()) {
-                throw storm::exceptions::OutOfRangeException() << "Cannot find integer assignment for variable '" << variableName << "' in update " << *this << ".";
+        storm::prism::Assignment const& Update::getAssignment(std::string const& variableName) const {
+            auto variableAssignmentPair = this->getAssignments().find(variableName);
+            if (variableAssignmentPair == this->getAssignments().end()) {
+                throw storm::exceptions::OutOfRangeException() << "Cannot find assignment for variable '" << variableName << "' in update " << *this << ".";
             }
             
             return variableAssignmentPair->second;
@@ -72,17 +47,9 @@ namespace storm {
         std::ostream& operator<<(std::ostream& stream, Update const& update) {
             stream << update.getLikelihoodExpression() << " : ";
             uint_fast64_t i = 0;
-            for (auto const& assignment : update.getBooleanAssignments()) {
-                stream << assignment.second;
-                if (i < update.getBooleanAssignments().size() - 1 || update.getIntegerAssignments().size() > 0) {
-                    stream << " & ";
-                }
-                ++i;
-            }
-            i = 0;
-            for (auto const& assignment : update.getIntegerAssignments()) {
+            for (auto const& assignment : update.getAssignments()) {
                 stream << assignment.second;
-                if (i < update.getIntegerAssignments().size() - 1) {
+                if (i < update.getAssignments().size() - 1) {
                     stream << " & ";
                 }
                 ++i;
diff --git a/src/storage/prism/Update.h b/src/storage/prism/Update.h
index 4999c04bd..517803c2b 100644
--- a/src/storage/prism/Update.h
+++ b/src/storage/prism/Update.h
@@ -20,7 +20,7 @@ namespace storm {
              * @param filename The filename in which the variable is defined.
              * @param lineNumber The line number in which the variable is defined.
              */
-            Update(uint_fast64_t index, storm::expressions::Expression const& likelihoodExpression, std::map<std::string, storm::prism::Assignment> const& booleanAssignments, std::map<std::string, storm::prism::Assignment> const& integerAssignments, std::string const& filename = "", uint_fast64_t lineNumber = 0);
+            Update(uint_fast64_t index, storm::expressions::Expression const& likelihoodExpression, std::map<std::string, storm::prism::Assignment> const& assignments, std::string const& filename = "", uint_fast64_t lineNumber = 0);
             
             /*!
              * Creates a copy of the given update and performs the provided renaming.
@@ -48,46 +48,25 @@ namespace storm {
             storm::expressions::Expression const& getLikelihoodExpression() const;
             
             /*!
-             * Retrieves the number of boolean assignments associated with this update.
+             * Retrieves the number of assignments associated with this update.
              *
-             * @return The number of boolean assignments associated with this update.
+             * @return The number of assignments associated with this update.
              */
-            std::size_t getNumberOfBooleanAssignments() const;
+            std::size_t getNumberOfAssignments() const;
             
             /*!
-             * Retrieves the number of integer assignments associated with this update.
+             * Retrieves a reference to the map of variable names to their respective assignments.
              *
-             * @return The number of integer assignments associated with this update.
+             * @return A reference to the map of variable names to their respective assignments.
              */
-            std::size_t getNumberOfIntegerAssignments() const;
+            std::map<std::string, storm::prism::Assignment> const& getAssignments() const;
             
             /*!
-             * Retrieves a reference to the map of boolean variable names to their respective assignments.
+             * Retrieves a reference to the assignment for the variable with the given name.
              *
-             * @return A reference to the map of boolean variable names to their respective assignments.
+             * @return A reference to the assignment for the variable with the given name.
              */
-            std::map<std::string, storm::prism::Assignment> const& getBooleanAssignments() const;
-            
-            /*!
-             * Retrieves a reference to the map of integer variable names to their respective assignments.
-             *
-             * @return A reference to the map of integer variable names to their respective assignments.
-             */
-            std::map<std::string, storm::prism::Assignment> const& getIntegerAssignments() const;
-            
-            /*!
-             * Retrieves a reference to the assignment for the boolean variable with the given name.
-             *
-             * @return A reference to the assignment for the boolean variable with the given name.
-             */
-            storm::prism::Assignment const& getBooleanAssignment(std::string const& variableName) const;
-            
-            /*!
-             * Retrieves a reference to the assignment for the integer variable with the given name.
-             *
-             * @return A reference to the assignment for the integer variable with the given name.
-             */
-            storm::prism::Assignment const& getIntegerAssignment(std::string const& variableName) const;
+            storm::prism::Assignment const& getAssignment(std::string const& variableName) const;
             
             /*!
              * Retrieves the global index of the update, that is, a unique index over all modules.
@@ -102,11 +81,8 @@ namespace storm {
             // An expression specifying the likelihood of taking this update.
             storm::expressions::Expression likelihoodExpression;
             
-            // A mapping of boolean variable names to their assignments in this update.
-            std::map<std::string, storm::prism::Assignment> booleanAssignments;
-            
-            // A mapping of integer variable names to their assignments in this update.
-            std::map<std::string, storm::prism::Assignment> integerAssignments;
+            // A mapping of variable names to their assignments in this update.
+            std::map<std::string, storm::prism::Assignment> assignments;
             
             // The global index of the update.
             uint_fast64_t globalIndex;
diff --git a/test/functional/parser/ParsePrismTest.cpp b/test/functional/parser/ParsePrismTest.cpp
deleted file mode 100644
index 0a8abb420..000000000
--- a/test/functional/parser/ParsePrismTest.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-#include "gtest/gtest.h"
-#include "storm-config.h"
-#include "src/parser/PrismParser.h"
-//#include "src/utility/IoUtility.h"
-#include "src/ir/Program.h"
-#include "src/adapters/ExplicitModelAdapter.h"
-#include "src/models/Dtmc.h"
-#include "src/models/Mdp.h"
-#include "src/settings/Settings.h"
-#include "src/settings/InternalOptionMemento.h"
-
-TEST(ParsePrismTest, parseCrowds5_5) {
-	storm::settings::InternalOptionMemento deadlockOption("fixDeadlocks", true);
-	ASSERT_TRUE(storm::settings::Settings::getInstance()->isSet("fixDeadlocks"));
-	storm::ir::Program program;
-	ASSERT_NO_THROW(program = storm::parser::PrismParserFromFile(STORM_CPP_BASE_PATH "/examples/dtmc/crowds/crowds5_5.pm"));
-	std::shared_ptr<storm::models::AbstractModel<double>> model = storm::adapters::ExplicitModelAdapter<double>::translateProgram(program);
-    
-	ASSERT_EQ(model->getNumberOfStates(), 8607ull);
-	ASSERT_EQ(model->getNumberOfTransitions(), 15113ull);
-}
-
-TEST(ParsePrismTest, parseTwoDice) {
-	storm::ir::Program program;
-	ASSERT_NO_THROW(program = storm::parser::PrismParserFromFile(STORM_CPP_BASE_PATH "/examples/mdp/two_dice/two_dice.nm"));
-
-	std::shared_ptr<storm::models::AbstractModel<double>> model = storm::adapters::ExplicitModelAdapter<double>::translateProgram(program, "", "coinflips");
-	
-	ASSERT_EQ(model->getNumberOfStates(), 169ull);
-	ASSERT_EQ(model->as<storm::models::AbstractNondeterministicModel<double>>()->getNumberOfChoices(), 254ull);
-	ASSERT_EQ(model->getNumberOfTransitions(), 436ull);
-}