diff --git a/alib2data/src/automaton/PDA/NPDA.cpp b/alib2data/src/automaton/PDA/NPDA.cpp index 743b4f6c815681f740b1c767f06f293f6048fd86..6986c8cbea3afbfbf0b05afd45f726c54725e9c8 100644 --- a/alib2data/src/automaton/PDA/NPDA.cpp +++ b/alib2data/src/automaton/PDA/NPDA.cpp @@ -20,8 +20,10 @@ namespace automaton { -NPDA::NPDA(State initialState, alphabet::Symbol initialPushdownSymbol) : SingleInitialSymbolPushdownStoreAlphabet(std::move(initialPushdownSymbol)), SingleInitialState(std::move(initialState)) { +NPDA::NPDA ( std::set < State > states, std::set < alphabet::Symbol > inputAlphabet, std::set < alphabet::Symbol > pushdownStoreAlphabet, State initialState, alphabet::Symbol initialSymbol, std::set < State > finalStates ) : std::Components < NPDA, alphabet::Symbol, std::tuple < InputAlphabet, PushdownStoreAlphabet >, std::tuple < InitialSymbol >, automaton::State, std::tuple < States, FinalStates >, std::tuple < InitialState > > ( std::make_tuple ( std::move ( inputAlphabet ), std::move ( pushdownStoreAlphabet ) ), std::make_tuple ( std::move ( initialSymbol ) ), std::make_tuple ( std::move ( states ), std::move ( finalStates ) ), std::make_tuple ( std::move ( initialState ) ) ) { +} +NPDA::NPDA(State initialState, alphabet::Symbol initialPushdownSymbol) : NPDA ( std::set < State > { initialState }, std::set < alphabet::Symbol > { }, std::set < alphabet::Symbol > { initialPushdownSymbol }, initialState, initialPushdownSymbol, std::set < automaton::State > { }) { } AutomatonBase* NPDA::clone() const { @@ -32,79 +34,23 @@ AutomatonBase* NPDA::plunder() && { return new NPDA(std::move(*this)); } -bool NPDA::removeState(const State& state) { - if (initialState == state) { - throw AutomatonException("State \"" + (std::string) state.getName() + "\" is initial state."); - } - - if (finalStates.find(state) != finalStates.end()) { - throw AutomatonException("State \"" + (std::string) state.getName() + "\" is final state."); - } - - for (const std::pair<const std::tuple<State, std::variant<string::Epsilon, alphabet::Symbol>, std::vector<alphabet::Symbol> >, std::set<std::pair<State, std::vector<alphabet::Symbol> > > >& transition : transitions) { - if (state == std::get<0>(transition.first)) - throw AutomatonException("State \"" + (std::string) state.getName() + "\" is used in transition."); - for(const std::pair<State, std::vector<alphabet::Symbol> >& target : transition.second) { - if(target.first == state) - throw AutomatonException("State \"" + (std::string) state.getName() + "\" is used in transition."); - } - } - - return states.erase(state); -} - -bool NPDA::removeInputSymbol(const alphabet::Symbol& symbol) { - for (const std::pair<const std::tuple<State, std::variant<string::Epsilon, alphabet::Symbol>, std::vector<alphabet::Symbol> >, std::set<std::pair<State, std::vector<alphabet::Symbol> > > >& transition : transitions) { - if (std::get<1>(transition.first).is<alphabet::Symbol>() && symbol == std::get<1>(transition.first).get<alphabet::Symbol>()) - throw AutomatonException("Symbol \"" + (std::string) symbol + "\" is used in transition."); - } - - return inputAlphabet.erase(symbol); -} - -bool NPDA::removePushdownStoreSymbol(const alphabet::Symbol& symbol) { - if(initialSymbol == symbol) { - throw AutomatonException("Pushdown store symbol \"" + (std::string) symbol + "\" is start symbol."); - } - - for (const std::pair<const std::tuple<State, std::variant<string::Epsilon, alphabet::Symbol>, std::vector<alphabet::Symbol> >, std::set<std::pair<State, std::vector<alphabet::Symbol> > > >& transition : transitions) { - for (const alphabet::Symbol& popSymbol : std::get<2>(transition.first)) { - if (symbol == popSymbol) - throw AutomatonException("Pushdown store symbol \"" + (std::string) symbol + "\" is used in transition."); - } - for (const std::pair<State, std::vector<alphabet::Symbol> >& target : transition.second) { - if (std::find(target.second.begin(), target.second.end(), symbol) != target.second.end()) - throw AutomatonException("Pushdown store symbol \"" + (std::string) symbol + "\" is used in transition."); - } - } - - return pushdownStoreAlphabet.erase(symbol); -} - bool NPDA::addTransition(State from, std::variant<string::Epsilon, alphabet::Symbol> input, std::vector<alphabet::Symbol> pop, State to, std::vector<alphabet::Symbol> push) { - if (states.find(from) == states.end()) { + if (! getStates().count(from)) throw AutomatonException("State \"" + (std::string) from.getName() + "\" doesn't exist."); - } - if (input.is<alphabet::Symbol>() && inputAlphabet.find(input.get<alphabet::Symbol>()) == inputAlphabet.end()) { + if (input.is<alphabet::Symbol>() && ! getInputAlphabet().count(input.get<alphabet::Symbol>())) throw AutomatonException("Input symbol \"" + (std::string) input.get<alphabet::Symbol>() + "\" doesn't exist."); - } - if (states.find(to) == states.end()) { + if (! getStates().count(to)) throw AutomatonException("State \"" + (std::string) to.getName() + "\" doesn't exist."); - } - for(const alphabet::Symbol& popSymbol : pop) { - if (pushdownStoreAlphabet.find(popSymbol) == pushdownStoreAlphabet.end()) { + for(const alphabet::Symbol& popSymbol : pop) + if (! getPushdownStoreAlphabet().count(popSymbol)) throw AutomatonException("Pushdown store symbol \"" + (std::string) popSymbol + "\" doesn't exist."); - } - } - for(const alphabet::Symbol& pushSymbol : push) { - if (pushdownStoreAlphabet.find(pushSymbol) == pushdownStoreAlphabet.end()) { + for(const alphabet::Symbol& pushSymbol : push) + if (! getPushdownStoreAlphabet().count(pushSymbol)) throw AutomatonException("Pushdown store symbol \"" + (std::string) pushSymbol + "\" doesn't exist."); - } - } std::tuple<State, std::variant<string::Epsilon, alphabet::Symbol>, std::vector<alphabet::Symbol> > key(std::move(from), std::move(input), std::move(pop)); std::pair<automaton::State, std::vector<alphabet::Symbol> > value = std::make_pair(std::move(to), std::move(push)); @@ -144,21 +90,21 @@ const std::map<std::tuple<State, std::variant<string::Epsilon, alphabet::Symbol> } int NPDA::compare(const NPDA& other) const { - auto first = std::tie(states, inputAlphabet, initialState, finalStates, pushdownStoreAlphabet, initialSymbol, transitions); - auto second = std::tie(other.states, other.inputAlphabet, other.initialState, other.finalStates, other.pushdownStoreAlphabet, other.initialSymbol, other.transitions); + auto first = std::tie(getStates(), getInputAlphabet(), getInitialState(), getFinalStates(), getPushdownStoreAlphabet(), getInitialSymbol(), transitions); + auto second = std::tie(other.getStates(), other.getInputAlphabet(), other.getInitialState(), other.getFinalStates(), other.getPushdownStoreAlphabet(), other.getInitialSymbol(), other.transitions); std::compare<decltype(first)> comp; return comp(first, second); } void NPDA::operator>>(std::ostream& out) const { - out << "(NPDA " - << "states = " << states - << "inputAlphabet = " << inputAlphabet - << "initialState = " << initialState - << "finalStates = " << finalStates - << "pushdownStoreAlphabet = " << pushdownStoreAlphabet - << "initialSymbol = " << initialSymbol + out << "(DPDA " + << "states = " << getStates() + << "inputAlphabet = " << getInputAlphabet() + << "initialState = " << getInitialState() + << "finalStates = " << getFinalStates() + << "pushdownStoreAlphabet = " << getPushdownStoreAlphabet() + << "initialSymbol = " << getInitialSymbol() << "transitions = " << transitions << ")"; } @@ -240,6 +186,127 @@ void NPDA::composeTransitions(std::deque<sax::Token>& out) const { } /* namespace automaton */ +namespace std { + +template < > +bool automaton::NPDA::Component < automaton::NPDA, alphabet::Symbol, automaton::InputAlphabet >::used ( const alphabet::Symbol & symbol ) const { + const automaton::NPDA * automaton = static_cast < const automaton::NPDA * > ( this ); + + for (const std::pair<const std::tuple<automaton::State, std::variant<::string::Epsilon, alphabet::Symbol>, std::vector<alphabet::Symbol> >, std::set<std::pair<automaton::State, std::vector<alphabet::Symbol> > > >& transition : automaton->getTransitions()) + if (std::get<1>(transition.first).is<alphabet::Symbol>() && symbol == std::get<1>(transition.first).get<alphabet::Symbol>()) + return true; + + return false; +} + +template < > +bool automaton::NPDA::Component < automaton::NPDA, alphabet::Symbol, automaton::InputAlphabet >::available ( const alphabet::Symbol & ) const { + return true; +} + +template < > +void automaton::NPDA::Component < automaton::NPDA, alphabet::Symbol, automaton::InputAlphabet >::valid ( const alphabet::Symbol & ) const { +} + +template < > +bool automaton::NPDA::Component < automaton::NPDA, alphabet::Symbol, automaton::PushdownStoreAlphabet >::used ( const alphabet::Symbol & symbol ) const { + const automaton::NPDA * automaton = static_cast < const automaton::NPDA * > ( this ); + + if(automaton->getInitialSymbol() == symbol) + return true; + + for (const std::pair<const std::tuple<automaton::State, std::variant<::string::Epsilon, alphabet::Symbol>, std::vector<alphabet::Symbol> >, std::set<std::pair<automaton::State, std::vector<alphabet::Symbol> > > >& transition : automaton->getTransitions()) { + for (const alphabet::Symbol& popSymbol : std::get<2>(transition.first)) + if (symbol == popSymbol) + return true; + + for (const std::pair<automaton::State, std::vector<alphabet::Symbol> >& target : transition.second) + if (std::find(target.second.begin(), target.second.end(), symbol) != target.second.end()) + return true; + } + + return false; +} + +template < > +bool automaton::NPDA::Component < automaton::NPDA, alphabet::Symbol, automaton::PushdownStoreAlphabet >::available ( const alphabet::Symbol & ) const { + return true; +} + +template < > +void automaton::NPDA::Component < automaton::NPDA, alphabet::Symbol, automaton::PushdownStoreAlphabet >::valid ( const alphabet::Symbol & ) const { +} + +template < > +bool automaton::NPDA::Element < automaton::NPDA, alphabet::Symbol, automaton::InitialSymbol >::available ( const alphabet::Symbol & symbol ) const { + const automaton::NPDA * automaton = static_cast < const automaton::NPDA * > ( this ); + + return automaton->accessComponent < automaton::PushdownStoreAlphabet > ( ).get ( ).count ( symbol ); +} + +template < > +void automaton::NPDA::Element < automaton::NPDA, alphabet::Symbol, automaton::InitialSymbol >::valid ( const alphabet::Symbol & ) const { +} + +template < > +bool automaton::NPDA::Component < automaton::NPDA, automaton::State, automaton::States >::used ( const automaton::State & state ) const { + const automaton::NPDA * automaton = static_cast < const automaton::NPDA * > ( this ); + + if ( automaton->getInitialState ( ) == state ) + return true; + + if ( automaton->getFinalStates ( ).count ( state ) ) + return true; + + for (const std::pair<const std::tuple<automaton::State, std::variant<::string::Epsilon, alphabet::Symbol>, std::vector<alphabet::Symbol> >, std::set<std::pair<automaton::State, std::vector<alphabet::Symbol> > > >& transition : automaton->getTransitions()) { + if (state == std::get<0>(transition.first)) + return true; + for(const std::pair<automaton::State, std::vector<alphabet::Symbol> >& target : transition.second) + if(target.first == state) + return true; + } + + return false; +} + +template < > +bool automaton::NPDA::Component < automaton::NPDA, automaton::State, automaton::States >::available ( const automaton::State & ) const { + return true; +} + +template < > +void automaton::NPDA::Component < automaton::NPDA, automaton::State, automaton::States >::valid ( const automaton::State & ) const { +} + +template < > +bool automaton::NPDA::Component < automaton::NPDA, automaton::State, automaton::FinalStates >::used ( const automaton::State & ) const { + return false; +} + +template < > +bool automaton::NPDA::Component < automaton::NPDA, automaton::State, automaton::FinalStates >::available ( const automaton::State & state ) const { + const automaton::NPDA * automaton = static_cast < const automaton::NPDA * > ( this ); + + return automaton->accessComponent < automaton::States > ( ).get ( ).count ( state ); +} + +template < > +void automaton::NPDA::Component < automaton::NPDA, automaton::State, automaton::FinalStates >::valid ( const automaton::State & ) const { +} + +template < > +bool automaton::NPDA::Element < automaton::NPDA, automaton::State, automaton::InitialState >::available ( const automaton::State & state ) const { + const automaton::NPDA * automaton = static_cast < const automaton::NPDA * > ( this ); + + return automaton->accessComponent < automaton::States > ( ).get ( ).count ( state ); +} + +template < > +void automaton::NPDA::Element < automaton::NPDA, automaton::State, automaton::InitialState >::valid ( const automaton::State & ) const { +} + +} /* namespace std */ + namespace alib { auto NPDAParserRegister = xmlApi<automaton::Automaton>::ParserRegister<automaton::NPDA>(); diff --git a/alib2data/src/automaton/PDA/NPDA.h b/alib2data/src/automaton/PDA/NPDA.h index 845b5d13c24c08c97f98ad0eb2f46f729ee597ce..85851ee07e4499f203dc324c0271a281e1a866c0 100644 --- a/alib2data/src/automaton/PDA/NPDA.h +++ b/alib2data/src/automaton/PDA/NPDA.h @@ -12,43 +12,123 @@ #include <map> #include <vector> #include <variant> +#include <core/components.hpp> #include "../AutomatonBase.h" -#include "../common/SingleInitialState.h" -#include "../common/SingleInitialSymbolPushdownStoreAlphabet.h" -#include "../common/InputAlphabet.h" +#include "../common/State.h" #include "../../alphabet/Symbol.h" #include "../../string/Epsilon.h" namespace automaton { +class InputAlphabet; +class PushdownStoreAlphabet; +class InitialSymbol; +class States; +class FinalStates; +class InitialState; + /** * Push Down Automaton */ -class NPDA : public AutomatonBase, public SingleInitialSymbolPushdownStoreAlphabet, public SingleInitialState, public InputAlphabet { +class NPDA : public AutomatonBase, public std::Components < NPDA, alphabet::Symbol, std::tuple < InputAlphabet, PushdownStoreAlphabet >, std::tuple < InitialSymbol >, automaton::State, std::tuple < States, FinalStates >, std::tuple < InitialState > > { protected: std::map < std::tuple < State, std::variant < string::Epsilon, alphabet::Symbol >, std::vector < alphabet::Symbol > >, std::set < std::pair < State, std::vector < alphabet::Symbol > > > > transitions; public: + explicit NPDA ( std::set < State > states, std::set < alphabet::Symbol > inputAlphabet, std::set < alphabet::Symbol > pushdownStoreSymbol, State initialState, alphabet::Symbol initialPushdownSymbol, std::set < automaton::State > finalStates ); explicit NPDA ( State initialState, alphabet::Symbol initialPushdownSymbol ); virtual AutomatonBase * clone ( ) const; virtual AutomatonBase * plunder ( ) &&; - /** - * @copydoc Automaton::removeState(const State&) - */ - virtual bool removeState ( const State & state ); + const State & getInitialState ( ) const { + return accessElement < InitialState > ( ).get ( ); + } - /** - * @copydoc Automaton::removeInputSymbol(const Symbol&) - */ - virtual bool removeInputSymbol ( const alphabet::Symbol & symbol ); + bool setInitialState ( State state ) { + return accessElement < InitialState > ( ).set ( std::move ( state ) ); + } - /** - * @copydoc Automaton::removePushdownStoreSymbol(const Symbol&) - */ - virtual bool removePushdownStoreSymbol ( const alphabet::Symbol & symbol ); + const std::set < State > & getStates ( ) const { + return accessComponent < States > ( ).get ( ); + } + + bool addState ( State state ) { + return accessComponent < States > ( ).add ( std::move ( state ) ); + } + + void setStates ( std::set < State > states ) { + accessComponent < States > ( ).set ( std::move ( states ) ); + } + + void removeState ( const State & state ) { + accessComponent < States > ( ).remove ( state ); + } + + const std::set < State > & getFinalStates ( ) const { + return accessComponent < FinalStates > ( ).get ( ); + } + + bool addFinalState ( State state ) { + return accessComponent < FinalStates > ( ).add ( std::move ( state ) ); + } + + void setFinalStates ( std::set < State > states ) { + accessComponent < FinalStates > ( ).set ( std::move ( states ) ); + } + + void removeFinalState ( const State & state ) { + accessComponent < FinalStates > ( ).remove ( state ); + } + + const std::set < alphabet::Symbol > & getPushdownStoreAlphabet ( ) const { + return accessComponent < PushdownStoreAlphabet > ( ).get ( ); + } + + bool addPushdownStoreSymbol ( alphabet::Symbol symbol ) { + return accessComponent < PushdownStoreAlphabet > ( ).add ( std::move ( symbol ) ); + } + + void addPushdownStoreSymbols ( std::set < alphabet::Symbol > symbols ) { + accessComponent < PushdownStoreAlphabet > ( ).add ( std::move ( symbols ) ); + } + + void setPushdownStoreAlphabet ( std::set < alphabet::Symbol > symbols ) { + accessComponent < PushdownStoreAlphabet > ( ).set ( std::move ( symbols ) ); + } + + void removePushdownStoreSymbol ( const alphabet::Symbol & symbol ) { + accessComponent < PushdownStoreAlphabet > ( ).remove ( symbol ); + } + + const alphabet::Symbol & getInitialSymbol ( ) const { + return accessElement < InitialSymbol > ( ).get ( ); + } + + bool setInitialSymbol ( alphabet::Symbol symbol ) { + return accessElement < InitialSymbol > ( ).set ( std::move ( symbol ) ); + } + + const std::set < alphabet::Symbol > & getInputAlphabet ( ) const { + return accessComponent < InputAlphabet > ( ).get ( ); + } + + bool addInputSymbol ( alphabet::Symbol symbol ) { + return accessComponent < InputAlphabet > ( ).add ( std::move ( symbol ) ); + } + + void addInputSymbols ( std::set < alphabet::Symbol > symbols ) { + accessComponent < InputAlphabet > ( ).add ( std::move ( symbols ) ); + } + + void setInputAlphabet ( std::set < alphabet::Symbol > symbols ) { + accessComponent < InputAlphabet > ( ).set ( std::move ( symbols ) ); + } + + void removeInputSymbol ( const alphabet::Symbol & symbol ) { + accessComponent < InputAlphabet > ( ).remove ( symbol ); + } /** * Adds transition to the NPDA.