From cc71a002f4bd9bc81d7401812d5f3f50e2f6a118 Mon Sep 17 00:00:00 2001
From: masawei <manuel.sascha.weiand@rwth-aachen.de>
Date: Thu, 2 Jan 2014 16:46:53 +0100
Subject: [PATCH] Refactored NondeterministicSparseTransitionParser.h/.cpp.

-Changed structure to conform to common parser structure: static class with two passes and structs to handle value passing.
-Killed all warnings (signed unsigned interger compare)
-Made parser more flexible: Is now able to ignore arbitrarily many columns after the value column (instead of only one).
-Threw out a number of unnecessary includes.
-more...

Next up: Refactor NondeterministicModelParser.h/.cpp


Former-commit-id: fd2fdb7fdf88af38f733ed6f83ef2d353a614e2f
---
 .../DeterministicSparseTransitionParser.cpp   |  18 +-
 .../DeterministicSparseTransitionParser.h     |   4 +-
 .../MarkovAutomatonSparseTransitionParser.cpp |   2 +-
 src/parser/NondeterministicModelParser.cpp    |  18 +-
 ...NondeterministicSparseTransitionParser.cpp | 565 +++++++-----------
 .../NondeterministicSparseTransitionParser.h  | 113 +++-
 src/parser/Parser.cpp                         |  23 +
 src/parser/Parser.h                           |   5 +
 8 files changed, 373 insertions(+), 375 deletions(-)

diff --git a/src/parser/DeterministicSparseTransitionParser.cpp b/src/parser/DeterministicSparseTransitionParser.cpp
index 03b94c78c..2ac9098bd 100644
--- a/src/parser/DeterministicSparseTransitionParser.cpp
+++ b/src/parser/DeterministicSparseTransitionParser.cpp
@@ -30,12 +30,14 @@ namespace parser {
 
 storm::storage::SparseMatrix<double> DeterministicSparseTransitionParser::parseDeterministicTransitions(std::string const& filename, bool insertDiagonalEntriesIfMissing) {
 
-	return DeterministicSparseTransitionParser::parse(filename, false, insertDiagonalEntriesIfMissing);
+	RewardMatrixInformationStruct nullInformation;
+
+	return DeterministicSparseTransitionParser::parse(filename, false, nullInformation, insertDiagonalEntriesIfMissing);
 }
 
 storm::storage::SparseMatrix<double> DeterministicSparseTransitionParser::parseDeterministicTransitionRewards(std::string const& filename, RewardMatrixInformationStruct const& rewardMatrixInformation) {
 
-	return DeterministicSparseTransitionParser::parse(filename, true, false, rewardMatrixInformation);
+	return DeterministicSparseTransitionParser::parse(filename, true, rewardMatrixInformation);
 }
 
 DeterministicSparseTransitionParser::FirstPassResult DeterministicSparseTransitionParser::firstPass(char* buf, SupportedLineEndingsEnum lineEndings, bool insertDiagonalEntriesIfMissing) {
@@ -44,7 +46,7 @@ DeterministicSparseTransitionParser::FirstPassResult DeterministicSparseTransiti
 
 	// Skip the format hint if it is there.
 	buf = trimWhitespaces(buf);
-	if(buf[0] != '0') {
+	if(buf[0] < '0' || buf[0] > '9') {
 		buf = storm::parser::forwardToNextLine(buf, lineEndings);
 	}
 
@@ -53,7 +55,7 @@ DeterministicSparseTransitionParser::FirstPassResult DeterministicSparseTransiti
 	bool rowHadDiagonalEntry = false;
 	while (buf[0] != '\0') {
 
-		// Read the transition..
+		// Read the transition.
 		row = checked_strtol(buf, &buf);
 		col = checked_strtol(buf, &buf);
 		// The actual read value is not needed here.
@@ -106,7 +108,7 @@ DeterministicSparseTransitionParser::FirstPassResult DeterministicSparseTransiti
 	return result;
 }
 
-storm::storage::SparseMatrix<double> DeterministicSparseTransitionParser::parse(std::string const& filename, bool rewardFile, bool insertDiagonalEntriesIfMissing, RewardMatrixInformationStruct const& rewardMatrixInformation) {
+storm::storage::SparseMatrix<double> DeterministicSparseTransitionParser::parse(std::string const& filename, bool isRewardFile, RewardMatrixInformationStruct const& rewardMatrixInformation, bool insertDiagonalEntriesIfMissing) {
 	// Enforce locale where decimal point is '.'.
 		setlocale(LC_NUMERIC, "C");
 
@@ -138,11 +140,11 @@ storm::storage::SparseMatrix<double> DeterministicSparseTransitionParser::parse(
 
 		// Skip the format hint if it is there.
 		buf = trimWhitespaces(buf);
-		if(buf[0] != '0') {
+		if(buf[0] < '0' || buf[0] > '9') {
 			buf = storm::parser::forwardToNextLine(buf, lineEndings);
 		}
 
-		if(rewardFile) {
+		if(isRewardFile) {
 			// The reward matrix should match the size of the transition matrix.
 			if (firstPass.highestStateIndex + 1 > rewardMatrixInformation.rowCount || firstPass.highestStateIndex + 1 > rewardMatrixInformation.columnCount) {
 				LOG4CPLUS_ERROR(logger, "Reward matrix has more rows or columns than transition matrix.");
@@ -169,7 +171,7 @@ storm::storage::SparseMatrix<double> DeterministicSparseTransitionParser::parse(
 		// work, i.e. the values in the matrix will be at wrong places.
 
 		// Different parsing routines for transition systems and transition rewards.
-		if(rewardFile) {
+		if(isRewardFile) {
 			while (buf[0] != '\0') {
 
 				// Read next transition.
diff --git a/src/parser/DeterministicSparseTransitionParser.h b/src/parser/DeterministicSparseTransitionParser.h
index 45ce9ac26..b9bb1621e 100644
--- a/src/parser/DeterministicSparseTransitionParser.h
+++ b/src/parser/DeterministicSparseTransitionParser.h
@@ -59,7 +59,7 @@ private:
 	 *
 	 * @param buffer The buffer that cointains the input.
 	 * @param lineEndings The line endings that are to be used while parsing.
-	 * @param insertDiagonalEntriesIfMissing Flag determining whether
+	 * @param insertDiagonalEntriesIfMissing A flag set iff entries on the primary diagonal of the matrix should be added in case they are missing in the parsed file.
 	 * @return A structure representing the result of the first pass.
 	 */
 	static FirstPassResult firstPass(char* buffer, SupportedLineEndingsEnum lineEndings, bool insertDiagonalEntriesIfMissing = true);
@@ -74,7 +74,7 @@ private:
 	 * @param rewardMatrixInformation A struct containing information that is used to check if the transition reward matrix fits to the rest of the model.
 	 * @return A SparseMatrix containing the parsed file contents.
 	 */
-	static storm::storage::SparseMatrix<double> parse(std::string const& filename, bool rewardFile, bool insertDiagonalEntriesIfMissing = false, RewardMatrixInformationStruct const& rewardMatrixInformation = nullptr);
+	static storm::storage::SparseMatrix<double> parse(std::string const& filename, bool isRewardFile, RewardMatrixInformationStruct const& rewardMatrixInformation, bool insertDiagonalEntriesIfMissing = false);
 
 };
 
diff --git a/src/parser/MarkovAutomatonSparseTransitionParser.cpp b/src/parser/MarkovAutomatonSparseTransitionParser.cpp
index 1ca4f7264..15a7c5809 100644
--- a/src/parser/MarkovAutomatonSparseTransitionParser.cpp
+++ b/src/parser/MarkovAutomatonSparseTransitionParser.cpp
@@ -14,7 +14,7 @@ MarkovAutomatonSparseTransitionParser::FirstPassResult MarkovAutomatonSparseTran
 
 	// Skip the format hint if it is there.
 	buf = trimWhitespaces(buf);
-	if(buf[0] != '0') {
+	if(buf[0] < '0' || buf[0] > '9') {
 		buf = storm::parser::forwardToNextLine(buf, lineEndings);
 	}
 
diff --git a/src/parser/NondeterministicModelParser.cpp b/src/parser/NondeterministicModelParser.cpp
index d4ab649ba..5f6e13360 100644
--- a/src/parser/NondeterministicModelParser.cpp
+++ b/src/parser/NondeterministicModelParser.cpp
@@ -29,23 +29,23 @@ namespace parser {
 NondeterministicModelParserResultContainer<double> parseNondeterministicModel(std::string const & transitionSystemFile, std::string const & labelingFile,
 		std::string const & stateRewardFile, std::string const & transitionRewardFile) {
 
-	NondeterministicSparseTransitionParserResult_t nondeterministicSparseTransitionParserResult(std::move(storm::parser::NondeterministicSparseTransitionParser(transitionSystemFile)));
-	storm::storage::SparseMatrix<double> resultTransitionSystem(std::move(nondeterministicSparseTransitionParserResult.first));
+	NondeterministicSparseTransitionParser::Result transitionParserResult(std::move(storm::parser::NondeterministicSparseTransitionParser::parseNondeterministicTransitions(transitionSystemFile)));
+	storm::storage::SparseMatrix<double> transitions(std::move(transitionParserResult.transitionMatrix));
 
-	uint_fast64_t stateCount = resultTransitionSystem.getColumnCount();
-	uint_fast64_t rowCount = resultTransitionSystem.getRowCount();
+	uint_fast64_t stateCount = transitions.getColumnCount();
+	uint_fast64_t rowCount = transitions.getRowCount();
 
-	storm::models::AtomicPropositionsLabeling resultLabeling(std::move(storm::parser::AtomicPropositionLabelingParser(stateCount, labelingFile)));
+	storm::models::AtomicPropositionsLabeling labeling(std::move(storm::parser::AtomicPropositionLabelingParser(stateCount, labelingFile)));
 
-	NondeterministicModelParserResultContainer<double> result(std::move(resultTransitionSystem), std::move(nondeterministicSparseTransitionParserResult.second), std::move(resultLabeling));
+	NondeterministicModelParserResultContainer<double> result(std::move(transitions), std::move(transitionParserResult.rowMapping), std::move(labeling));
 	
 	if (stateRewardFile != "") {
 		result.stateRewards.reset(storm::parser::SparseStateRewardParser::parseSparseStateReward(stateCount, stateRewardFile));
 	}
+
 	if (transitionRewardFile != "") {
-		RewardMatrixInformationStruct* rewardMatrixInfo = new RewardMatrixInformationStruct(rowCount, stateCount, &result.rowMapping);
-		result.transitionRewards.reset(storm::parser::NondeterministicSparseTransitionParser(transitionRewardFile, rewardMatrixInfo).first);
-		delete rewardMatrixInfo;
+		RewardMatrixInformationStruct rewardMatrixInfo(rowCount, stateCount, &result.rowMapping);
+		result.transitionRewards.reset(storm::parser::NondeterministicSparseTransitionParser::parseNondeterministicTransitionRewards(transitionRewardFile, rewardMatrixInfo).transitionMatrix);
 	}
 	return result;
 }
diff --git a/src/parser/NondeterministicSparseTransitionParser.cpp b/src/parser/NondeterministicSparseTransitionParser.cpp
index 02a1e94f1..fa20585ec 100644
--- a/src/parser/NondeterministicSparseTransitionParser.cpp
+++ b/src/parser/NondeterministicSparseTransitionParser.cpp
@@ -1,5 +1,5 @@
 /*!
- *	TraParser.cpp
+ *	NondeterministicSparseTransitionParser.cpp
  *
  *	Created on: 20.11.2012
  *		Author: Gereon Kremer
@@ -7,380 +7,277 @@
 
 #include "src/parser/NondeterministicSparseTransitionParser.h"
 
-#include <errno.h>
-#include <time.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <locale.h>
-
-#include <cstdlib>
-#include <cstdio>
-#include <cstring>
-#include <clocale>
-#include <iostream>
-#include <utility>
 #include <string>
 
 #include "src/settings/Settings.h"
 #include "src/exceptions/FileIoException.h"
 #include "src/exceptions/WrongFormatException.h"
-#include <cstdint>
+
 #include "log4cplus/logger.h"
 #include "log4cplus/loggingmacros.h"
 extern log4cplus::Logger logger;
 
 namespace storm {
-namespace parser {
+	namespace parser {
 
-/*!
- *	@brief	Perform first pass through the file and obtain overall number of
- *	choices, number of non-zero cells and maximum node id.
- *
- *	This method does the first pass through the transition file.
- *
- *	It computes the overall number of nondeterministic choices, i.e. the
- *	number of rows in the matrix that should be created.
- *	It also calculates the overall number of non-zero cells, i.e. the number
- *	of elements the matrix has to hold, and the maximum node id, i.e. the
- *	number of columns of the matrix.
- *
- *	@param buf Data to scan. Is expected to be some char array.
- *	@param choices Overall number of choices.
- *	@param maxnode Is set to highest id of all nodes.
- *	@return The number of non-zero elements.
- */
-uint_fast64_t firstPass(char* buf, SupportedLineEndingsEnum lineEndings, uint_fast64_t& choices, int_fast64_t& maxnode, RewardMatrixInformationStruct* rewardMatrixInformation) {
-	bool isRewardFile = rewardMatrixInformation != nullptr;
-
-	/*
-	 *	Check file header and extract number of transitions.
-	 */
-	if (!isRewardFile) {
-		// skip format hint
-		buf = storm::parser::forwardToNextLine(buf, lineEndings);
-	}
-
-	/*
-	 *	Read all transitions.
-	 */
-	int_fast64_t source, target, choice, lastchoice = -1;
-	int_fast64_t lastsource = -1;
-	uint_fast64_t nonzero = 0;
-	double val;
-	choices = 0;
-	maxnode = 0;
-	while (buf[0] != '\0') {
-		/*
-		 *	Read source state and choice.
-		 */
-		source = checked_strtol(buf, &buf);
-
-		// Read the name of the nondeterministic choice.
-		choice = checked_strtol(buf, &buf);
-
-		// Check if we encountered a state index that is bigger than all previously seen.
-		if (source > maxnode) {
-			maxnode = source;
+		NondeterministicSparseTransitionParser::Result NondeterministicSparseTransitionParser::parseNondeterministicTransitions(std::string const& filename) {
+
+			RewardMatrixInformationStruct nullInformation;
+
+			return NondeterministicSparseTransitionParser::parse(filename, false, nullInformation);
 		}
 
-		if (isRewardFile) {
-			// If we have switched the source state, we possibly need to insert the rows of the last
-			// last source state.
-			if (source != lastsource && lastsource != -1) {
-				choices += lastchoice - ((*rewardMatrixInformation->nondeterministicChoiceIndices)[lastsource + 1] - (*rewardMatrixInformation->nondeterministicChoiceIndices)[lastsource] - 1);
-			}
+		NondeterministicSparseTransitionParser::Result NondeterministicSparseTransitionParser::parseNondeterministicTransitionRewards(std::string const& filename, RewardMatrixInformationStruct const& rewardMatrixInformation) {
 
-			// If we skipped some states, we need to reserve empty rows for all their nondeterministic
-			// choices.
-			for (int_fast64_t i = lastsource + 1; i < source; ++i) {
-				choices += ((*rewardMatrixInformation->nondeterministicChoiceIndices)[i + 1] - (*rewardMatrixInformation->nondeterministicChoiceIndices)[i]);
-			}
+			return NondeterministicSparseTransitionParser::parse(filename, true, rewardMatrixInformation);
+		}
 
-			// If we advanced to the next state, but skipped some choices, we have to reserve rows
-			// for them
-			if (source != lastsource) {
-				choices += choice + 1;
-			} else if (choice != lastchoice) {
-				choices += choice - lastchoice;
-			}
-		} else {
-			// If we have skipped some states, we need to reserve the space for the self-loop insertion
-			// in the second pass.
-			if (source > lastsource + 1) {
-				nonzero += source - lastsource - 1;
-				choices += source - lastsource - 1;
-			} else if (source != lastsource || choice != lastchoice) {
-				// If we have switched the source state or the nondeterministic choice, we need to
-				// reserve one row more.
-				++choices;
+		NondeterministicSparseTransitionParser::FirstPassResult NondeterministicSparseTransitionParser::firstPass(char* buf, SupportedLineEndingsEnum lineEndings, bool isRewardFile, RewardMatrixInformationStruct const& rewardMatrixInformation) {
+
+			// Check file header and extract number of transitions.
+
+			// Skip the format hint if it is there.
+			buf = trimWhitespaces(buf);
+			if(buf[0] < '0' || buf[0] > '9') {
+				buf = storm::parser::forwardToNextLine(buf, lineEndings);
 			}
-		}
 
-		// Read target and check if we encountered a state index that is bigger than all previously
-		// seen.
-		target = checked_strtol(buf, &buf);
-		if (target > maxnode) {
-			maxnode = target;
-		}
+			// Read all transitions.
+			uint_fast64_t source = 0, target = 0, choice = 0, lastchoice = 0, lastsource = 0;
+			double val = 0.0;
+			NondeterministicSparseTransitionParser::FirstPassResult result;
 
-		// Read value and check whether it's positive.
-		val = checked_strtod(buf, &buf);
-		if ((val < 0.0) || (val > 1.0)) {
-			LOG4CPLUS_ERROR(logger, "Expected a positive probability but got \"" << std::string(buf, 0, 16) << "\".");
-			return 0;
-		}
+			// Since the first line is already a new choice but is not covered below, that has to be covered here.
+			result.choices = 1;
 
-		lastchoice = choice;
-		lastsource = source;
-
-		/*
-		 *	Increase number of non-zero values.
-		 */
-		nonzero++;
-
-		// The PRISM output format lists the name of the transition in the fourth column,
-		// but omits the fourth column if it is an internal action. In either case, however, the third column
-		// is followed by a space. We need to skip over that space first (instead of trimming whitespaces),
-		// before we can skip to the line end, because trimming the white spaces will proceed to the next line
-		// in case there is no action label in the fourth column.
-		if (buf[0] == ' ') {
-			++buf;
-		}
+			while (buf[0] != '\0') {
 
-		/*
-		 *	Proceed to beginning of next line.
-		 */
-		switch (lineEndings) {
-			case SupportedLineEndingsEnum::SlashN:
-				buf += strcspn(buf, " \t\n");
-				break;
-			case SupportedLineEndingsEnum::SlashR:
-				buf += strcspn(buf, " \t\r");
-				break;
-			case SupportedLineEndingsEnum::SlashRN:
-				buf += strcspn(buf, " \t\r\n");
-				break;
-			default:
-			case storm::parser::SupportedLineEndingsEnum::Unsupported:
-				// This Line will never be reached as the Parser would have thrown already.
-				throw;
-				break;
-		}
-		buf = trimWhitespaces(buf);
-	}
+				// Read source state and choice.
+				source = checked_strtol(buf, &buf);
 
-	if (isRewardFile) {
-		// If not all rows were filled for the last state, we need to insert them.
-		choices += lastchoice - ((*rewardMatrixInformation->nondeterministicChoiceIndices)[lastsource + 1] - (*rewardMatrixInformation->nondeterministicChoiceIndices)[lastsource] - 1);
+				// Read the name of the nondeterministic choice.
+				choice = checked_strtol(buf, &buf);
 
-		// If we skipped some states, we need to reserve empty rows for all their nondeterministic
-		// choices.
-		for (uint_fast64_t i = lastsource + 1; i < rewardMatrixInformation->nondeterministicChoiceIndices->size() - 1; ++i) {
-			choices += ((*rewardMatrixInformation->nondeterministicChoiceIndices)[i + 1] - (*rewardMatrixInformation->nondeterministicChoiceIndices)[i]);
-		}
-	}
+				// Check if we encountered a state index that is bigger than all previously seen.
+				if (source > result.highestStateIndex) {
+					result.highestStateIndex = source;
+				}
 
-	return nonzero;
-}
+				if (isRewardFile) {
+					// If we have switched the source state, we possibly need to insert rows for skipped choices of the last
+					// source state.
+					if (source != lastsource) {
+						// number of choices skipped = number of choices of last state - number of choices read
+						result.choices += ((*rewardMatrixInformation.nondeterministicChoiceIndices)[lastsource + 1] - (*rewardMatrixInformation.nondeterministicChoiceIndices)[lastsource]) - (lastchoice + 1);
+					}
+
+					// If we skipped some states, we need to reserve empty rows for all their nondeterministic
+					// choices.
+					for (uint_fast64_t i = lastsource + 1; i < source; ++i) {
+						result.choices += ((*rewardMatrixInformation.nondeterministicChoiceIndices)[i + 1] - (*rewardMatrixInformation.nondeterministicChoiceIndices)[i]);
+					}
+
+					// If we advanced to the next state, but skipped some choices, we have to reserve rows
+					// for them.
+					if (source != lastsource) {
+						result.choices += choice + 1;
+					} else if (choice != lastchoice) {
+						result.choices += choice - lastchoice;
+					}
+				} else {
 
+					// If we have skipped some states, we need to reserve the space for the self-loop insertion
+					// in the second pass.
+					if (source > lastsource + 1) {
+						result.numberOfNonzeroEntries += source - lastsource - 1;
+						result.choices += source - lastsource - 1;
+					} else if (source != lastsource || choice != lastchoice) {
+						// If we have switched the source state or the nondeterministic choice, we need to
+						// reserve one row more.
+						++result.choices;
+					}
+				}
 
+				// Read target and check if we encountered a state index that is bigger than all previously
+				// seen.
+				target = checked_strtol(buf, &buf);
+				if (target > result.highestStateIndex) {
+					result.highestStateIndex = target;
+				}
 
-/*!
- *	Reads a .tra file and produces a sparse matrix representing the described Markov Chain.
- *
- *	Matrices created with this method have to be freed with the delete operator.
- *	@param filename input .tra file's name.
- *	@return a pointer to the created sparse matrix.
- */
+				// Read value and check whether it's positive.
+				val = checked_strtod(buf, &buf);
+				if ((val < 0.0) || (val > 1.0)) {
+					LOG4CPLUS_ERROR(logger, "Expected a positive probability but got \"" << std::string(buf, 0, 16) << "\".");
+					NondeterministicSparseTransitionParser::FirstPassResult nullResult;
+					return nullResult;
+				}
 
-NondeterministicSparseTransitionParserResult_t NondeterministicSparseTransitionParser(std::string const &filename, RewardMatrixInformationStruct* rewardMatrixInformation) {
-	/*
-	 *	Enforce locale where decimal point is '.'.
-	 */
-	setlocale(LC_NUMERIC, "C");
-
-	if (!fileExistsAndIsReadable(filename.c_str())) {
-		LOG4CPLUS_ERROR(logger, "Error while parsing " << filename << ": File does not exist or is not readable.");
-		throw storm::exceptions::WrongFormatException();
-	}
-
-	bool isRewardFile = rewardMatrixInformation != nullptr;
-
-	/*
-	 *	Find out about the used line endings.
-	 */
-	SupportedLineEndingsEnum lineEndings = findUsedLineEndings(filename, true);
-
-	/*
-	 *	Open file.
-	 */
-	MappedFile file(filename.c_str());
-	char* buf = file.data;
-
-	/*
-	 *	Perform first pass, i.e. obtain number of columns, rows and non-zero elements.
-	 */
-	int_fast64_t maxnode;
-	uint_fast64_t choices;
-	uint_fast64_t nonzero = firstPass(file.data, lineEndings, choices, maxnode, rewardMatrixInformation);
-
-	/*
-	 *	If first pass returned zero, the file format was wrong.
-	 */
-	if (nonzero == 0) {
-		LOG4CPLUS_ERROR(logger, "Error while parsing " << filename << ": erroneous file format.");
-		throw storm::exceptions::WrongFormatException();
-	}
-
-	/*
-	 *	Perform second pass.
-	 *	
-	 *	From here on, we already know that the file header is correct.
-	 */
-
-	/*
-	 *	Skip file header.
-	 */
-	if (!isRewardFile) {
-		// skip format hint
-		buf = storm::parser::forwardToNextLine(buf, lineEndings);
-	}
-
-	if (isRewardFile) {
-		if (choices > rewardMatrixInformation->rowCount || (uint_fast64_t)(maxnode + 1) > rewardMatrixInformation->columnCount) {
-			LOG4CPLUS_ERROR(logger, "Reward matrix size exceeds transition matrix size.");
-			throw storm::exceptions::WrongFormatException() << "Reward matrix size exceeds transition matrix size.";
-		} else if (choices != rewardMatrixInformation->rowCount) {
-			LOG4CPLUS_ERROR(logger, "Reward matrix row count does not match transition matrix row count.");
-			throw storm::exceptions::WrongFormatException() << "Reward matrix row count does not match transition matrix row count.";
-		} else {
-			maxnode = rewardMatrixInformation->columnCount - 1;
-		}
-	}
-
-	/*
-	 *	Create and initialize matrix.
-	 *	The matrix should have as many columns as we have nodes and as many rows as we have choices.
-	 *	Those two values, as well as the number of nonzero elements, was been calculated in the first run.
-	 */
-	LOG4CPLUS_INFO(logger, "Attempting to create matrix of size " << choices << " x " << (maxnode+1) << " with " << nonzero << " entries.");
-	storm::storage::SparseMatrixBuilder<double> matrixBuilder(choices, maxnode + 1, nonzero);
-
-	/*
-	 *	Create row mapping.
-	 */
-	std::vector<uint_fast64_t> rowMapping(maxnode + 2, 0);
-
-	/*
-	 *	Parse file content.
-	 */
-	int_fast64_t source, target, lastsource = -1, choice, lastchoice = -1;
-	uint_fast64_t curRow = -1;
-	double val;
-	bool fixDeadlocks = storm::settings::Settings::getInstance()->isSet("fixDeadlocks");
-	bool hadDeadlocks = false;
-
-	/*
-	 *	Read all transitions from file.
-	 */
-	while (buf[0] != '\0') {
-		/*
-		 *	Read source state and choice.
-		 */
-		source = checked_strtol(buf, &buf);
-		choice = checked_strtol(buf, &buf);
-
-		if (isRewardFile) {
-			// If we have switched the source state, we possibly need to insert the rows of the last
-			// last source state.
-			if (source != lastsource && lastsource != -1) {
-				curRow += lastchoice - ((*rewardMatrixInformation->nondeterministicChoiceIndices)[lastsource + 1] - (*rewardMatrixInformation->nondeterministicChoiceIndices)[lastsource] - 1);
+				lastchoice = choice;
+				lastsource = source;
+
+				// Increase number of non-zero values.
+				result.numberOfNonzeroEntries++;
+
+				// The PRISM output format lists the name of the transition in the fourth column,
+				// but omits the fourth column if it is an internal action. In either case we can skip to the end of the line.
+				buf = forwardToLineEnd(buf, lineEndings);
+
+				buf = trimWhitespaces(buf);
 			}
 
-			// If we skipped some states, we need to reserve empty rows for all their nondeterministic
-			// choices.
-			for (int_fast64_t i = lastsource + 1; i < source; ++i) {
-				curRow += ((*rewardMatrixInformation->nondeterministicChoiceIndices)[i + 1] - (*rewardMatrixInformation->nondeterministicChoiceIndices)[i]);
+			if (isRewardFile) {
+				// If not all rows were filled for the last state, we need to insert them.
+				result.choices += ((*rewardMatrixInformation.nondeterministicChoiceIndices)[lastsource + 1] - (*rewardMatrixInformation.nondeterministicChoiceIndices)[lastsource] ) - (lastchoice + 1);
+
+				// If we skipped some states, we need to reserve empty rows for all their nondeterministic
+				// choices.
+				for (uint_fast64_t i = lastsource + 1; i < rewardMatrixInformation.nondeterministicChoiceIndices->size() - 1; ++i) {
+					result.choices += ((*rewardMatrixInformation.nondeterministicChoiceIndices)[i + 1] - (*rewardMatrixInformation.nondeterministicChoiceIndices)[i]);
+				}
 			}
 
-			// If we advanced to the next state, but skipped some choices, we have to reserve rows
-			// for them
-			if (source != lastsource) {
-				curRow += choice + 1;
-			} else if (choice != lastchoice) {
-				curRow += choice - lastchoice;
+			return result;
+		}
+
+		NondeterministicSparseTransitionParser::Result NondeterministicSparseTransitionParser::parse(std::string const &filename, bool isRewardFile, RewardMatrixInformationStruct const& rewardMatrixInformation) {
+
+			// Enforce locale where decimal point is '.'.
+			setlocale(LC_NUMERIC, "C");
+
+			if (!fileExistsAndIsReadable(filename.c_str())) {
+				LOG4CPLUS_ERROR(logger, "Error while parsing " << filename << ": File does not exist or is not readable.");
+				throw storm::exceptions::WrongFormatException();
 			}
-		} else {
-			// Increase line count if we have either finished reading the transitions of a certain state
-			// or we have finished reading one nondeterministic choice of a state.
-			if ((source != lastsource || choice != lastchoice)) {
-				++curRow;
+
+			// Find out about the used line endings.
+			SupportedLineEndingsEnum lineEndings = findUsedLineEndings(filename, true);
+
+			// Open file.
+			MappedFile file(filename.c_str());
+			char* buf = file.data;
+
+			// Perform first pass, i.e. obtain number of columns, rows and non-zero elements.
+			NondeterministicSparseTransitionParser::FirstPassResult firstPass = NondeterministicSparseTransitionParser::firstPass(file.data, lineEndings, isRewardFile, rewardMatrixInformation);
+
+			// If first pass returned zero, the file format was wrong.
+			if (firstPass.numberOfNonzeroEntries == 0) {
+				LOG4CPLUS_ERROR(logger, "Error while parsing " << filename << ": erroneous file format.");
+				throw storm::exceptions::WrongFormatException();
 			}
-			/*
-			 *	Check if we have skipped any source node, i.e. if any node has no
-			 *	outgoing transitions. If so, insert a self-loop.
-			 *	Also add self-loops to rowMapping.
-			 */
-			for (int_fast64_t node = lastsource + 1; node < source; node++) {
-				hadDeadlocks = true;
-				if (fixDeadlocks) {
-					rowMapping.at(node) = curRow;
-					matrixBuilder.addNextValue(curRow, node, 1);
-					++curRow;
-					LOG4CPLUS_WARN(logger, "Warning while parsing " << filename << ": node " << node << " has no outgoing transitions. A self-loop was inserted.");
+
+			// Perform second pass.
+
+			// Skip the format hint if it is there.
+			buf = trimWhitespaces(buf);
+			if(buf[0] < '0' || buf[0] > '9') {
+				buf = storm::parser::forwardToNextLine(buf, lineEndings);
+			}
+
+			if (isRewardFile) {
+				// The reward matrix should match the size of the transition matrix.
+				if (firstPass.choices > rewardMatrixInformation.rowCount || (uint_fast64_t)(firstPass.highestStateIndex + 1) > rewardMatrixInformation.columnCount) {
+					LOG4CPLUS_ERROR(logger, "Reward matrix size exceeds transition matrix size.");
+					throw storm::exceptions::WrongFormatException() << "Reward matrix size exceeds transition matrix size.";
+				} else if (firstPass.choices != rewardMatrixInformation.rowCount) {
+					LOG4CPLUS_ERROR(logger, "Reward matrix row count does not match transition matrix row count.");
+					throw storm::exceptions::WrongFormatException() << "Reward matrix row count does not match transition matrix row count.";
 				} else {
-					LOG4CPLUS_ERROR(logger, "Error while parsing " << filename << ": node " << node << " has no outgoing transitions.");
+					firstPass.highestStateIndex = rewardMatrixInformation.columnCount - 1;
 				}
 			}
-			if (source != lastsource) {
-				/*
-				 *	Add this source to rowMapping, if this is the first choice we encounter for this state.
-				 */
-				rowMapping.at(source) = curRow;
-			}
-		}
 
-		// Read target and value and write it to the matrix.
-		target = checked_strtol(buf, &buf);
-		val = checked_strtod(buf, &buf);
-		matrixBuilder.addNextValue(curRow, target, val);
 
-		lastsource = source;
-		lastchoice = choice;
+			// Create the matrix builder.
+			// The matrix to be build should have as many columns as we have nodes and as many rows as we have choices.
+			// Those two values, as well as the number of nonzero elements, was been calculated in the first run.
+			LOG4CPLUS_INFO(logger, "Attempting to create matrix of size " << firstPass.choices << " x " << (firstPass.highestStateIndex+1) << " with " << firstPass.numberOfNonzeroEntries << " entries.");
+			storm::storage::SparseMatrixBuilder<double> matrixBuilder(firstPass.choices, firstPass.highestStateIndex + 1, firstPass.numberOfNonzeroEntries);
+
+			// Create row mapping.
+			std::vector<uint_fast64_t> rowMapping(firstPass.highestStateIndex + 2, 0);
+
+			// Initialize variables for the parsing run.
+			uint_fast64_t source = 0, target = 0, lastsource = 0, choice = 0, lastchoice = 0, curRow = 0;
+			double val = 0.0;
+			bool fixDeadlocks = storm::settings::Settings::getInstance()->isSet("fixDeadlocks");
+			bool hadDeadlocks = false;
+
+			// Read all transitions from file.
+			while (buf[0] != '\0') {
+
+				// Read source state and choice.
+				source = checked_strtol(buf, &buf);
+				choice = checked_strtol(buf, &buf);
+
+				if (isRewardFile) {
+					// If we have switched the source state, we possibly need to insert the rows of the last
+					// source state.
+					if (source != lastsource) {
+						curRow += ((*rewardMatrixInformation.nondeterministicChoiceIndices)[lastsource + 1] - (*rewardMatrixInformation.nondeterministicChoiceIndices)[lastsource]) -(lastchoice + 1);
+					}
+
+					// If we skipped some states, we need to reserve empty rows for all their nondeterministic
+					// choices.
+					for (uint_fast64_t i = lastsource + 1; i < source; ++i) {
+						curRow += ((*rewardMatrixInformation.nondeterministicChoiceIndices)[i + 1] - (*rewardMatrixInformation.nondeterministicChoiceIndices)[i]);
+					}
+
+					// If we advanced to the next state, but skipped some choices, we have to reserve rows
+					// for them
+					if (source != lastsource) {
+						curRow += choice + 1;
+					} else if (choice != lastchoice) {
+						curRow += choice - lastchoice;
+					}
+				} else {
+					// Increase line count if we have either finished reading the transitions of a certain state
+					// or we have finished reading one nondeterministic choice of a state.
+					if ((source != lastsource || choice != lastchoice)) {
+						++curRow;
+					}
+					// Check if we have skipped any source node, i.e. if any node has no
+					// outgoing transitions. If so, insert a self-loop.
+					// Also add self-loops to rowMapping.
+					for (uint_fast64_t node = lastsource + 1; node < source; node++) {
+						hadDeadlocks = true;
+						if (fixDeadlocks) {
+							rowMapping.at(node) = curRow;
+							matrixBuilder.addNextValue(curRow, node, 1);
+							++curRow;
+							LOG4CPLUS_WARN(logger, "Warning while parsing " << filename << ": node " << node << " has no outgoing transitions. A self-loop was inserted.");
+						} else {
+							LOG4CPLUS_ERROR(logger, "Error while parsing " << filename << ": node " << node << " has no outgoing transitions.");
+						}
+					}
+					if (source != lastsource) {
+						// Add this source to rowMapping, if this is the first choice we encounter for this state.
+						rowMapping.at(source) = curRow;
+					}
+				}
 
-		/*
-		 *	Proceed to beginning of next line in file and next row in matrix.
-		 */
-		if (buf[0] == ' ') {
-			++buf;
-		}
-		switch (lineEndings) {
-			case SupportedLineEndingsEnum::SlashN:
-				buf += strcspn(buf, " \t\n");
-				break;
-			case SupportedLineEndingsEnum::SlashR:
-				buf += strcspn(buf, " \t\r");
-				break;
-			case SupportedLineEndingsEnum::SlashRN:
-				buf += strcspn(buf, " \t\r\n");
-				break;
-			default:
-			case storm::parser::SupportedLineEndingsEnum::Unsupported:
-				// This Line will never be reached as the Parser would have thrown already.
-				throw;
-				break;
-		}
-		buf = trimWhitespaces(buf);
-	}
+				// Read target and value and write it to the matrix.
+				target = checked_strtol(buf, &buf);
+				val = checked_strtod(buf, &buf);
+				matrixBuilder.addNextValue(curRow, target, val);
+
+				lastsource = source;
+				lastchoice = choice;
 
-	for (int_fast64_t node = lastsource + 1; node <= maxnode + 1; node++) {
-		rowMapping.at(node) = curRow + 1;
-	}
+				// Proceed to beginning of next line in file and next row in matrix.
+				buf = forwardToLineEnd(buf, lineEndings);
 
-	if (!fixDeadlocks && hadDeadlocks && !isRewardFile) throw storm::exceptions::WrongFormatException() << "Some of the nodes had deadlocks. You can use --fixDeadlocks to insert self-loops on the fly.";
+				buf = trimWhitespaces(buf);
+			}
 
-	return std::make_pair(matrixBuilder.build(), std::move(rowMapping));
-}
+			for (uint_fast64_t node = lastsource + 1; node <= firstPass.highestStateIndex + 1; node++) {
+				rowMapping.at(node) = curRow + 1;
+			}
+
+			if (!fixDeadlocks && hadDeadlocks && !isRewardFile) throw storm::exceptions::WrongFormatException() << "Some of the nodes had deadlocks. You can use --fixDeadlocks to insert self-loops on the fly.";
+
+			return NondeterministicSparseTransitionParser::Result(matrixBuilder.build(), rowMapping);
+		}
 
-}  // namespace parser
+	}  // namespace parser
 }  // namespace storm
diff --git a/src/parser/NondeterministicSparseTransitionParser.h b/src/parser/NondeterministicSparseTransitionParser.h
index 900bc088e..34fc3f397 100644
--- a/src/parser/NondeterministicSparseTransitionParser.h
+++ b/src/parser/NondeterministicSparseTransitionParser.h
@@ -1,30 +1,101 @@
-#ifndef STORM_PARSER_NONDETTRAPARSER_H_
-#define STORM_PARSER_NONDETTRAPARSER_H_
-
-#include "src/storage/SparseMatrix.h"
+#ifndef STORM_PARSER_NONDETERMINISTICSPARSETRANSITIONPARSER_H_
+#define STORM_PARSER_NONDETERMINISTICSPARSETRANSITIONPARSER_H_
 
 #include "src/parser/Parser.h"
-#include "src/utility/OsDetection.h"
+#include "src/storage/SparseMatrix.h"
 
-#include <utility>
-#include <memory>
 #include <vector>
 
 namespace storm {
-namespace parser {
+	namespace parser {
+
+		class NondeterministicSparseTransitionParser {
+
+		public:
+
+			/*
+			 * A structure representing the result of the first pass of this parser.
+			 * It contains the number of non-zero entries in the model, the highest state index and the total number if nondeterministic choices.
+			 */
+			struct FirstPassResult {
+
+				FirstPassResult() : numberOfNonzeroEntries(0), highestStateIndex(0), choices(0) {
+					// Intentionally left empty.
+				}
+
+				// The total number of non-zero entries of the model.
+				uint_fast64_t numberOfNonzeroEntries;
+
+				// The highest state index that appears in the model.
+				uint_fast64_t highestStateIndex;
+
+				// The total number of nondeterministic choices within the transition system.
+				uint_fast64_t choices;
+			};
+
+			/*!
+			 * A structure representing the result of the parser.
+			 * It contains the resulting matrix as well as the row mapping.
+			 */
+			struct Result {
+
+				Result(storm::storage::SparseMatrix<double> transitionMatrix, std::vector<uint_fast64_t> rowMapping) : transitionMatrix(transitionMatrix), rowMapping(rowMapping) {
+					// Intentionally left empty.
+				}
+
+				// The matrix containing the parsed transition system.
+				storm::storage::SparseMatrix<double> transitionMatrix;
+
+				// A mapping from rows of the matrix to states of the model.
+				// This resolves the nondeterministic choices inside the transition system.
+				std::vector<uint_fast64_t> rowMapping;
+			};
+
+			/*!
+			 *	@brief	Load a nondeterministic transition system from file and create a
+			 *	sparse adjacency matrix whose entries represent the weights of the edges
+			 */
+			static Result parseNondeterministicTransitions(std::string const &filename);
+
+			/*!
+			 *	@brief	Load a nondeterministic transition system from file and create a
+			 *	sparse adjacency matrix whose entries represent the weights of the edges
+			 */
+			static Result parseNondeterministicTransitionRewards(std::string const &filename, RewardMatrixInformationStruct const& rewardMatrixInformation);
+
+		private:
+
+			/*!
+			 * This method does the first pass through the buffer containing the content of some transition file.
+			 *
+			 * It computes the overall number of nondeterministic choices, i.e. the
+			 * number of rows in the matrix that should be created.
+			 * It also calculates the overall number of non-zero cells, i.e. the number
+			 * of elements the matrix has to hold, and the maximum node id, i.e. the
+			 * number of columns of the matrix.
+			 *
+			 * @param buffer Buffer containing the data to scan. This is expected to be some char array.
+			 * @param lineEndings The line endings that are to be used while parsing.
+			 * @param insertDiagonalEntriesIfMissing A flag set iff entries on the primary diagonal of the matrix should be added in case they are missing in the parsed file.
+			 * @return A structure representing the result of the first pass.
+			 */
+			static FirstPassResult firstPass(char* buffer, SupportedLineEndingsEnum lineEndings, bool isRewardFile, RewardMatrixInformationStruct const& rewardMatrixInformation);
+
+			/*!
+			 * The main parsing routine.
+			 * Opens the given file, calls the first pass and performs the second pass, parsing the content of the file into a SparseMatrix.
+			 *
+			 * @param filename The path of file to be parsed.
+			 * @param rewardFile A flag set iff the file to be parsed contains transition rewards.
+			 * @param insertDiagonalEntriesIfMissing A flag set iff entries on the primary diagonal of the matrix should be added in case they are missing in the parsed file.
+			 * @param rewardMatrixInformation A struct containing information that is used to check if the transition reward matrix fits to the rest of the model.
+			 * @return A SparseMatrix containing the parsed file contents.
+			 */
+			static Result parse(std::string const& filename, bool isRewardFile, RewardMatrixInformationStruct const& rewardMatrixInformation);
+
+		};
 	
-/*! 
- * @brief Contains the Result of a call to the NondeterministicSparseTransitionParser function. The first part is the resulting matrix. The second part is the row mapping.
- */
-typedef std::pair<storm::storage::SparseMatrix<double>, std::vector<uint_fast64_t>> NondeterministicSparseTransitionParserResult_t;
-
-/*!
- *	@brief	Load a nondeterministic transition system from file and create a
- *	sparse adjacency matrix whose entries represent the weights of the edges
- */
-NondeterministicSparseTransitionParserResult_t NondeterministicSparseTransitionParser(std::string const &filename, RewardMatrixInformationStruct* rewardMatrixInformation = nullptr);
-
-} // namespace parser
+	} // namespace parser
 } // namespace storm
 
-#endif /* STORM_PARSER_NONDETTRAPARSER_H_ */
+#endif /* STORM_PARSER_NONDETERMINISTICSPARSETRANSITIONPARSER_H__H_ */
diff --git a/src/parser/Parser.cpp b/src/parser/Parser.cpp
index 6fb26ef4b..b1b0c6e79 100644
--- a/src/parser/Parser.cpp
+++ b/src/parser/Parser.cpp
@@ -117,6 +117,29 @@ SupportedLineEndingsEnum findUsedLineEndings(std::string const& fileName, bool t
 	return SupportedLineEndingsEnum::Unsupported;
 }
 
+/*!
+ * @brief Encapsulates the usage of function @strcspn to forward to the end of the line (next char is the newline character).
+ */
+char* forwardToLineEnd(char* buffer, SupportedLineEndingsEnum lineEndings) {
+	switch (lineEndings) {
+		case SupportedLineEndingsEnum::SlashN:
+			return buffer + strcspn(buffer, "\n\0");
+			break;
+		case SupportedLineEndingsEnum::SlashR:
+			return buffer + strcspn(buffer, "\r\0");
+			break;
+		case SupportedLineEndingsEnum::SlashRN:
+			return buffer + strcspn(buffer, "\r\0");
+			break;
+		default:
+		case SupportedLineEndingsEnum::Unsupported:
+			// This Line will never be reached as the Parser would have thrown already.
+			throw;
+			break;
+	}
+	return nullptr;
+}
+
 /*!
  * @brief Encapsulates the usage of function @strchr to forward to the next line
  */
diff --git a/src/parser/Parser.h b/src/parser/Parser.h
index e7fcf4dab..b2cfb0677 100644
--- a/src/parser/Parser.h
+++ b/src/parser/Parser.h
@@ -146,6 +146,11 @@ enum class SupportedLineEndingsEnum : unsigned short {
  */
 storm::parser::SupportedLineEndingsEnum findUsedLineEndings(std::string const& fileName, bool throwOnUnsupported = false);
 
+/*!
+ * @brief Encapsulates the usage of function @strcspn to forward to the end of the line (next char is the newline character).
+ */
+char* forwardToLineEnd(char* buffer, storm::parser::SupportedLineEndingsEnum lineEndings);
+
 /*!
  * @brief Encapsulates the usage of function @strchr to forward to the next line
  */