From 355a25951e500e92ab19f1bc0c10274958e872b2 Mon Sep 17 00:00:00 2001
From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz>
Date: Mon, 30 May 2016 23:04:09 +0200
Subject: [PATCH] NPDA use components

---
 alib2data/src/automaton/PDA/NPDA.cpp | 213 ++++++++++++++++++---------
 alib2data/src/automaton/PDA/NPDA.h   | 112 ++++++++++++--
 2 files changed, 236 insertions(+), 89 deletions(-)

diff --git a/alib2data/src/automaton/PDA/NPDA.cpp b/alib2data/src/automaton/PDA/NPDA.cpp
index 743b4f6c81..6986c8cbea 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 845b5d13c2..85851ee07e 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.
-- 
GitLab