Browse Source

Second part of the refactoring of Parser.cpp/.h

- Eliminated the need for SupportedLineEndings (I hope...should work on all os, but have only tested this on linux)
- Moved fileExistsAndIsReadable to MappedFile
- Removed scanForModelHint and replaced it with its contents at the one point where is was used in the AutoParser
- Moved and renamed remaining part of Parser.cpp/.h to src/utility/cstring.cpp/.h
|- New namespace of the cstring manipulation functions is storm::utility::cstring
|- Used a using namespace storm::utility::cstring to eliminate the full namespace specification within the needing parsers. This keeps the code readable.
- Threw out some unnessesary includes.

Next up: Commenting and making things look nice.


Former-commit-id: c983d1e1a2
tempestpy_adaptions
masawei 11 years ago
parent
commit
fe7afc727f
  1. 35
      src/parser/AtomicPropositionLabelingParser.cpp
  2. 19
      src/parser/AutoParser.cpp
  3. 8
      src/parser/AutoParser.h
  4. 2
      src/parser/CslParser.h
  5. 1
      src/parser/DeterministicModelParser.h
  6. 18
      src/parser/DeterministicSparseTransitionParser.cpp
  7. 4
      src/parser/DeterministicSparseTransitionParser.h
  8. 1
      src/parser/LtlParser.h
  9. 8
      src/parser/MappedFile.cpp
  10. 6
      src/parser/MappedFile.h
  11. 38
      src/parser/MarkovAutomatonSparseTransitionParser.cpp
  12. 7
      src/parser/MarkovAutomatonSparseTransitionParser.h
  13. 1
      src/parser/NondeterministicModelParser.h
  14. 23
      src/parser/NondeterministicSparseTransitionParser.cpp
  15. 4
      src/parser/NondeterministicSparseTransitionParser.h
  16. 253
      src/parser/Parser.cpp
  17. 93
      src/parser/Parser.h
  18. 2
      src/parser/PrctlParser.h
  19. 6
      src/parser/SparseStateRewardParser.cpp
  20. 95
      src/utility/cstring.cpp
  21. 53
      src/utility/cstring.h
  22. 2
      test/functional/parser/MarkovAutomatonParserTest.cpp

35
src/parser/AtomicPropositionLabelingParser.cpp

@ -11,7 +11,7 @@
#include <string>
#include <iostream>
#include "src/parser/Parser.h"
#include "src/utility/cstring.h"
#include "src/parser/MappedFile.h"
#include "src/exceptions/WrongFormatException.h"
#include "src/exceptions/FileIoException.h"
@ -23,25 +23,20 @@ extern log4cplus::Logger logger;
namespace storm {
namespace parser {
using namespace storm::utility::cstring;
storm::models::AtomicPropositionsLabeling AtomicPropositionLabelingParser::parseAtomicPropositionLabeling(uint_fast64_t node_count, std::string const & filename) {
// Open the given file.
if (!storm::parser::fileExistsAndIsReadable(filename.c_str())) {
if (!MappedFile::fileExistsAndIsReadable(filename.c_str())) {
LOG4CPLUS_ERROR(logger, "Error while parsing " << filename << ": File does not exist or is not readable.");
throw storm::exceptions::FileIoException() << "The supplied Labeling input file \"" << filename << "\" does not exist or is not readable by this process.";
}
// Find out about the used line endings.
SupportedLineEndings lineEndings = findUsedLineEndings(filename, true);
MappedFile file(filename.c_str());
char* buf = file.data;
// First pass: Count the number of propositions.
// Convert the line endings into a string containing all whitespace characters, that separate words in the file.
char separator[5];
storm::parser::getMatchingSeparatorString(separator, sizeof(separator), lineEndings);
bool foundDecl = false, foundEnd = false;
uint_fast32_t proposition_count = 0;
size_t cnt = 0;
@ -49,11 +44,12 @@ namespace storm {
// Iterate over tokens until we hit #END or the end of the file.
while(buf[0] != '\0') {
// Move the buffer pointer to the separator.
//Move the buffer to the beginning of the next word.
buf += cnt;
buf = trimWhitespaces(buf);
// Get the number of characters until the next separator.
cnt = strcspn(buf, separator);
cnt = skipWord(buf) - buf;
if (cnt > 0) {
// If the next token is #DECLARATION: Just skip it.
@ -67,10 +63,6 @@ namespace storm {
break;
}
proposition_count++;
} else {
// If the next character is a separator, skip it.
buf++;
}
}
@ -98,11 +90,12 @@ namespace storm {
// As we already checked the file header, we know that #DECLARATION and #END are tokens in the character stream.
while(buf[0] != '\0') {
// Move the buffer pointer to the separator.
//Move the buffer to the beginning of the next word.
buf += cnt;
buf = trimWhitespaces(buf);
// The number of characters until the next separator.
cnt = strcspn(buf, separator);
// Get the number of characters until the next separator.
cnt = skipWord(buf) - buf;
if (cnt >= sizeof(proposition)) {
@ -122,10 +115,6 @@ namespace storm {
strncpy(proposition, buf, cnt);
proposition[cnt] = '\0';
labeling.addAtomicProposition(proposition);
} else {
// The next character is a separator, thus move one step forward.
buf++;
}
}
@ -143,7 +132,7 @@ namespace storm {
// Stop at the end of the line.
node = checked_strtol(buf, &buf);
while ((buf[0] != '\r') && (buf[0] != '\n') && (buf[0] != '\0')) {
cnt = strcspn(buf, separator);
cnt = skipWord(buf) - buf;
if (cnt == 0) {
// The next character is a separator.

19
src/parser/AutoParser.cpp

@ -7,7 +7,6 @@
#include "src/parser/AutoParser.h"
#include "src/parser/Parser.h"
#include "src/parser/MappedFile.h"
#include "src/parser/DeterministicModelParser.h"
@ -15,9 +14,14 @@
#include "src/parser/MarkovAutomatonParser.h"
#include "src/exceptions/WrongFormatException.h"
#include "src/utility/cstring.h"
#include "src/utility/OsDetection.h"
namespace storm {
namespace parser {
using namespace storm::utility::cstring;
std::shared_ptr<storm::models::AbstractModel<double>> AutoParser::parseModel(std::string const & transitionSystemFile,
std::string const & labelingFile,
std::string const & stateRewardFile,
@ -68,17 +72,18 @@ namespace storm {
storm::models::ModelType AutoParser::analyzeHint(const std::string& filename) {
storm::models::ModelType hintType = storm::models::Unknown;
// Find out the line endings used within the file.
storm::parser::SupportedLineEndings lineEndings = storm::parser::findUsedLineEndings(filename);
// Open the file.
MappedFile file(filename.c_str());
char* buf = file.data;
// Find and read in the hint.
char hint[128];
// %20s => The input hint can be AT MOST 120 chars long.
storm::parser::scanForModelHint(hint, sizeof(hint), buf, lineEndings);
char hint[65];
// %60s => The input hint can be AT MOST 60 chars long.
#ifdef WINDOWS
sscanf_s(buf, "%60s", hint, sizeof(hint));
#else
sscanf(buf, "%60s", hint);
#endif
for (char* c = hint; *c != '\0'; c++) *c = toupper(*c);

8
src/parser/AutoParser.h

@ -6,6 +6,14 @@
#include <string>
namespace storm {
/*!
* @brief Contains all file parsers and helper classes.
*
* This namespace contains everything needed to load data files (like
* atomic propositions, transition systems, formulas, etc.) including
* methods for efficient file access (see MappedFile).
*/
namespace parser {
class AutoParser {

2
src/parser/CslParser.h

@ -8,8 +8,6 @@
#ifndef STORM_PARSER_CSLPARSER_H_
#define STORM_PARSER_CSLPARSER_H_
#include "Parser.h"
#include "src/formula/Csl.h"
#include <functional>

1
src/parser/DeterministicModelParser.h

@ -8,7 +8,6 @@
#ifndef STORM_PARSER_DETERMINISTICMODELPARSER_H_
#define STORM_PARSER_DETERMINISTICMODELPARSER_H_
#include "src/parser/Parser.h"
#include "src/models/Dtmc.h"
#include "src/models/Ctmc.h"

18
src/parser/DeterministicSparseTransitionParser.cpp

@ -15,6 +15,7 @@
#include <string>
#include "src/utility/constants.h"
#include "src/utility/cstring.h"
#include "src/parser/MappedFile.h"
#include "src/exceptions/FileIoException.h"
#include "src/exceptions/WrongFormatException.h"
@ -27,6 +28,8 @@ extern log4cplus::Logger logger;
namespace storm {
namespace parser {
using namespace storm::utility::cstring;
storm::storage::SparseMatrix<double> DeterministicSparseTransitionParser::parseDeterministicTransitions(std::string const& filename) {
storm::storage::SparseMatrix<double> emptyMatrix;
@ -43,21 +46,18 @@ namespace storm {
// Enforce locale where decimal point is '.'.
setlocale(LC_NUMERIC, "C");
if (!fileExistsAndIsReadable(filename.c_str())) {
if (!MappedFile::fileExistsAndIsReadable(filename.c_str())) {
LOG4CPLUS_ERROR(logger, "Error while parsing " << filename << ": File does not exist or is not readable.");
throw storm::exceptions::FileIoException() << "The supplied Transition input file \"" << filename << "\" does not exist or is not readable by this process.";
}
// Find out about the used line endings.
SupportedLineEndings lineEndings = findUsedLineEndings(filename, true);
// Open file.
MappedFile file(filename.c_str());
char* buf = file.data;
// Perform first pass, i.e. count entries that are not zero.
bool insertDiagonalEntriesIfMissing = !isRewardFile;
DeterministicSparseTransitionParser::FirstPassResult firstPass = DeterministicSparseTransitionParser::firstPass(file.data, lineEndings, insertDiagonalEntriesIfMissing);
DeterministicSparseTransitionParser::FirstPassResult firstPass = DeterministicSparseTransitionParser::firstPass(file.data, insertDiagonalEntriesIfMissing);
LOG4CPLUS_INFO(logger, "First pass on " << filename << " shows " << firstPass.numberOfNonzeroEntries << " NonZeros.");
@ -72,7 +72,8 @@ namespace storm {
// Skip the format hint if it is there.
buf = trimWhitespaces(buf);
if(buf[0] < '0' || buf[0] > '9') {
buf = storm::parser::forwardToNextLine(buf, lineEndings);
buf = forwardToLineEnd(buf);
buf = trimWhitespaces(buf);
}
if(isRewardFile) {
@ -191,14 +192,15 @@ namespace storm {
return resultMatrix.build();
}
DeterministicSparseTransitionParser::FirstPassResult DeterministicSparseTransitionParser::firstPass(char* buf, SupportedLineEndings lineEndings, bool insertDiagonalEntriesIfMissing) {
DeterministicSparseTransitionParser::FirstPassResult DeterministicSparseTransitionParser::firstPass(char* buf, bool insertDiagonalEntriesIfMissing) {
DeterministicSparseTransitionParser::FirstPassResult result;
// Skip the format hint if it is there.
buf = trimWhitespaces(buf);
if(buf[0] < '0' || buf[0] > '9') {
buf = storm::parser::forwardToNextLine(buf, lineEndings);
buf = forwardToLineEnd(buf);
buf = trimWhitespaces(buf);
}
// Check all transitions for non-zero diagonal entries and deadlock states.

4
src/parser/DeterministicSparseTransitionParser.h

@ -2,7 +2,6 @@
#define STORM_PARSER_DETERMINISTICSPARSETRANSITIONPARSER_H_
#include "src/storage/SparseMatrix.h"
#include "src/parser/Parser.h"
namespace storm {
@ -59,11 +58,10 @@ private:
* transitions and the maximum node id.
*
* @param buffer The buffer that cointains the input.
* @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, SupportedLineEndings lineEndings, bool insertDiagonalEntriesIfMissing = true);
static FirstPassResult firstPass(char* buffer, bool insertDiagonalEntriesIfMissing = true);
/*
* The main parsing routine.

1
src/parser/LtlParser.h

@ -8,7 +8,6 @@
#ifndef STORM_PARSER_LTLPARSER_H_
#define STORM_PARSER_LTLPARSER_H_
#include "Parser.h"
#include "src/formula/Ltl.h"
namespace storm {

8
src/parser/MappedFile.cpp

@ -11,9 +11,6 @@
#include <cstring>
#include <fcntl.h>
#include <iostream>
#include <string>
#include <boost/integer/integer_mask.hpp>
#include "src/exceptions/FileIoException.h"
@ -96,6 +93,11 @@ namespace storm {
CloseHandle(this->file);
#endif
}
bool MappedFile::fileExistsAndIsReadable(const char* fileName) {
std::ifstream fin(fileName);
return fin.good();
}
} // namespace parser
} // namespace storm

6
src/parser/MappedFile.h

@ -48,6 +48,12 @@ namespace storm {
*/
~MappedFile();
/*!
* @brief Tests whether the given file exists and is readable.
* @return True iff the file exists and is readable.
*/
static bool fileExistsAndIsReadable(const char* fileName);
/*!
* @brief pointer to actual file content.
*/

38
src/parser/MarkovAutomatonSparseTransitionParser.cpp

@ -2,13 +2,17 @@
#include "src/settings/Settings.h"
#include "src/exceptions/WrongFormatException.h"
#include "MappedFile.h"
#include "src/parser/MappedFile.h"
#include "src/utility/cstring.h"
namespace storm {
namespace parser {
MarkovAutomatonSparseTransitionParser::FirstPassResult MarkovAutomatonSparseTransitionParser::firstPass(char* buf, SupportedLineEndings lineEndings) {
using namespace storm::utility::cstring;
MarkovAutomatonSparseTransitionParser::FirstPassResult MarkovAutomatonSparseTransitionParser::firstPass(char* buf) {
MarkovAutomatonSparseTransitionParser::FirstPassResult result;
bool fixDeadlocks = storm::settings::Settings::getInstance()->isSet("fixDeadlocks");
@ -16,7 +20,8 @@ MarkovAutomatonSparseTransitionParser::FirstPassResult MarkovAutomatonSparseTran
// Skip the format hint if it is there.
buf = trimWhitespaces(buf);
if(buf[0] < '0' || buf[0] > '9') {
buf = storm::parser::forwardToNextLine(buf, lineEndings);
buf = forwardToLineEnd(buf);
buf = trimWhitespaces(buf);
}
// Now read the transitions.
@ -84,7 +89,8 @@ MarkovAutomatonSparseTransitionParser::FirstPassResult MarkovAutomatonSparseTran
stateHasProbabilisticChoice = true;
}
buf = forwardToNextLine(buf, lineEndings);
// Go to the next line where the transitions start.
buf = forwardToNextLine(buf);
// Now that we have the source state and the information whether or not the current choice is probabilistic or Markovian, we need to read the list of successors and the probabilities/rates.
bool hasSuccessorState = false;
@ -131,7 +137,7 @@ MarkovAutomatonSparseTransitionParser::FirstPassResult MarkovAutomatonSparseTran
// As we found a new successor, we need to increase the number of nonzero entries.
++result.numberOfNonzeroEntries;
buf = forwardToNextLine(buf, lineEndings);
buf = forwardToNextLine(buf);
} else {
// If it was not a "*", we have to assume that we encountered the beginning of a new choice definition. In this case, we don't move the pointer
// to the buffer, because we still need to read the new source state.
@ -143,13 +149,17 @@ MarkovAutomatonSparseTransitionParser::FirstPassResult MarkovAutomatonSparseTran
return result;
}
MarkovAutomatonSparseTransitionParser::ResultType MarkovAutomatonSparseTransitionParser::secondPass(char* buf, SupportedLineEndings lineEndings, FirstPassResult const& firstPassResult) {
MarkovAutomatonSparseTransitionParser::ResultType MarkovAutomatonSparseTransitionParser::secondPass(char* buf, FirstPassResult const& firstPassResult) {
ResultType result(firstPassResult);
bool fixDeadlocks = storm::settings::Settings::getInstance()->isSet("fixDeadlocks");
// Skip the format hint.
buf = storm::parser::forwardToNextLine(buf, lineEndings);
// Skip the format hint if it is there.
buf = trimWhitespaces(buf);
if(buf[0] < '0' || buf[0] > '9') {
buf = forwardToLineEnd(buf);
buf = trimWhitespaces(buf);
}
// Now read the transitions.
uint_fast64_t source, target = 0;
@ -195,7 +205,8 @@ MarkovAutomatonSparseTransitionParser::ResultType MarkovAutomatonSparseTransitio
isMarkovianChoice = false;
}
buf = forwardToNextLine(buf, lineEndings);
// Go to the next line where the transitions start.
buf = forwardToNextLine(buf);
// Now that we have the source state and the information whether or not the current choice is probabilistic or Markovian, we need to read the list of successors and the probabilities/rates.
bool encounteredNewDistribution = false;
@ -226,7 +237,7 @@ MarkovAutomatonSparseTransitionParser::ResultType MarkovAutomatonSparseTransitio
result.exitRates[source] += val;
}
buf = forwardToNextLine(buf, lineEndings);
buf = forwardToNextLine(buf);
} else {
// If it was not a "*", we have to assume that we encountered the beginning of a new choice definition. In this case, we don't move the pointer
// to the buffer, because we still need to read the new source state.
@ -247,19 +258,16 @@ MarkovAutomatonSparseTransitionParser::ResultType MarkovAutomatonSparseTransitio
// Set the locale to correctly recognize floating point numbers.
setlocale(LC_NUMERIC, "C");
if (!fileExistsAndIsReadable(filename.c_str())) {
if (!MappedFile::fileExistsAndIsReadable(filename.c_str())) {
LOG4CPLUS_ERROR(logger, "Error while parsing " << filename << ": File does not exist or is not readable.");
throw storm::exceptions::WrongFormatException() << "Error while parsing " << filename << ": File does not exist or is not readable.";
}
// Determine used line endings.
SupportedLineEndings lineEndings = findUsedLineEndings(filename, true);
// Open file and prepare pointer to buffer.
MappedFile file(filename.c_str());
char* buf = file.data;
return secondPass(buf, lineEndings, firstPass(buf, lineEndings));
return secondPass(buf, firstPass(buf));
}
} // namespace parser

7
src/parser/MarkovAutomatonSparseTransitionParser.h

@ -3,7 +3,6 @@
#include "src/storage/SparseMatrix.h"
#include "src/storage/BitVector.h"
#include "Parser.h"
namespace storm {
@ -77,20 +76,18 @@ private:
* Performs the first pass on the input pointed to by the given buffer.
*
* @param buffer The buffer that cointains the input.
* @param lineEndings The line endings that are to be used while parsing.
* @return A structure representing the result of the first pass.
*/
static FirstPassResult firstPass(char* buffer, SupportedLineEndings lineEndings);
static FirstPassResult firstPass(char* buffer);
/*
* Performs the second pass on the input pointed to by the given buffer with the information of the first pass.
*
* @param buffer The buffer that cointains the input.
* @param lineEndings The line endings that are to be used while parsing.
* @param firstPassResult The result of the first pass performed on the same input.
* @return A structure representing the result of the second pass.
*/
static ResultType secondPass(char* buffer, SupportedLineEndings lineEndings, FirstPassResult const& firstPassResult);
static ResultType secondPass(char* buffer, FirstPassResult const& firstPassResult);
};
} // namespace parser

1
src/parser/NondeterministicModelParser.h

@ -8,7 +8,6 @@
#ifndef STORM_PARSER_NONDETERMINISTICMODELPARSER_H_
#define STORM_PARSER_NONDETERMINISTICMODELPARSER_H_
#include "src/parser/Parser.h"
#include "src/models/Mdp.h"
#include "src/models/Ctmdp.h"

23
src/parser/NondeterministicSparseTransitionParser.cpp

@ -14,6 +14,8 @@
#include "src/exceptions/FileIoException.h"
#include "src/exceptions/WrongFormatException.h"
#include "src/utility/cstring.h"
#include "log4cplus/logger.h"
#include "log4cplus/loggingmacros.h"
extern log4cplus::Logger logger;
@ -21,6 +23,8 @@ extern log4cplus::Logger logger;
namespace storm {
namespace parser {
using namespace storm::utility::cstring;
NondeterministicSparseTransitionParser::Result NondeterministicSparseTransitionParser::parseNondeterministicTransitions(std::string const& filename) {
Result emptyResult;
@ -38,20 +42,17 @@ namespace storm {
// Enforce locale where decimal point is '.'.
setlocale(LC_NUMERIC, "C");
if (!fileExistsAndIsReadable(filename.c_str())) {
if (!MappedFile::fileExistsAndIsReadable(filename.c_str())) {
LOG4CPLUS_ERROR(logger, "Error while parsing " << filename << ": File does not exist or is not readable.");
throw storm::exceptions::WrongFormatException();
}
// Find out about the used line endings.
SupportedLineEndings 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, modelInformation);
NondeterministicSparseTransitionParser::FirstPassResult firstPass = NondeterministicSparseTransitionParser::firstPass(file.data, isRewardFile, modelInformation);
// If first pass returned zero, the file format was wrong.
if (firstPass.numberOfNonzeroEntries == 0) {
@ -64,7 +65,8 @@ namespace storm {
// Skip the format hint if it is there.
buf = trimWhitespaces(buf);
if(buf[0] < '0' || buf[0] > '9') {
buf = storm::parser::forwardToNextLine(buf, lineEndings);
buf = forwardToLineEnd(buf);
buf = trimWhitespaces(buf);
}
if (isRewardFile) {
@ -158,7 +160,7 @@ namespace storm {
lastchoice = choice;
// Proceed to beginning of next line in file and next row in matrix.
buf = forwardToLineEnd(buf, lineEndings);
buf = forwardToLineEnd(buf);
buf = trimWhitespaces(buf);
}
@ -172,14 +174,15 @@ namespace storm {
return NondeterministicSparseTransitionParser::Result(matrixBuilder.build(), rowMapping);
}
NondeterministicSparseTransitionParser::FirstPassResult NondeterministicSparseTransitionParser::firstPass(char* buf, SupportedLineEndings lineEndings, bool isRewardFile, Result const & modelInformation) {
NondeterministicSparseTransitionParser::FirstPassResult NondeterministicSparseTransitionParser::firstPass(char* buf, bool isRewardFile, Result const & modelInformation) {
// 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);
buf = forwardToLineEnd(buf);
buf = trimWhitespaces(buf);
}
// Read all transitions.
@ -261,7 +264,7 @@ namespace storm {
// 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 = forwardToLineEnd(buf);
buf = trimWhitespaces(buf);
}

4
src/parser/NondeterministicSparseTransitionParser.h

@ -1,7 +1,6 @@
#ifndef STORM_PARSER_NONDETERMINISTICSPARSETRANSITIONPARSER_H_
#define STORM_PARSER_NONDETERMINISTICSPARSETRANSITIONPARSER_H_
#include "src/parser/Parser.h"
#include "src/storage/SparseMatrix.h"
#include <vector>
@ -87,11 +86,10 @@ namespace storm {
* 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, SupportedLineEndings lineEndings, bool isRewardFile, Result const & modelInformation);
static FirstPassResult firstPass(char* buffer, bool isRewardFile, Result const & modelInformation);
/*!
* The main parsing routine.

253
src/parser/Parser.cpp

@ -1,253 +0,0 @@
#include "src/parser/Parser.h"
#include <fcntl.h>
#include <iostream>
#include <fstream>
#include <cstring>
#include <string>
#include <cerrno>
#include <boost/integer/integer_mask.hpp>
#include "src/exceptions/FileIoException.h"
#include "src/exceptions/WrongFormatException.h"
#include "src/utility/OsDetection.h"
#include "src/parser/MappedFile.h"
#include "log4cplus/logger.h"
#include "log4cplus/loggingmacros.h"
extern log4cplus::Logger logger;
namespace storm {
namespace parser {
/*!
* Calls strtol() internally and checks if the new pointer is different
* from the original one, i.e. if str != *end. If they are the same, a
* storm::exceptions::WrongFormatException will be thrown.
* @param str String to parse
* @param end New pointer will be written there
* @return Result of strtol()
*/
uint_fast64_t checked_strtol(const char* str, char** end) {
uint_fast64_t res = strtol(str, end, 10);
if (str == *end) {
LOG4CPLUS_ERROR(logger, "Error while parsing integer. Next input token is not a number.");
LOG4CPLUS_ERROR(logger, "\tUpcoming input is: \"" << std::string(str, 0, 16) << "\"");
throw storm::exceptions::WrongFormatException("Error while parsing integer. Next input token is not a number.");
}
return res;
}
/*!
* Calls strtod() internally and checks if the new pointer is different
* from the original one, i.e. if str != *end. If they are the same, a
* storm::exceptions::WrongFormatException will be thrown.
* @param str String to parse
* @param end New pointer will be written there
* @return Result of strtod()
*/
double checked_strtod(const char* str, char** end) {
double res = strtod(str, end);
if (str == *end) {
LOG4CPLUS_ERROR(logger, "Error while parsing floating point. Next input token is not a number.");
LOG4CPLUS_ERROR(logger, "\tUpcoming input is: \"" << std::string(str, 0, 16) << "\"");
throw storm::exceptions::WrongFormatException("Error while parsing floating point. Next input token is not a number.");
}
return res;
}
/*!
* @brief Tests whether the given file exists and is readable.
* @return True iff the file exists and is readable.
*/
bool fileExistsAndIsReadable(const char* fileName) {
std::ifstream fin(fileName);
bool returnValue = !fin.fail();
return returnValue;
}
/*!
* Skips all numbers, letters and special characters.
* Returns a pointer to the first char that is a whitespace.
* @param buf The string buffer to operate on.
* @return A pointer to the first whitespace character.
*/
char* skipWord(char* buf){
while((*buf != ' ') && (*buf != '\t') && (*buf != '\n') && (*buf != '\r')) buf++;
return buf;
}
/*!
* Skips spaces, tabs, newlines and carriage returns. Returns a pointer
* to first char that is not a whitespace.
* @param buf The string buffer to operate on.
* @return A pointer to the first non-whitespace character.
*/
char* trimWhitespaces(char* buf) {
while ((*buf == ' ') || (*buf == '\t') || (*buf == '\n') || (*buf == '\r')) buf++;
return buf;
}
/*!
* @briefs Analyzes the given file and tries to find out the used file endings.
*/
SupportedLineEndings findUsedLineEndings(std::string const& fileName, bool throwOnUnsupported) {
MappedFile fileMap(fileName.c_str());
char* buf = nullptr;
char* const bufferEnd = fileMap.dataend;
for (buf = fileMap.data; buf != bufferEnd; ++buf) {
if (*buf == '\r') {
// check for following \n
if (((buf + sizeof(char)) < bufferEnd) && (*(buf + sizeof(char)) == '\n')) {
return SupportedLineEndings::SlashRN;
}
return SupportedLineEndings::SlashR;
} else if (*buf == '\n') {
return SupportedLineEndings::SlashN;
}
}
if (throwOnUnsupported) {
LOG4CPLUS_ERROR(logger, "Error while parsing \"" << fileName << "\": Unsupported or unknown line-endings. Please use either of \\r, \\n or \\r\\n");
throw storm::exceptions::WrongFormatException() << "Error while parsing \"" << fileName << "\": Unsupported or unknown line-endings. Please use either of \\r, \\n or \\r\\n";
}
LOG4CPLUS_WARN(logger, "Error while parsing \"" << fileName << "\": Unsupported or unknown line-endings. Please use either of \\r, \\n or \\r\\n");
return SupportedLineEndings::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, SupportedLineEndings lineEndings) {
switch (lineEndings) {
case SupportedLineEndings::SlashN:
return buffer + strcspn(buffer, "\n\0");
break;
case SupportedLineEndings::SlashR:
return buffer + strcspn(buffer, "\r\0");
break;
case SupportedLineEndings::SlashRN:
return buffer + strcspn(buffer, "\r\0");
break;
default:
case SupportedLineEndings::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
*/
char* forwardToNextLine(char* buffer, SupportedLineEndings lineEndings) {
switch (lineEndings) {
case SupportedLineEndings::SlashN:
return strchr(buffer, '\n') + 1;
break;
case SupportedLineEndings::SlashR:
return strchr(buffer, '\r') + 1;
break;
case SupportedLineEndings::SlashRN:
return strchr(buffer, '\r') + 2;
break;
default:
case SupportedLineEndings::Unsupported:
// This Line will never be reached as the Parser would have thrown already.
throw;
break;
}
return nullptr;
}
/*!
* @brief Encapsulates the usage of function @sscanf to scan for the model type hint
* @param targetBuffer The Target for the hint, must be at least 64 bytes long
* @param buffer The Source Buffer from which the Model Hint will be read
*/
void scanForModelHint(char* targetBuffer, uint_fast64_t targetBufferSize, char const* buffer, SupportedLineEndings lineEndings) {
if (targetBufferSize <= 4) {
throw;
}
switch (lineEndings) {
case SupportedLineEndings::SlashN:
#ifdef WINDOWS
sscanf_s(buffer, "%60s\n", targetBuffer, targetBufferSize);
#else
sscanf(buffer, "%60s\n", targetBuffer);
#endif
break;
case SupportedLineEndings::SlashR:
#ifdef WINDOWS
sscanf_s(buffer, "%60s\r", targetBuffer, sizeof(targetBufferSize));
#else
sscanf(buffer, "%60s\r", targetBuffer);
#endif
break;
case SupportedLineEndings::SlashRN:
#ifdef WINDOWS
sscanf_s(buffer, "%60s\r\n", targetBuffer, sizeof(targetBufferSize));
#else
sscanf(buffer, "%60s\r\n", targetBuffer);
#endif
break;
default:
case SupportedLineEndings::Unsupported:
// This Line will never be reached as the Parser would have thrown already.
throw;
break;
}
}
/*!
* @brief Returns the matching Separator-String in the format of "BLANK\t\NEWLINESYMBOL(S)\0
*/
void getMatchingSeparatorString(char* targetBuffer, uint_fast64_t targetBufferSize, SupportedLineEndings lineEndings) {
if (targetBufferSize < 5) {
LOG4CPLUS_ERROR(logger, "getMatchingSeparatorString: The passed Target Buffer is too small.");
throw;
}
switch (lineEndings) {
case SupportedLineEndings::SlashN: {
char source[] = " \n\t";
#ifdef WINDOWS
strncpy(targetBuffer, targetBufferSize, source, sizeof(source));
#else
strncpy(targetBuffer, source, targetBufferSize);
#endif
break;
}
case SupportedLineEndings::SlashR: {
char source[] = " \r\t";
#ifdef WINDOWS
strncpy(targetBuffer, targetBufferSize, source, sizeof(source));
#else
strncpy(targetBuffer, source, targetBufferSize);
#endif
break;
}
case SupportedLineEndings::SlashRN: {
char source[] = " \r\n\t";
#ifdef WINDOWS
strncpy(targetBuffer, targetBufferSize, source, sizeof(source));
#else
strncpy(targetBuffer, source, targetBufferSize);
#endif
break;
}
default:
case SupportedLineEndings::Unsupported:
// This Line will never be reached as the Parser would have thrown already.
LOG4CPLUS_ERROR(logger, "getMatchingSeparatorString: The passed lineEndings were Unsupported. Check your input file.");
throw;
break;
}
}
} // namespace parser
} // namespace storm

93
src/parser/Parser.h

@ -1,93 +0,0 @@
/*
* Parser.h
*
* Created on: 21.11.2012
* Author: Gereon Kremer
*/
#ifndef STORM_PARSER_PARSER_H_
#define STORM_PARSER_PARSER_H_
#include "src/utility/OsDetection.h"
#include <sys/stat.h>
#include <vector>
#include <string>
namespace storm {
/*!
* @brief Contains all file parsers and helper classes.
*
* This namespace contains everything needed to load data files (like
* atomic propositions, transition systems, formulas, etc.) including
* methods for efficient file access (see MappedFile).
*/
namespace parser {
/*!
* @brief Parses integer and checks, if something has been parsed.
*/
uint_fast64_t checked_strtol(const char* str, char** end);
/*!
* @brief Parses floating point and checks, if something has been parsed.
*/
double checked_strtod(const char* str, char** end);
/*!
* @brief Skips all non whitespace characters until the next whitespace.
*/
char* skipWord(char* buf);
/*!
* @brief Skips common whitespaces in a string.
*/
char* trimWhitespaces(char* buf);
/*!
* @brief Tests whether the given file exists and is readable.
*/
bool fileExistsAndIsReadable(const char* fileName);
/*!
* @brief Enum Class Type containing all supported file endings.
*/
enum class SupportedLineEndings : unsigned short {
Unsupported = 0,
SlashR,
SlashN,
SlashRN
};
/*!
* @briefs Analyzes the given file and tries to find out the used line endings.
*/
storm::parser::SupportedLineEndings 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::SupportedLineEndings lineEndings);
/*!
* @brief Encapsulates the usage of function @strchr to forward to the next line
*/
char* forwardToNextLine(char* buffer, storm::parser::SupportedLineEndings lineEndings);
/*!
* @brief Encapsulates the usage of function @sscanf to scan for the model type hint
* @param targetBuffer The Target for the hint, should be at least 64 bytes long
* @param buffer The Source Buffer from which the Model Hint will be read
*/
void scanForModelHint(char* targetBuffer, uint_fast64_t targetBufferSize, char const* buffer, storm::parser::SupportedLineEndings lineEndings);
/*!
* @brief Returns the matching Separator-String in the format of "BLANK\t\NEWLINESYMBOL(S)\0
*/
void getMatchingSeparatorString(char* targetBuffer, uint_fast64_t targetBufferSize, storm::parser::SupportedLineEndings lineEndings);
} // namespace parser
} // namespace storm
#endif /* STORM_PARSER_PARSER_H_ */

2
src/parser/PrctlParser.h

@ -1,8 +1,6 @@
#ifndef STORM_PARSER_PRCTLPARSER_H_
#define STORM_PARSER_PRCTLPARSER_H_
#include "src/parser/Parser.h"
#include "src/formula/Prctl.h"
//#include <memory>

6
src/parser/SparseStateRewardParser.cpp

@ -11,7 +11,7 @@
#include "src/exceptions/WrongFormatException.h"
#include "src/exceptions/FileIoException.h"
#include "src/parser/Parser.h"
#include "src/utility/cstring.h"
#include "src/parser/MappedFile.h"
#include "log4cplus/logger.h"
#include "log4cplus/loggingmacros.h"
@ -21,6 +21,8 @@ namespace storm {
namespace parser {
using namespace storm::utility::cstring;
/*!
* Reads a state reward file and puts the result in a state reward vector.
*
@ -30,7 +32,7 @@ namespace parser {
*/
std::vector<double> SparseStateRewardParser::parseSparseStateReward(uint_fast64_t stateCount, std::string const & filename) {
// Open file.
if (!fileExistsAndIsReadable(filename.c_str())) {
if (!MappedFile::fileExistsAndIsReadable(filename.c_str())) {
LOG4CPLUS_ERROR(logger, "Error while parsing " << filename << ": File does not exist or is not readable.");
throw storm::exceptions::WrongFormatException();
}

95
src/utility/cstring.cpp

@ -0,0 +1,95 @@
#include "src/utility/cstring.h"
#include <cstring>
#include "src/exceptions/WrongFormatException.h"
#include "log4cplus/logger.h"
#include "log4cplus/loggingmacros.h"
extern log4cplus::Logger logger;
namespace storm {
namespace utility {
namespace cstring {
/*!
* Calls strtol() internally and checks if the new pointer is different
* from the original one, i.e. if str != *end. If they are the same, a
* storm::exceptions::WrongFormatException will be thrown.
* @param str String to parse
* @param end New pointer will be written there
* @return Result of strtol()
*/
uint_fast64_t checked_strtol(const char* str, char** end) {
uint_fast64_t res = strtol(str, end, 10);
if (str == *end) {
LOG4CPLUS_ERROR(logger, "Error while parsing integer. Next input token is not a number.");
LOG4CPLUS_ERROR(logger, "\tUpcoming input is: \"" << std::string(str, 0, 16) << "\"");
throw storm::exceptions::WrongFormatException("Error while parsing integer. Next input token is not a number.");
}
return res;
}
/*!
* Calls strtod() internally and checks if the new pointer is different
* from the original one, i.e. if str != *end. If they are the same, a
* storm::exceptions::WrongFormatException will be thrown.
* @param str String to parse
* @param end New pointer will be written there
* @return Result of strtod()
*/
double checked_strtod(const char* str, char** end) {
double res = strtod(str, end);
if (str == *end) {
LOG4CPLUS_ERROR(logger, "Error while parsing floating point. Next input token is not a number.");
LOG4CPLUS_ERROR(logger, "\tUpcoming input is: \"" << std::string(str, 0, 16) << "\"");
throw storm::exceptions::WrongFormatException("Error while parsing floating point. Next input token is not a number.");
}
return res;
}
/*!
* Skips all numbers, letters and special characters.
* Returns a pointer to the first char that is a whitespace.
* @param buf The string buffer to operate on.
* @return A pointer to the first whitespace character.
*/
char* skipWord(char* buf){
while(!isspace(*buf) && *buf != '\0') buf++;
return buf;
}
/*!
* Skips spaces, tabs, newlines and carriage returns. Returns a pointer
* to first char that is not a whitespace.
* @param buf The string buffer to operate on.
* @return A pointer to the first non-whitespace character.
*/
char* trimWhitespaces(char* buf) {
while (isspace(*buf)) buf++;
return buf;
}
/*!
* @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) {
return buffer + strcspn(buffer, "\n\r\0");
}
/*!
* @brief Encapsulates the usage of function @strchr to forward to the next line
*/
char* forwardToNextLine(char* buffer) {
char* lineEnd = forwardToLineEnd(buffer);
while((*lineEnd == '\n') || (*lineEnd == '\r')) lineEnd++;
return lineEnd;
}
} // namespace cstring
} // namespace utility
} // namespace storm

53
src/utility/cstring.h

@ -0,0 +1,53 @@
/*
* cstring.h
*
* Created on: 30.01.2014
* Author: Manuel Sascha Weiand
*/
#ifndef STORM_UTILITY_CSTRING_H_
#define STORM_UTILITY_CSTRING_H_
#include <cstdint>
namespace storm {
namespace utility {
namespace cstring {
/*!
* @brief Parses integer and checks, if something has been parsed.
*/
uint_fast64_t checked_strtol(const char* str, char** end);
/*!
* @brief Parses floating point and checks, if something has been parsed.
*/
double checked_strtod(const char* str, char** end);
/*!
* @brief Skips all non whitespace characters until the next whitespace.
*/
char* skipWord(char* buf);
/*!
* @brief Skips common whitespaces in a string.
*/
char* trimWhitespaces(char* buf);
/*!
* @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);
/*!
* @brief Encapsulates the usage of function @strchr to forward to the next line
*
* Note: All lines after the current, which do not contain any characters are skipped.
*/
char* forwardToNextLine(char* buffer);
} // namespace cstring
} // namespace utility
} // namespace storm
#endif /* STORM_UTILITY_CSTRING_H_ */

2
test/functional/parser/MarkovAutomatonParserTest.cpp

@ -14,7 +14,7 @@
#include "src/parser/MarkovAutomatonSparseTransitionParser.h"
#include "src/parser/SparseStateRewardParser.h"
#include "src/parser/Parser.h"
#include "src/utility/cstring.h"
#include "src/parser/MarkovAutomatonParser.h"
#define STATE_COUNT 6

Loading…
Cancel
Save