diff --git a/alib2algo/src/automaton/convert/ToGrammar.h b/alib2algo/src/automaton/convert/ToGrammar.h index 79147ee784144f3e16de2289a15e225fa9af069e..df34d7452db4bdf9eed13cdea67bb21b80e190ff 100644 --- a/alib2algo/src/automaton/convert/ToGrammar.h +++ b/alib2algo/src/automaton/convert/ToGrammar.h @@ -43,7 +43,7 @@ public: /** * Performs the conversion (@sa ToGrammarRightRG::convert). * @tparam SymbolType Type for symbols. - * @tparam StateType Type for states. + * @tparam StateAndNonterminalType Type for states. * @param automaton the automaton to convert * @return right regular grammar equivalent to the input @p automaton */ diff --git a/alib2algo/src/automaton/convert/ToGrammarRightRG.cpp b/alib2algo/src/automaton/convert/ToGrammarRightRG.cpp index b4acef5b64717f1dce5a4f3b8e67a427f18b5e9b..58e84d9f6f585557660e50071f6ff2e518447f87 100644 --- a/alib2algo/src/automaton/convert/ToGrammarRightRG.cpp +++ b/alib2algo/src/automaton/convert/ToGrammarRightRG.cpp @@ -6,95 +6,12 @@ */ #include "ToGrammarRightRG.h" -#include <common/createUnique.hpp> #include <registration/AlgoRegistration.hpp> namespace automaton { namespace convert { -grammar::RightRG < > ToGrammarRightRG::convert(const automaton::NFA < > & automaton) { - ext::map<DefaultStateType, DefaultSymbolType> nonterminalMap; - - const DefaultStateType& initState = automaton.getInitialState(); - DefaultSymbolType initSymbol { initState }; - - grammar::RightRG < > grammar(initSymbol); - nonterminalMap.insert(std::make_pair(initState, initSymbol)); - - grammar.setTerminalAlphabet(automaton.getInputAlphabet()); - - for(const auto& state : automaton.getStates()) { - if(state == initState) - continue; - - DefaultSymbolType nt = common::createUnique(DefaultSymbolType(state), grammar.getTerminalAlphabet(), grammar.getNonterminalAlphabet()); - grammar.addNonterminalSymbol(nt); - nonterminalMap.insert(std::make_pair(state, nt)); - } - - // step 2 - create set of P in G - for(const auto& transition : automaton.getTransitions()) { - const DefaultStateType& from = transition.first.first; - const DefaultSymbolType& input = transition.first.second; - for(const auto& to : transition.second) { - grammar.addRule(nonterminalMap.find(from)->second, ext::make_pair(input, nonterminalMap.find(to)->second)); // 2a - if(automaton.getFinalStates().count(to)) // 2b - grammar.addRule(nonterminalMap.find(from)->second, input); - } - } - - // step 3 - set start symbol of G - grammar.setInitialSymbol(nonterminalMap.find(automaton.getInitialState())->second); - - // step 4 - if(automaton.getFinalStates().count(automaton.getInitialState())) - grammar.setGeneratesEpsilon(true); // okay this feature breaks algorithm but simplifies the code actually :)) - - return grammar; -} - -grammar::RightRG < > ToGrammarRightRG::convert(const automaton::DFA<>& automaton) { - ext::map<DefaultStateType, DefaultSymbolType> nonterminalMap; - - const DefaultStateType& initState = automaton.getInitialState(); - DefaultSymbolType initSymbol { initState }; - - grammar::RightRG < > grammar(initSymbol); - nonterminalMap.insert(std::make_pair(initState, initSymbol)); - - grammar.setTerminalAlphabet(automaton.getInputAlphabet()); - - for(const auto& state : automaton.getStates()) { - if(state == initState) - continue; - - DefaultSymbolType nt = common::createUnique(DefaultSymbolType(state), grammar.getTerminalAlphabet(), grammar.getNonterminalAlphabet()); - grammar.addNonterminalSymbol(nt); - nonterminalMap.insert(std::make_pair(state, nt)); - } - - // step 2 - create set of P in G - for(const auto& transition : automaton.getTransitions()) { - const DefaultStateType& from = transition.first.first; - const DefaultSymbolType& input = transition.first.second; - const DefaultStateType& to = transition.second; - - grammar.addRule(nonterminalMap.find(from)->second, ext::make_pair(input, nonterminalMap.find(to)->second)); // 2a - if(automaton.getFinalStates().count(to)) // 2b - grammar.addRule(nonterminalMap.find(from)->second, input); - } - - // step 3 - set start symbol of G - grammar.setInitialSymbol(nonterminalMap.find(automaton.getInitialState())->second); - - // step 4 - if(automaton.getFinalStates().count(automaton.getInitialState())) - grammar.setGeneratesEpsilon(true); // okay this feature breaks algorithm but simplifies the code actually :)) - - return grammar; -} - auto ToGrammarRightRGNFA = registration::AbstractRegister < ToGrammarRightRG, grammar::RightRG < >, const automaton::NFA < > & > ( ToGrammarRightRG::convert ); auto ToGrammarRightRGDFA = registration::AbstractRegister < ToGrammarRightRG, grammar::RightRG < >, const automaton::DFA < > & > ( ToGrammarRightRG::convert ); diff --git a/alib2algo/src/automaton/convert/ToGrammarRightRG.h b/alib2algo/src/automaton/convert/ToGrammarRightRG.h index d3d29ee7892a55afcc2d2c51009ea65c768cbc89..f72eab3bd5f5415710c8e174bb6389aa6bde5383 100644 --- a/alib2algo/src/automaton/convert/ToGrammarRightRG.h +++ b/alib2algo/src/automaton/convert/ToGrammarRightRG.h @@ -25,9 +25,12 @@ #define __TO_GRAMMAR_RIGHT_RG_H__ #include <grammar/Regular/RightRG.h> + #include <automaton/FSM/NFA.h> #include <automaton/FSM/DFA.h> +#include <common/createUnique.hpp> + namespace automaton { namespace convert { @@ -39,17 +42,82 @@ class ToGrammarRightRG { public: /** * Performs the conversion of the finite automaton to right regular grammar. - * @param automaton a finite automaton to convert - * @return right regular grammar equivalent to the source @p automaton. + * + * \tparam SymbolType the type of input/terminal symbols of automaton and the resulting grammar + * \tparam StateNonterminalType the type of states of the automaton and nonterminal symbols of the resulting grammar + * + * \param automaton a finite automaton to convert + * + * \return right regular grammar equivalent to the source @p automaton. */ - static grammar::RightRG < > convert(const automaton::NFA < > & automaton); + template < class SymbolType, class StateNonterminalType > + static grammar::RightRG < SymbolType, StateNonterminalType > convert ( const automaton::NFA < SymbolType, StateNonterminalType > & automaton ); /** * \overload */ - static grammar::RightRG < > convert(const automaton::DFA < > & automaton); + template < class SymbolType, class StateNonterminalType > + static grammar::RightRG < SymbolType, StateNonterminalType > convert ( const automaton::DFA < SymbolType, StateNonterminalType > & automaton ); }; + +template < class SymbolType, class StateNonterminalType > +grammar::RightRG < SymbolType, StateNonterminalType > ToGrammarRightRG::convert ( const automaton::NFA < SymbolType, StateNonterminalType > & automaton ) { + grammar::RightRG < SymbolType, StateNonterminalType > grammar ( automaton.getInitialState ( ) ); + + grammar.setTerminalAlphabet ( automaton.getInputAlphabet ( ) ); + grammar.setNonterminalAlphabet ( automaton.getStates ( ) ); + + // step 2 - create set of P in G + for(const auto& transition : automaton.getTransitions()) { + const auto & from = transition.first.first; + const auto & input = transition.first.second; + + for(const auto& to : transition.second) { + grammar.addRule ( from, ext::make_pair ( input, to ) ); // 2a + if(automaton.getFinalStates().count(to)) // 2b + grammar.addRule(transition.first.first, transition.first.second ); + } + } + + // step 3 - set start symbol of G + grammar.setInitialSymbol(automaton.getInitialState()); + + // step 4 + if(automaton.getFinalStates().count(automaton.getInitialState())) + grammar.setGeneratesEpsilon(true); // okay this feature makes the algorithm a bit different but at the same time it simplifies the code :)) + + return grammar; +} + +template < class SymbolType, class StateNonterminalType > +grammar::RightRG < SymbolType, StateNonterminalType > ToGrammarRightRG::convert ( const automaton::DFA < SymbolType, StateNonterminalType > & automaton ) { + grammar::RightRG < SymbolType, StateNonterminalType > grammar ( automaton.getInitialState ( ) ); + + grammar.setTerminalAlphabet ( automaton.getInputAlphabet ( ) ); + grammar.setNonterminalAlphabet ( automaton.getStates ( ) ); + + // step 2 - create set of P in G + for(const auto& transition : automaton.getTransitions()) { + const auto & from = transition.first.first; + const auto & input = transition.first.second; + const auto & to = transition.second; + + grammar.addRule(from, ext::make_pair(input, to)); // 2a + if(automaton.getFinalStates().count(to)) // 2b + grammar.addRule(from, input); + } + + // step 3 - set start symbol of G + grammar.setInitialSymbol ( automaton.getInitialState ( ) ); + + // step 4 + if ( automaton.getFinalStates ( ).count ( automaton.getInitialState ( ) ) ) + grammar.setGeneratesEpsilon(true); // okay this feature makes the algorithm a bit different but at the same time it simplifies the code :)) + + return grammar; +} + } /* namespace convert */ } /* namespace automaton */