diff --git a/src/parser/AutoTransitionParser.cpp b/src/parser/AutoTransitionParser.cpp new file mode 100644 index 000000000..c8d5a8604 --- /dev/null +++ b/src/parser/AutoTransitionParser.cpp @@ -0,0 +1,80 @@ +#include "src/parser/AutoTransitionParser.h" + +#include "src/exceptions/WrongFileFormatException.h" + +#include "DeterministicSparseTransitionParser.h" +#include "NonDeterministicSparseTransitionParser.h" + +namespace mrmc { +namespace parser { + +AutoTransitionParser::AutoTransitionParser(const std::string& filename) + : type(Unknown) +{ + + TransitionType name = this->analyzeFilename(filename); + std::pair content = this->analyzeContent(filename); + TransitionType hint = content.first, transitions = content.second; + + if (hint == Unknown) { + if (name == transitions) this->type = name; + else { + LOG4CPLUS_ERROR(logger, "Could not determine file type of " << filename << ". Filename suggests " << name << " but transitions look like " << transitions); + LOG4CPLUS_ERROR(logger, "Please fix your file and try again."); + throw mrmc::exceptions::WrongFileFormatException() << "Could not determine type of file " << filename; + } + } else { + if ((hint == name) && (name == transitions)) this->type = name; + else if (hint == name) { + LOG4CPLUS_WARN(logger, "Transition format in file " << filename << " of type " << name << " look like " << transitions << " transitions."); + LOG4CPLUS_WARN(logger, "We will use the parser for " << name << " and hope for the best!"); + this->type = name; + } + else if (hint == transitions) { + LOG4CPLUS_WARN(logger, "File extension of " << filename << " suggests type " << name << " but the content seems to be " << hint); + LOG4CPLUS_WARN(logger, "We will use the parser for " << hint << " and hope for the best!"); + this->type = hint; + } + else if (name == transitions) { + LOG4CPLUS_WARN(logger, "File " << filename << " contains a hint that it is " << hint << " but filename and transition pattern suggests " << name); + LOG4CPLUS_WARN(logger, "We will use the parser for " << name << " and hope for the best!"); + this->type = name; + } + else { + LOG4CPLUS_WARN(logger, "File " << filename << " contains a hint that it is " << hint << " but filename suggests " << name << " and transition pattern suggests " << transitions); + LOG4CPLUS_WARN(logger, "We will stick to the hint, use the parser for " << hint << " and hope for the best!"); + this->type = hint; + } + } + + // Do actual parsing + switch (this->type) { + case DTMC: + this->parser = new DeterministicSparseTransitionParser(filename); + break; + case NDTMC: + this->parser = new NonDeterministicSparseTransitionParser(filename); + break; + default: ; // Unknown + } +} + +TransitionType AutoTransitionParser::analyzeFilename(const std::string& filename) { + TransitionType type = Unknown; + + return type; +} + +std::pair AutoTransitionParser::analyzeContent(const std::string& filename) { + + TransitionType hintType = Unknown, transType = Unknown; + // Open file + MappedFile file(filename.c_str()); + //char* buf = file.data; + + + return std::pair(hintType, transType); +} + +} //namespace parser +} //namespace mrmc \ No newline at end of file diff --git a/src/parser/AutoTransitionParser.h b/src/parser/AutoTransitionParser.h new file mode 100644 index 000000000..a964ac1fe --- /dev/null +++ b/src/parser/AutoTransitionParser.h @@ -0,0 +1,88 @@ +#ifndef MRMC_PARSER_AUTOPARSER_H_ +#define MRMC_PARSER_AUTOPARSER_H_ + +#include "src/models/AtomicPropositionsLabeling.h" +#include "boost/integer/integer_mask.hpp" + +#include "src/parser/Parser.h" + +#include +#include +#include + +namespace mrmc { +namespace parser { + +/*! + * @brief Enumeration of all supported types of transition systems. + */ +enum TransitionType { + Unknown, DTMC, NDTMC +}; + +std::ostream& operator<<(std::ostream& os, const TransitionType type) +{ + switch (type) { + case Unknown: os << "Unknown"; break; + case DTMC: os << "DTMC"; break; + case NDTMC: os << "NDTMC"; break; + default: os << "Invalid TransitionType"; + } + return os; +} + +/*! + * @brief Checks the given file and tries to call the correct parser. + * + * This parser analyzes the filename, an optional format hint (in the first + * line of the file) and the transitions within the file. + * + * If all three (or two, if the hint is not given) are consistent, it will + * call the appropriate parser. + * If two guesses are the same but the third one contradicts, it will issue + * a warning to the user and call the (hopefully) appropriate parser. + * If all guesses differ, but a format hint is given, it will issue a + * warning to the user and use the format hint to determine the correct + * parser. + * Otherwise, it will issue an error. + */ +class AutoTransitionParser : Parser { + public: + AutoTransitionParser(const std::string& filename); + + /*! + * @brief Returns the type of transition system that was detected. + */ + TransitionType getTransitionType() { + return this->type; + } + + // TODO: is this actually safe with shared_ptr? + template + T* getParser() { + return dynamic_cast( this->parser ); + } + + ~AutoTransitionParser() { + delete this->parser; + } + private: + + TransitionType analyzeFilename(const std::string& filename); + std::pair analyzeContent(const std::string& filename); + + /*! + * @brief Type of the transition system. + */ + TransitionType type; + + /*! + * @brief Pointer to a parser that has parsed the given transition system. + */ + Parser* parser; +}; + +} // namespace parser +} // namespace mrmc + +#endif /* MRMC_PARSER_AUTOPARSER_H_ */