#include "TransitionMachine.hpp" #include "File.hpp" #include "util.hpp" #include <cstring> TransitionMachine::TransitionMachine(bool trainMode) { std::string filename = ProgramParameters::tmFilename; auto badFormatAndAbort = [&filename](const std::string & errInfo) { fprintf(stderr, "ERROR (%s) : file %s bad format. Aborting.\n", errInfo.c_str(), filename.c_str()); exit(1); }; this->trainMode = trainMode; File file(filename, "r"); FILE * fd = file.getDescriptor(); char buffer[1024]; char buffer2[1024]; char buffer3[1024]; // Reading the name if(fscanf(fd, "Name : %[^\n]\n", buffer) != 1) badFormatAndAbort(ERRINFO); name = buffer; // Reading dicts if(fscanf(fd, "Dicts : %[^\n]\n", buffer) != 1) badFormatAndAbort(ERRINFO); if (ProgramParameters::dicts.empty()) ProgramParameters::dicts = ProgramParameters::expPath + buffer; Dict::readDicts(ProgramParameters::expPath, ProgramParameters::dicts, trainMode); // Reading %CLASSIFIERS if(fscanf(fd, "%%%s\n", buffer) != 1 || buffer != std::string("CLASSIFIERS")) badFormatAndAbort(ERRINFO); while(fscanf(fd, "%%%s\n", buffer) != 1) { // Reading a classifier if(fscanf(fd, "%s %s\n", buffer, buffer2) != 2) badFormatAndAbort(ERRINFO); str2classifier.emplace(buffer, std::unique_ptr<Classifier>(new Classifier(buffer2, trainMode))); } // Reading %STATES if(buffer != std::string("STATES")) badFormatAndAbort(ERRINFO); currentState = ""; initialState = ""; while(fscanf(fd, "%%%s\n", buffer) != 1) { // Reading a state if(fscanf(fd, "%s %s\n", buffer, buffer2) != 2) badFormatAndAbort(ERRINFO); if(str2classifier.count(buffer2) == 0) badFormatAndAbort(ERRINFO + std::string(" unknown classifier \'") + buffer2 + std::string("\'")); str2state.emplace(buffer, std::unique_ptr<State>(new State(buffer, buffer2))); if(currentState.empty()) // Initial state = first state in the file { currentState = buffer; initialState = currentState; } } // Reading %TRANSITIONS if(buffer != std::string("TRANSITIONS")) badFormatAndAbort(ERRINFO); while(fscanf(fd, "%s %s %[^\n]\n", buffer, buffer2, buffer3) == 3) { std::string src(buffer); std::string dest(buffer2); std::string prefix(buffer3); if(str2state.count(src) == 0) badFormatAndAbort(ERRINFO + std::string(" unknown state \'") + src + std::string("\'")); if(str2state.count(dest) == 0) badFormatAndAbort(ERRINFO + std::string(" unknown state \'") + dest + std::string("\'")); State * srcState = str2state[src].get(); srcState->transitions.emplace_back(dest, prefix); } } TransitionMachine::State::State(const std::string & name, const std::string & classifier) { this->name = name; this->classifier = classifier; } TransitionMachine::Transition::Transition(const std::string & dest, const std::string & prefix) { this->dest = dest; this->actionPrefix = prefix; } std::string & TransitionMachine::getCurrentState() { return currentState; } TransitionMachine::Transition * TransitionMachine::getTransition(const std::string & action) { int longestPrefix = -1; State * currentStatePtr = str2state[currentState].get(); for (unsigned int i = 0; i < currentStatePtr->transitions.size(); i++) { auto & transition = currentStatePtr->transitions[i]; unsigned int currentMaxLength = longestPrefix >= 0 ? currentStatePtr->transitions[longestPrefix].actionPrefix.size() : 0; if(transition.actionPrefix == "*" || !strncmp(action.c_str(), transition.actionPrefix.c_str(), transition.actionPrefix.size())) if (transition.actionPrefix.size() > currentMaxLength) longestPrefix = i; } if (longestPrefix != -1) return ¤tStatePtr->transitions[longestPrefix]; fprintf(stderr, "ERROR (%s) : no corresponding transition for action \'%s\' and state \'%s\'. Aborting.\n", ERRINFO, action.c_str(), currentStatePtr->name.c_str()); exit(1); return nullptr; } void TransitionMachine::takeTransition(Transition * transition) { currentState = transition->dest; } std::vector<Classifier*> TransitionMachine::getClassifiers() { std::vector<Classifier*> classifiers; for (auto & it : str2classifier) classifiers.emplace_back(it.second.get()); return classifiers; } void TransitionMachine::reset() { currentState = initialState; } Classifier * TransitionMachine::getCurrentClassifier() { return str2classifier[str2state[currentState]->classifier].get(); }