diff --git a/alib2/src/automaton/FSM/FiniteAutomatonFromStringParser.cpp b/alib2/src/automaton/FSM/FiniteAutomatonFromStringParser.cpp index ef7cbf02d593f6025234252481b90f842858fae2..e48d286921a7d71b6a32031349fc33582691dce9 100644 --- a/alib2/src/automaton/FSM/FiniteAutomatonFromStringParser.cpp +++ b/alib2/src/automaton/FSM/FiniteAutomatonFromStringParser.cpp @@ -159,14 +159,62 @@ NFA FiniteAutomatonFromStringParser::parseNFA() { } DFA FiniteAutomatonFromStringParser::parseDFA() { - DFA res(State(label::Label(label::IntegerLabel(0))));; + + FiniteAutomatonFromStringLexer::Token token = m_FiniteAutomatonLexer.token(); + if(token.type != FiniteAutomatonFromStringLexer::TokenType::DFA) { + throw alib::AlibException(); + } + std::vector<alphabet::Symbol> symbols; + + next() || m_SymbolParser.first() || m_SymbolParser.m_LabelParser.first(); + token = m_FiniteAutomatonLexer.token(); + while(token.type != FiniteAutomatonFromStringLexer::TokenType::NEW_LINE) { + alphabet::Symbol symbol = m_SymbolParser.parse(); + symbols.push_back(symbol); + + next() || m_SymbolParser.first() || m_SymbolParser.m_LabelParser.first(); + token = m_FiniteAutomatonLexer.token(); + } + + token = m_FiniteAutomatonLexer.token(); + if(token.type != FiniteAutomatonFromStringLexer::TokenType::NEW_LINE) throw alib::AlibException(); + + State* initialState = NULL; + std::set<State> finalStates; + std::set<State> states; + std::set<std::tuple<State, alphabet::Symbol, State>> transitionFunction; + + next() || m_LabelParser.first(); + parseDFATransition(states, symbols, initialState, finalStates, transitionFunction); + token = m_FiniteAutomatonLexer.token(); + + while(token.type == FiniteAutomatonFromStringLexer::TokenType::NEW_LINE) { + next() || m_LabelParser.first(); + token = m_FiniteAutomatonLexer.token(); + if(token.type == FiniteAutomatonFromStringLexer::TokenType::TEOF) break; + + parseDFATransition(states, symbols, initialState, finalStates, transitionFunction); + token = m_FiniteAutomatonLexer.token(); + } + + if(initialState == NULL) throw alib::AlibException(); + + DFA res(*initialState); + delete initialState; + + res.setInputSymbols(std::set<alphabet::Symbol>(symbols.begin(), symbols.end())); + res.setStates(states); + res.setFinalStates(finalStates); + for(const std::tuple<State, alphabet::Symbol, State> transition : transitionFunction) { + res.addTransition(std::get<0>(transition), std::get<1>(transition), std::get<2>(transition)); + } return res; } - -void FiniteAutomatonFromStringParser::parseEpsilonNFATransition(EpsilonNFA& res, const std::vector<std::variant<string::Epsilon, alphabet::Symbol> >& symbols) { - bool initial = false; - bool final = false; + +void FiniteAutomatonFromStringParser::initialFinalState(bool& initial, bool& final) { + initial = false; + final = false; FiniteAutomatonFromStringLexer::Token token = m_FiniteAutomatonLexer.token(); if(token.type == FiniteAutomatonFromStringLexer::TokenType::IN) { @@ -188,6 +236,14 @@ void FiniteAutomatonFromStringParser::parseEpsilonNFATransition(EpsilonNFA& res, next() || m_LabelParser.first(); } } +} + + +void FiniteAutomatonFromStringParser::parseEpsilonNFATransition(EpsilonNFA& res, const std::vector<std::variant<string::Epsilon, alphabet::Symbol> >& symbols) { + bool initial = false; + bool final = false; + + initialFinalState(initial, final); State from(m_LabelParser.parse()); res.addState(from); @@ -196,6 +252,7 @@ void FiniteAutomatonFromStringParser::parseEpsilonNFATransition(EpsilonNFA& res, next() || m_LabelParser.first(); + FiniteAutomatonFromStringLexer::Token token; std::vector<std::variant<string::Epsilon, alphabet::Symbol>>::const_iterator iter = symbols.begin(); do { if(iter == symbols.end()) throw alib::AlibException(); @@ -227,26 +284,7 @@ void FiniteAutomatonFromStringParser::parseNFATransition(NFA& res, const std::ve bool initial = false; bool final = false; - FiniteAutomatonFromStringLexer::Token token = m_FiniteAutomatonLexer.token(); - if(token.type == FiniteAutomatonFromStringLexer::TokenType::IN) { - initial = true; - next() || m_LabelParser.first(); - token = m_FiniteAutomatonLexer.token(); - - if(token.type == FiniteAutomatonFromStringLexer::TokenType::OUT) { - final = true; - next() || m_LabelParser.first(); - } - } else if(token.type == FiniteAutomatonFromStringLexer::TokenType::OUT) { - final = true; - next() || m_LabelParser.first(); - token = m_FiniteAutomatonLexer.token(); - - if(token.type == FiniteAutomatonFromStringLexer::TokenType::IN) { - initial = true; - next() || m_LabelParser.first(); - } - } + initialFinalState(initial, final); State from(m_LabelParser.parse()); res.addState(from); @@ -255,6 +293,7 @@ void FiniteAutomatonFromStringParser::parseNFATransition(NFA& res, const std::ve next() || m_LabelParser.first(); + FiniteAutomatonFromStringLexer::Token token; std::vector<alphabet::Symbol>::const_iterator iter = symbols.begin(); do { if(iter == symbols.end()) throw alib::AlibException(); @@ -281,4 +320,49 @@ void FiniteAutomatonFromStringParser::parseNFATransition(NFA& res, const std::ve } while(token.type != FiniteAutomatonFromStringLexer::TokenType::NEW_LINE); if(iter != symbols.end()) throw alib::AlibException(); } + +void FiniteAutomatonFromStringParser::parseDFATransition(std::set<State>& states, const std::vector<alphabet::Symbol>& symbols, State*& initialState, std::set<State>& finalStates, std::set<std::tuple<State, alphabet::Symbol, State>>& transitionFunction) { + bool initial = false; + bool final = false; + + initialFinalState(initial, final); + + State from(m_LabelParser.parse()); + states.insert(from); + if(initial) { + if(initialState != NULL) throw alib::AlibException(); + initialState = new State(from); + } + if(final) finalStates.insert(from); + + next() || m_LabelParser.first(); + + FiniteAutomatonFromStringLexer::Token token; + std::vector<alphabet::Symbol>::const_iterator iter = symbols.begin(); + do { + if(iter == symbols.end()) throw alib::AlibException(); + + token = m_FiniteAutomatonLexer.token(); + if(token.type != FiniteAutomatonFromStringLexer::TokenType::NONE) { + + do { + State to(m_LabelParser.parse()); + states.insert(to); + transitionFunction.insert(std::make_tuple(from, *iter, to)); + + next() || m_LabelParser.first(); + token = m_FiniteAutomatonLexer.token(); + if(token.type != FiniteAutomatonFromStringLexer::TokenType::SEPARATOR) break; + + next() || m_LabelParser.first(); + } while(true); + } else { + next() || m_LabelParser.first(); + token = m_FiniteAutomatonLexer.token(); + } + iter++; + } while(token.type != FiniteAutomatonFromStringLexer::TokenType::NEW_LINE); + if(iter != symbols.end()) throw alib::AlibException(); +} + } /* namespace automaton */ diff --git a/alib2/src/automaton/FSM/FiniteAutomatonFromStringParser.h b/alib2/src/automaton/FSM/FiniteAutomatonFromStringParser.h index 4fa7cde86a41982820db56695ed8ac7dcd8f49a6..6fdcbd3feb0d40995890a57f634aa513bc35d062 100644 --- a/alib2/src/automaton/FSM/FiniteAutomatonFromStringParser.h +++ b/alib2/src/automaton/FSM/FiniteAutomatonFromStringParser.h @@ -5,9 +5,13 @@ #include "../../alphabet/SymbolFromStringParser.h" #include "../../label/LabelFromStringParser.h" +#include <tuple> + #include "../Automaton.h" #include "../AutomatonFeatures.h" +#include "../common/State.h" + #include "../../std/variant.hpp" #include "../../string/Epsilon.h" @@ -23,12 +27,14 @@ class FiniteAutomatonFromStringParser { Automaton parse(const std::set<FEATURES>& features); bool next(); + void initialFinalState(bool& initial, bool& final); + EpsilonNFA parseEpsilonNFA(); NFA parseNFA(); DFA parseDFA(); void parseEpsilonNFATransition(EpsilonNFA& res, const std::vector<std::variant<string::Epsilon, alphabet::Symbol> >& symbols); void parseNFATransition(NFA& res, const std::vector<alphabet::Symbol>& symbols); - void parseDFATransition(DFA& res, const std::vector<alphabet::Symbol>& symbols); + void parseDFATransition(std::set<State>& states, const std::vector<alphabet::Symbol>& symbols, State*& initialState, std::set<State>& finalStates, std::set<std::tuple<State, alphabet::Symbol, State>>& transitionFunction); public: FiniteAutomatonFromStringParser(std::stringstream& input); diff --git a/alib2/src/automaton/FSM/FiniteAutomatonToStringComposer.cpp b/alib2/src/automaton/FSM/FiniteAutomatonToStringComposer.cpp index 9798b1c6cf568c428a22a63786e81c27ec195fe6..c5349181a83d4e6047489dd707b09d0098c62d70 100644 --- a/alib2/src/automaton/FSM/FiniteAutomatonToStringComposer.cpp +++ b/alib2/src/automaton/FSM/FiniteAutomatonToStringComposer.cpp @@ -6,6 +6,20 @@ namespace automaton { +void FiniteAutomatonToStringComposer::composeTransitionsFromState(std::stringstream& out, const DFA& automaton, const State& from) const { + std::map<std::pair<State, alphabet::Symbol>, State> symbolTransitionsFromState = automaton.getTransitionsFromState(from); + + for(const alphabet::Symbol& inputSymbol : automaton.getInputAlphabet()) { + const std::map<std::pair<State, alphabet::Symbol>, State>::iterator toStates = symbolTransitionsFromState.find(std::make_pair(from, inputSymbol)); + if(toStates == symbolTransitionsFromState.end()) { + out << " -"; + } else { + label::LabelToStringComposer composer; + out << " " << composer.compose(toStates->second.getName()); + } + } +} + void FiniteAutomatonToStringComposer::composeTransitionsFromState(std::stringstream& out, const NFA& automaton, const State& from) const { std::map<std::pair<State, alphabet::Symbol>, std::set<State> > symbolTransitionsFromState = automaton.getTransitionsFromState(from); @@ -57,6 +71,28 @@ void FiniteAutomatonToStringComposer::composeTransitionsFromState(std::stringstr std::string FiniteAutomatonToStringComposer::compose(const DFA& automaton) const { std::stringstream out; + out << "DFA"; + for(auto iterSymbol = automaton.getInputAlphabet().begin(); iterSymbol != automaton.getInputAlphabet().end(); iterSymbol++) { + alphabet::SymbolToStringComposer composer; + out << " " << composer.compose(*iterSymbol); + } + + out << std::endl; + + for(auto iterState = automaton.getStates().begin(); iterState != automaton.getStates().end(); iterState++) { + if(automaton.getInitialState() == *iterState) { + out << ">"; + } + if(automaton.getFinalStates().find(*iterState) != automaton.getFinalStates().end()) { + out << "<"; + } + label::LabelToStringComposer composer; + out << composer.compose(iterState->getName()); + + composeTransitionsFromState(out, automaton, *iterState); + + out << std::endl; + } return out.str(); } diff --git a/alib2/src/automaton/FSM/FiniteAutomatonToStringComposer.h b/alib2/src/automaton/FSM/FiniteAutomatonToStringComposer.h index 78d8f070480f44e75de54771b2ca1ff2d7290364..cacb27ec64c93b32622d89a88416f81728cad297 100644 --- a/alib2/src/automaton/FSM/FiniteAutomatonToStringComposer.h +++ b/alib2/src/automaton/FSM/FiniteAutomatonToStringComposer.h @@ -20,6 +20,7 @@ class FiniteAutomatonToStringComposer : public AutomatonBase::const_visitor_type void Visit(void*, const PDA& automaton) const; void Visit(void*, const OneTapeDTM& automaton) const; + void composeTransitionsFromState(std::stringstream& out, const DFA& automaton, const State& from) const; void composeTransitionsFromState(std::stringstream& out, const NFA& automaton, const State& from) const; void composeTransitionsFromState(std::stringstream& out, const EpsilonNFA& automaton, const State& from) const; diff --git a/alib2/test-src/automaton/AutomatonTest.cpp b/alib2/test-src/automaton/AutomatonTest.cpp index 853a0e3aa6447bab336123e6cbbb88dcc17cbf42..92c3fc58206212180c42e475a6fe74a0bc27ed4f 100644 --- a/alib2/test-src/automaton/AutomatonTest.cpp +++ b/alib2/test-src/automaton/AutomatonTest.cpp @@ -135,6 +135,30 @@ void AutomatonTest::FSMStringParserTest() { automaton::FiniteAutomatonFromStringParser parser2(outputs); automaton::Automaton automaton2 = parser2.parseValue(); + CPPUNIT_ASSERT( automaton == automaton2 ); + } + { + std::string input = "DFA a b c d\n" + ">0 3 5 1 -\n" + "1 2 - - -\n" + "2 3 - - -\n" + "3 - - 4 -\n" + "4 - 5 - -\n" + "<5 - - - 3\n"; + std::stringstream inputs(input); + + automaton::FiniteAutomatonFromStringParser parser(inputs); + automaton::Automaton automaton = parser.parseValue(); + + automaton::FiniteAutomatonToStringComposer composer; + std::string output = composer.compose(automaton); + std::stringstream outputs(output); + + CPPUNIT_ASSERT( input == output ); + + automaton::FiniteAutomatonFromStringParser parser2(outputs); + automaton::Automaton automaton2 = parser2.parseValue(); + CPPUNIT_ASSERT( automaton == automaton2 ); } }