diff --git a/alib2/src/automaton/FSM/FiniteAutomatonFromStringParser.cpp b/alib2/src/automaton/FSM/FiniteAutomatonFromStringParser.cpp index f2bcd8e8388bf7e22f494821c9d15e033286a9db..ef7cbf02d593f6025234252481b90f842858fae2 100644 --- a/alib2/src/automaton/FSM/FiniteAutomatonFromStringParser.cpp +++ b/alib2/src/automaton/FSM/FiniteAutomatonFromStringParser.cpp @@ -122,7 +122,40 @@ EpsilonNFA FiniteAutomatonFromStringParser::parseEpsilonNFA() { NFA FiniteAutomatonFromStringParser::parseNFA() { NFA res; - return res; + FiniteAutomatonFromStringLexer::Token token = m_FiniteAutomatonLexer.token(); + if(token.type != FiniteAutomatonFromStringLexer::TokenType::NFA) { + 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(); + res.addInputSymbol(symbol); + 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(); + + next() || m_LabelParser.first(); + parseNFATransition(res, symbols); + 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; + + parseNFATransition(res, symbols); + token = m_FiniteAutomatonLexer.token(); + } + + return res; } DFA FiniteAutomatonFromStringParser::parseDFA() { @@ -190,4 +223,62 @@ void FiniteAutomatonFromStringParser::parseEpsilonNFATransition(EpsilonNFA& res, if(iter != symbols.end()) throw alib::AlibException(); } +void FiniteAutomatonFromStringParser::parseNFATransition(NFA& res, const std::vector<alphabet::Symbol>& symbols) { + 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(); + } + } + + State from(m_LabelParser.parse()); + res.addState(from); + if(initial) res.addInitialState(from); + if(final) res.addFinalState(from); + + next() || m_LabelParser.first(); + + 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()); + res.addState(to); + res.addTransition(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 9b35c28dd7315eab98d33c665a1d941b15c01bb0..4fa7cde86a41982820db56695ed8ac7dcd8f49a6 100644 --- a/alib2/src/automaton/FSM/FiniteAutomatonFromStringParser.h +++ b/alib2/src/automaton/FSM/FiniteAutomatonFromStringParser.h @@ -27,8 +27,8 @@ class FiniteAutomatonFromStringParser { 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 parseNFATransition(NFA& res, const std::vector<alphabet::Symbol>& symbols); + void parseDFATransition(DFA& res, const std::vector<alphabet::Symbol>& symbols); public: FiniteAutomatonFromStringParser(std::stringstream& input); diff --git a/alib2/src/automaton/FSM/FiniteAutomatonToStringComposer.cpp b/alib2/src/automaton/FSM/FiniteAutomatonToStringComposer.cpp index c024932d7af03c7ab40c83d5e42818b60a1f8d35..9798b1c6cf568c428a22a63786e81c27ec195fe6 100644 --- a/alib2/src/automaton/FSM/FiniteAutomatonToStringComposer.cpp +++ b/alib2/src/automaton/FSM/FiniteAutomatonToStringComposer.cpp @@ -6,6 +6,24 @@ namespace automaton { +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); + + for(const alphabet::Symbol& inputSymbol : automaton.getInputAlphabet()) { + const std::map<std::pair<State, alphabet::Symbol>, std::set<State> >::iterator toStates = symbolTransitionsFromState.find(std::make_pair(from, inputSymbol)); + if(toStates == symbolTransitionsFromState.end() || toStates->second.size() == 0) { + out << " -"; + } else { + bool sign = false; + for(const State& to : toStates->second) { + label::LabelToStringComposer composer; + out << (sign ? "|" : " ") << composer.compose(to.getName()); + sign = true; + } + } + } +} + void FiniteAutomatonToStringComposer::composeTransitionsFromState(std::stringstream& out, const EpsilonNFA& automaton, const State& from) const { std::map<std::pair<State, alphabet::Symbol>, std::set<State> > symbolTransitionsFromState = automaton.getSymbolTransitionsFromState(from); @@ -46,6 +64,28 @@ std::string FiniteAutomatonToStringComposer::compose(const DFA& automaton) const std::string FiniteAutomatonToStringComposer::compose(const NFA& automaton) const { std::stringstream out; + out << "NFA"; + 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.getInitialStates().find(*iterState) != automaton.getInitialStates().end()) { + 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 aa5ef2872bf7d2460d03f0b768c7cecd5ed6f9a3..78d8f070480f44e75de54771b2ca1ff2d7290364 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 NFA& automaton, const State& from) const; void composeTransitionsFromState(std::stringstream& out, const EpsilonNFA& automaton, const State& from) const; public: diff --git a/alib2/test-src/automaton/AutomatonTest.cpp b/alib2/test-src/automaton/AutomatonTest.cpp index 11c938d218bb7a37fd0041cf54e666e5a2dd04ad..853a0e3aa6447bab336123e6cbbb88dcc17cbf42 100644 --- a/alib2/test-src/automaton/AutomatonTest.cpp +++ b/alib2/test-src/automaton/AutomatonTest.cpp @@ -89,26 +89,52 @@ void AutomatonTest::testDFAParser() { } void AutomatonTest::FSMStringParserTest() { - std::string input = "ENFA a b c d #E\n" - ">0 3|4 5 1|3|4 - 2\n" - "1 2 - - - -\n" - "2 3 - - - -\n" - "3 - - 4 - -\n" - "4 - 5 - - 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 ); + { + std::string input = "ENFA a b c d #E\n" + ">0 3|4 5 1|3|4 - 2\n" + "1 2 - - - -\n" + "2 3 - - - -\n" + "3 - - 4 - -\n" + "4 - 5 - - 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 ); + } + { + std::string input = "NFA a b c d\n" + ">0 3|4 5 1|3|4 -\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 ); + } }