From 2538ab7a7028dfd7a91e2b86f7fbffd29ecd902a Mon Sep 17 00:00:00 2001
From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz>
Date: Sun, 18 May 2014 20:47:56 +0200
Subject: [PATCH] visitor in xml composer, polymorfic printing, operator==

---
 alib2/src/automaton/Automaton.cpp             |  45 ++++++
 alib2/src/automaton/Automaton.h               |  37 ++++-
 .../src/automaton/AutomatonToXMLComposer.cpp  | 152 +++++++++++++++++-
 alib2/src/automaton/AutomatonToXMLComposer.h  |  22 ++-
 alib2/src/automaton/FSM/CompactNFA.cpp        |  19 +++
 alib2/src/automaton/FSM/CompactNFA.h          |   8 +-
 alib2/src/automaton/FSM/DFA.cpp               |  20 ++-
 alib2/src/automaton/FSM/DFA.h                 |   8 +-
 alib2/src/automaton/FSM/EpsilonNFA.cpp        |  19 +++
 alib2/src/automaton/FSM/EpsilonNFA.h          |  10 +-
 alib2/src/automaton/FSM/ExtendedNFA.cpp       |  19 +++
 alib2/src/automaton/FSM/ExtendedNFA.h         |  10 +-
 alib2/src/automaton/FSM/NFA.cpp               |  18 +++
 alib2/src/automaton/FSM/NFA.h                 |  11 +-
 alib2/src/automaton/PDA/PDA.cpp               |  21 +++
 alib2/src/automaton/PDA/PDA.h                 |   8 +-
 alib2/src/automaton/TM/OneTapeDTM.cpp         |  21 +++
 alib2/src/automaton/TM/OneTapeDTM.h           |   7 +-
 alib2/src/automaton/UnknownAutomaton.cpp      |  27 ++--
 alib2/src/automaton/UnknownAutomaton.h        |   8 +-
 .../UnknownAutomatonToXMLComposer.cpp         | 152 ------------------
 .../automaton/UnknownAutomatonToXMLComposer.h |  46 ------
 alib2/src/factory/AutomatonFactory.cpp        |  10 +-
 alib2/src/factory/AutomatonFactory.h          |  10 +-
 alib2/src/std/list.hpp                        |  11 +-
 alib2/src/std/map.hpp                         |  36 +++++
 alib2/src/std/pair.hpp                        |  27 ++++
 alib2/src/std/set.hpp                         |  11 +-
 alib2/src/std/tuple.hpp                       |  52 ++++++
 alib2/src/std/vector.hpp                      |  12 +-
 alib2/test-src/automaton/AutomatonTest.cpp    |  10 +-
 31 files changed, 607 insertions(+), 260 deletions(-)
 delete mode 100644 alib2/src/automaton/UnknownAutomatonToXMLComposer.cpp
 delete mode 100644 alib2/src/automaton/UnknownAutomatonToXMLComposer.h
 create mode 100644 alib2/src/std/map.hpp
 create mode 100644 alib2/src/std/pair.hpp
 create mode 100644 alib2/src/std/tuple.hpp

diff --git a/alib2/src/automaton/Automaton.cpp b/alib2/src/automaton/Automaton.cpp
index d8dfa9540a..cf7fe0bf13 100644
--- a/alib2/src/automaton/Automaton.cpp
+++ b/alib2/src/automaton/Automaton.cpp
@@ -13,5 +13,50 @@ Automaton::~Automaton() {
 
 }
 
+bool Automaton::operator!=(const Automaton& other) const {
+	return !(*this == other);
+}
+
+bool Automaton::operator==(const UnknownAutomaton& other) const {
+	return false;
+}
+
+bool Automaton::operator==(const DFA& other) const {
+	return false;
+}
+
+bool Automaton::operator==(const NFA& other) const {
+	return false;
+}
+
+bool Automaton::operator==(const EpsilonNFA& other) const{
+	return false;
+}
+
+bool Automaton::operator==(const CompactNFA& other) const{
+	return false;
+}
+
+bool Automaton::operator==(const ExtendedNFA& other) const {
+	return false;
+}
+
+bool Automaton::operator==(const PDA& other) const {
+	return false;
+}
+
+bool Automaton::operator==(const OneTapeDTM& other) const {
+	return false;
+}
+
+bool Automaton::operator==(const Automaton& other) const {
+	return false;
+}
+
+std::ostream& operator<<(std::ostream& os, const Automaton& automaton) {
+	automaton >> os;
+	return os;
+}
+
 } /* namespace automaton */
 
diff --git a/alib2/src/automaton/Automaton.h b/alib2/src/automaton/Automaton.h
index 5c6029a6e1..13a1acf614 100644
--- a/alib2/src/automaton/Automaton.h
+++ b/alib2/src/automaton/Automaton.h
@@ -8,14 +8,49 @@
 #ifndef AUTOMATON_H_
 #define AUTOMATON_H_
 
+#include "../std/visitor.hpp"
+
 namespace automaton {
 
+class UnknownAutomaton;
+class DFA;
+class NFA;
+class EpsilonNFA;
+class CompactNFA;
+class ExtendedNFA;
+class PDA;
+class OneTapeDTM;
+
 /**
  * Abstract base class for all automata.
  */
-class Automaton {
+class Automaton : virtual public std::elementBase<std::visitor<UnknownAutomaton, DFA, NFA, EpsilonNFA, CompactNFA, ExtendedNFA, PDA, OneTapeDTM> > {
 public:
 	virtual ~Automaton() noexcept;
+	
+	virtual bool operator!=(const Automaton& other) const;
+
+	virtual bool operator==(const UnknownAutomaton& other) const;
+
+	virtual bool operator==(const DFA& other) const;
+
+	virtual bool operator==(const NFA& other) const;
+
+	virtual bool operator==(const EpsilonNFA& other) const;
+
+	virtual bool operator==(const CompactNFA& other) const;
+
+	virtual bool operator==(const ExtendedNFA& other) const;
+
+	virtual bool operator==(const PDA& other) const;
+
+	virtual bool operator==(const OneTapeDTM& other) const;
+
+	virtual bool operator==(const Automaton& other) const = 0;
+
+	friend std::ostream& operator<<(std::ostream& os, const Automaton& automaton);
+
+	virtual void operator>>(std::ostream&) const = 0;
 };
 
 } /* namespace automaton */
diff --git a/alib2/src/automaton/AutomatonToXMLComposer.cpp b/alib2/src/automaton/AutomatonToXMLComposer.cpp
index 34ed86507e..be77fd416e 100644
--- a/alib2/src/automaton/AutomatonToXMLComposer.cpp
+++ b/alib2/src/automaton/AutomatonToXMLComposer.cpp
@@ -6,6 +6,7 @@
  */
 
 #include "AutomatonToXMLComposer.h"
+#include "../alphabet/Blank.h"
 
 namespace automaton {
 
@@ -25,6 +26,53 @@ void AutomatonToXMLComposer::printSymbols(std::list<sax::Token>& out, const std:
 	out.push_back(sax::Token(tagName, sax::Token::END_ELEMENT));
 }
 
+void AutomatonToXMLComposer::printSymbols(std::list<sax::Token>& out, const std::vector<alphabet::Symbol>& symbols, std::string tagName) {
+	out.push_back(sax::Token(tagName, sax::Token::START_ELEMENT));
+	for (auto& symbol : symbols) {
+		printSymbol(out, symbol, "symbol");
+	}
+	out.push_back(sax::Token(tagName, sax::Token::END_ELEMENT));
+}
+
+void AutomatonToXMLComposer::printShift(std::list<sax::Token>& out, const Shift shift, std::string tagName) {
+	out.push_back(sax::Token(tagName, sax::Token::START_ELEMENT));
+	out.push_back(sax::Token(SHIFT_NAMES [shift], sax::Token::CHARACTER));
+	out.push_back(sax::Token(tagName, sax::Token::END_ELEMENT));
+}
+
+void AutomatonToXMLComposer::printTransitions(std::list<sax::Token>& out, const UnknownAutomaton& automaton) {
+	out.push_back(sax::Token("transitions", sax::Token::START_ELEMENT));
+	for (auto& transition : automaton.getTransitions()) {
+		out.push_back(sax::Token("transition", sax::Token::START_ELEMENT));
+
+		if (transition.hasFrom())
+			printState(out, transition.getFrom(), "from");
+
+		if(transition.hasInput())
+			printInput(out, transition.getInput(), "input");
+
+		if(transition.hasTo())
+			printState(out, transition.getTo(), "to");
+
+		if (transition.getPop().size() > 0)
+			printSymbols(out, transition.getPop(), "pop");
+
+		if (transition.getPush().size() > 0)
+			printSymbols(out, transition.getPush(), "push");
+
+		if (transition.hasOutput())
+			printInput(out, transition.getOutput(), "output");
+
+		if (transition.getShift() != Shift::NOT_SET)
+			printShift(out, transition.getShift(), "shift");
+
+		out.push_back(sax::Token("transition", sax::Token::END_ELEMENT));
+	}
+
+	out.push_back(sax::Token("transitions", sax::Token::END_ELEMENT));
+}
+
+
 void AutomatonToXMLComposer::printTransitions(std::list<sax::Token>& out, const DFA& automaton) {
 	out.push_back(sax::Token("transitions", sax::Token::START_ELEMENT));
 	for(auto& transition : automaton.getTransitions()) {
@@ -91,6 +139,9 @@ void AutomatonToXMLComposer::printInput(std::list<sax::Token>& out, const std::v
 	if(symbol.is<string::Epsilon>()) {
 		out.push_back(sax::Token("epsilon", sax::Token::START_ELEMENT));
 		out.push_back(sax::Token("epsilon", sax::Token::END_ELEMENT));
+	} else if(symbol.get<alphabet::Symbol>() == alphabet::Blank::BLANK) {
+		out.push_back(sax::Token("blank", sax::Token::START_ELEMENT));
+		out.push_back(sax::Token("blank", sax::Token::END_ELEMENT));
 	} else {
 		out.push_back(sax::Token(symbol.get<alphabet::Symbol>().getSymbol(), sax::Token::CHARACTER));
 	}
@@ -99,17 +150,47 @@ void AutomatonToXMLComposer::printInput(std::list<sax::Token>& out, const std::v
 
 void AutomatonToXMLComposer::printSymbol(std::list<sax::Token>& out, const alphabet::Symbol& symbol, std::string tagName) {
 	out.push_back(sax::Token(tagName, sax::Token::START_ELEMENT));
-	out.push_back(sax::Token(symbol.getSymbol(), sax::Token::CHARACTER));
+	if(symbol == alphabet::Blank::BLANK) {
+		out.push_back(sax::Token("blank", sax::Token::START_ELEMENT));
+		out.push_back(sax::Token("blank", sax::Token::START_ELEMENT));
+	} else {
+		out.push_back(sax::Token(symbol.getSymbol(), sax::Token::CHARACTER));
+	}
 	out.push_back(sax::Token(tagName, sax::Token::END_ELEMENT));
 }
 
-std::list<sax::Token> AutomatonToXMLComposer::compose(const Automaton* automaton) {
-	std::list<sax::Token> out;
-	return out;
-}
-
 std::list<sax::Token> AutomatonToXMLComposer::compose(const UnknownAutomaton& automaton) {
 	std::list<sax::Token> out;
+	out.push_back(sax::Token("automaton", sax::Token::START_ELEMENT));
+	
+	if (automaton.getStates().size() > 0)
+		printStates(out, automaton.getStates(), "states");
+
+	if (automaton.getInputSymbols().size() > 0)
+		printSymbols(out, automaton.getInputSymbols(), "inputAlphabet");
+
+	if (automaton.getTapeSymbols().size() > 0)
+		printSymbols(out, automaton.getTapeSymbols(), "tapeAlphabet");
+
+	if (automaton.getStackSymbols().size() > 0)
+		printSymbols(out, automaton.getStackSymbols(), "stackAlphabet");
+
+	if (automaton.hasBlankSymbol())
+		printSymbol(out, automaton.getBlankSymbol(), "blankSymbol");
+
+	if (automaton.getInitialSymbols().size() > 0)
+		printSymbols(out, automaton.getInitialSymbols(), "startSymbols");
+
+	if (automaton.getInitialStates().size() > 0)
+		printStates(out, automaton.getInitialStates(), "initialStates");
+
+	if (automaton.getFinalStates().size() > 0)
+		printStates(out, automaton.getFinalStates(), "finalStates");
+
+	if (automaton.getTransitions().size() > 0)
+		printTransitions(out, automaton);
+
+	out.push_back(sax::Token("automaton", sax::Token::END_ELEMENT));
 	return out;
 }
 
@@ -155,5 +236,64 @@ std::list<sax::Token> AutomatonToXMLComposer::compose(const EpsilonNFA& automato
 	return out;
 }
 
+std::list<sax::Token> AutomatonToXMLComposer::compose(const ExtendedNFA& automaton) {
+	std::list<sax::Token> out;
+	return out;
+}
+
+std::list<sax::Token> AutomatonToXMLComposer::compose(const CompactNFA& automaton) {
+	std::list<sax::Token> out;
+	return out;
+}
+
+std::list<sax::Token> AutomatonToXMLComposer::compose(const PDA& automaton) {
+	std::list<sax::Token> out;
+	return out;
+}
+
+std::list<sax::Token> AutomatonToXMLComposer::compose(const OneTapeDTM& automaton) {
+	std::list<sax::Token> out;
+	return out;
+}
+
+
+std::list<sax::Token> AutomatonToXMLComposer::compose(const Automaton& automaton) {
+	std::list<sax::Token> out;
+	automaton.Accept((void*) &out, *this);
+	return out;
+}
+
+void AutomatonToXMLComposer::Visit(void* data, const UnknownAutomaton& automaton) {
+	*((std::list<sax::Token>*) data) = this->compose(automaton);
+}
+
+void AutomatonToXMLComposer::Visit(void* data, const EpsilonNFA& automaton) {
+	*((std::list<sax::Token>*) data) = this->compose(automaton);
+}
+
+void AutomatonToXMLComposer::Visit(void* data, const NFA& automaton) {
+	*((std::list<sax::Token>*) data) = this->compose(automaton);
+}
+
+void AutomatonToXMLComposer::Visit(void* data, const DFA& automaton) {
+	*((std::list<sax::Token>*) data) = this->compose(automaton);
+}
+
+void AutomatonToXMLComposer::Visit(void* data, const ExtendedNFA& automaton) {
+	*((std::list<sax::Token>*) data) = this->compose(automaton);
+}
+
+void AutomatonToXMLComposer::Visit(void* data, const CompactNFA& automaton) {
+	*((std::list<sax::Token>*) data) = this->compose(automaton);;
+}
+
+void AutomatonToXMLComposer::Visit(void* data, const PDA& automaton) {
+	*((std::list<sax::Token>*) data) = this->compose(automaton);;
+}
+
+void AutomatonToXMLComposer::Visit(void* data, const OneTapeDTM& automaton) {
+	*((std::list<sax::Token>*) data) = this->compose(automaton);;
+}
+
 } /* namespace automaton */
 
diff --git a/alib2/src/automaton/AutomatonToXMLComposer.h b/alib2/src/automaton/AutomatonToXMLComposer.h
index 1a39dc731c..3daa380ce1 100644
--- a/alib2/src/automaton/AutomatonToXMLComposer.h
+++ b/alib2/src/automaton/AutomatonToXMLComposer.h
@@ -21,11 +21,23 @@ namespace automaton {
 /**
  * This class contains methods to print XML representation of automata to the output stream.
  */
-class AutomatonToXMLComposer {
+class AutomatonToXMLComposer : public Automaton::visitor_type {
+	void Visit(void*, const UnknownAutomaton& automaton);
+	void Visit(void*, const EpsilonNFA& automaton);
+	void Visit(void*, const NFA& automaton);
+	void Visit(void*, const DFA& automaton);
+	void Visit(void*, const ExtendedNFA& automaton);
+	void Visit(void*, const CompactNFA& automaton);
+	void Visit(void*, const PDA& automaton);
+	void Visit(void*, const OneTapeDTM& automaton);
+
 protected:
 	static void printStates(std::list<sax::Token>&, const std::set<State>& states, std::string tagName);
 	static void printSymbols(std::list<sax::Token>&, const std::set<alphabet::Symbol>& symbols, std::string tagName);
-	
+	static void printSymbols(std::list<sax::Token>&, const std::vector<alphabet::Symbol>& symbols, std::string tagName);
+	static void printShift(std::list<sax::Token>&, const Shift shift, std::string tagName);
+
+	static void printTransitions(std::list<sax::Token>&, const UnknownAutomaton& automaton);
 	static void printTransitions(std::list<sax::Token>&, const EpsilonNFA& automaton);
 	static void printTransitions(std::list<sax::Token>&, const NFA& automaton);
 	static void printTransitions(std::list<sax::Token>&, const DFA& automaton);
@@ -41,12 +53,16 @@ public:
 	 * @param automaton automaton to print
 	 * @return list of xml tokens representing the automaton
 	 */
-	std::list<sax::Token> compose(const Automaton* automaton);
+	std::list<sax::Token> compose(const Automaton& automaton);
 	
 	std::list<sax::Token> compose(const UnknownAutomaton& automaton);
 	std::list<sax::Token> compose(const DFA& automaton);
 	std::list<sax::Token> compose(const NFA& automaton);
 	std::list<sax::Token> compose(const EpsilonNFA& automaton);
+	std::list<sax::Token> compose(const ExtendedNFA& automaton);
+	std::list<sax::Token> compose(const CompactNFA& automaton);
+	std::list<sax::Token> compose(const PDA& automaton);
+	std::list<sax::Token> compose(const OneTapeDTM& automaton);
 };
 
 } /* namespace automaton */
diff --git a/alib2/src/automaton/FSM/CompactNFA.cpp b/alib2/src/automaton/FSM/CompactNFA.cpp
index 0e2b2ed2d9..e8f8585b90 100644
--- a/alib2/src/automaton/FSM/CompactNFA.cpp
+++ b/alib2/src/automaton/FSM/CompactNFA.cpp
@@ -6,6 +6,7 @@
  */
 
 #include "CompactNFA.h"
+#include "../../std/map.hpp"
 #include "../AutomatonException.h"
 #include <ostream>
 #include <algorithm>
@@ -96,4 +97,22 @@ std::map<std::pair<State, string::String>, std::set<State>> CompactNFA::getTrans
 	return transitionsToState;
 }
 
+bool CompactNFA::operator==(const Automaton& other) const {
+	return other == *this;
+}
+
+bool CompactNFA::operator==(const CompactNFA& other) const {
+	return states == other.states && inputAlphabet == other.inputAlphabet && initialStates == other.initialStates && finalStates == other.finalStates && transitions == other.transitions;
+}
+
+void CompactNFA::operator>>(std::ostream& out) const {
+	out << "(CompactNFA"
+		<< "states = " << states
+		<< "inputAlphabet = " << inputAlphabet
+		<< "initialStates = " << initialStates
+		<< "finalStates = " << finalStates
+		<< "transitions = " << transitions
+		<< ")";
+}
+
 } /* namespace automaton */
diff --git a/alib2/src/automaton/FSM/CompactNFA.h b/alib2/src/automaton/FSM/CompactNFA.h
index 7e1b7e9053..0779c6783e 100644
--- a/alib2/src/automaton/FSM/CompactNFA.h
+++ b/alib2/src/automaton/FSM/CompactNFA.h
@@ -20,7 +20,7 @@ namespace automaton {
  * Represents Finite Automaton.
  * Can store nondeterministic finite automaton without epsilon transitions.
  */
-class CompactNFA : public Automaton, public MultiInitialStates, public InputAlphabet {
+class CompactNFA : public Automaton, public std::element<CompactNFA, Automaton::visitor_type>, public MultiInitialStates, public InputAlphabet {
 protected:
 	std::map<std::pair<State, string::String>, std::set<State> > transitions;
 public:
@@ -66,7 +66,11 @@ public:
 	 */
 	std::map<std::pair<State, string::String>, std::set<State>> getTransitionsToState(const State& from) const;
 
-	friend std::ostream& operator<<(std::ostream& out, const CompactNFA& automaton);
+	virtual bool operator==(const Automaton& other) const;
+
+	virtual bool operator==(const CompactNFA& other) const;
+
+	virtual void operator>>(std::ostream& os) const;
 };
 
 } /* namespace automaton */
diff --git a/alib2/src/automaton/FSM/DFA.cpp b/alib2/src/automaton/FSM/DFA.cpp
index a96cbe28df..5b86e94dd5 100644
--- a/alib2/src/automaton/FSM/DFA.cpp
+++ b/alib2/src/automaton/FSM/DFA.cpp
@@ -6,6 +6,8 @@
  */
 
 #include "DFA.h"
+#include "../../std/set.hpp"
+#include "../../std/map.hpp"
 #include "../AutomatonException.h"
 #include <ostream>
 
@@ -117,12 +119,26 @@ std::map<std::pair<State, alphabet::Symbol>, State> DFA::getTransitionsToState(c
 	return transitionsToState;
 }
 
+bool DFA::isTotal() const {
+	return transitions.size() == inputAlphabet.size() * states.size();
+}
+
+bool DFA::operator==(const Automaton& other) const {
+	return other == *this;
+}
+
 bool DFA::operator==(const DFA& other) const {
 	return this->states == other.states && this->inputAlphabet == other.inputAlphabet && this->initialState == other.initialState && this->finalStates == other.finalStates && this->transitions == other.transitions;
 }
 
-bool DFA::isTotal() const {
-	return transitions.size() == inputAlphabet.size() * states.size();
+void DFA::operator>>(std::ostream& out) const {
+	out << "(DFA"
+		<< " states = " << states
+		<< " inputAlphabet = " << inputAlphabet
+		<< " initialState = " << initialState
+		<< " finalStates = " << finalStates
+		<< " transitions = " << transitions
+		<< ")";
 }
 
 } /* namespace automaton */
diff --git a/alib2/src/automaton/FSM/DFA.h b/alib2/src/automaton/FSM/DFA.h
index 6db2f5ede0..db697e2827 100644
--- a/alib2/src/automaton/FSM/DFA.h
+++ b/alib2/src/automaton/FSM/DFA.h
@@ -20,7 +20,7 @@ namespace automaton {
  * Represents Finite Automaton.
  * Can store nondeterministic finite automaton without epsilon transitions.
  */
-class DFA : public Automaton, public SingleInitialState, public InputAlphabet {
+class DFA : public Automaton, public std::element<DFA, Automaton::visitor_type>, public SingleInitialState, public InputAlphabet {
 protected:
 	std::map<std::pair<State, alphabet::Symbol>, State> transitions;
 public:
@@ -75,10 +75,12 @@ public:
 	 * @return true when automaton is total deterministic, false otherwise
 	 */
 	bool isTotal() const;
+	
+	virtual bool operator==(const Automaton& other) const;
 
-	bool operator==(const DFA& other) const;
+	virtual bool operator==(const DFA& other) const;
 	
-	friend std::ostream& operator<<(std::ostream& out, const DFA& automaton);
+	virtual void operator>>(std::ostream& os) const;
 };
 
 } /* namespace automaton */
diff --git a/alib2/src/automaton/FSM/EpsilonNFA.cpp b/alib2/src/automaton/FSM/EpsilonNFA.cpp
index fa208742d5..45567fab50 100644
--- a/alib2/src/automaton/FSM/EpsilonNFA.cpp
+++ b/alib2/src/automaton/FSM/EpsilonNFA.cpp
@@ -6,6 +6,7 @@
  */
 
 #include "EpsilonNFA.h"
+#include "../../std/map.hpp"
 #include "../AutomatonException.h"
 #include <ostream>
 
@@ -227,4 +228,22 @@ bool EpsilonNFA::isTotal() const {
 	return isDeterministic() && transitions.size() == inputAlphabet.size() * states.size();
 }
 
+bool EpsilonNFA::operator==(const Automaton& other) const {
+	return other == *this;
+}
+
+bool EpsilonNFA::operator==(const EpsilonNFA& other) const {
+	return this->states == other.states && this->inputAlphabet == other.inputAlphabet && this->initialStates == other.initialStates && this->finalStates == other.finalStates && this->transitions == other.transitions;
+}
+
+void EpsilonNFA::operator>>(std::ostream& out) const {
+	out << "(EpsilonNFA"
+		<< " states = " << states
+		<< " inputAlphabet = " << inputAlphabet
+		<< " initialStates = " << initialStates
+		<< " finalStates = " << finalStates
+		<< " transitions = " << transitions
+		<< ")";
+}
+
 } /* namespace automaton */
diff --git a/alib2/src/automaton/FSM/EpsilonNFA.h b/alib2/src/automaton/FSM/EpsilonNFA.h
index 5e41b4243c..ef9d78e2a9 100644
--- a/alib2/src/automaton/FSM/EpsilonNFA.h
+++ b/alib2/src/automaton/FSM/EpsilonNFA.h
@@ -22,7 +22,7 @@ namespace automaton {
  * Represents Finite Automaton.
  * Can store nondeterministic finite automaton with epsilon transitions.
  */
-class EpsilonNFA : public Automaton, public MultiInitialStates, public InputAlphabet {
+class EpsilonNFA : public Automaton, public std::element<EpsilonNFA, Automaton::visitor_type>, public MultiInitialStates, public InputAlphabet {
 protected:
 	std::map<std::pair<State, std::variant<string::Epsilon, alphabet::Symbol> >, std::set<State> > transitions;
 public:
@@ -146,8 +146,12 @@ public:
 	 * @return true when automaton is total deterministic, false otherwise
 	 */
 	bool isTotal() const;
-	
-	friend std::ostream& operator<<(std::ostream& out, const EpsilonNFA& automaton);
+
+	virtual bool operator==(const Automaton& other) const;
+
+	virtual bool operator==(const EpsilonNFA& other) const;
+
+	virtual void operator>>(std::ostream& os) const;
 };
 
 } /* namespace automaton */
diff --git a/alib2/src/automaton/FSM/ExtendedNFA.cpp b/alib2/src/automaton/FSM/ExtendedNFA.cpp
index 796d32ab95..66fecb5ad6 100644
--- a/alib2/src/automaton/FSM/ExtendedNFA.cpp
+++ b/alib2/src/automaton/FSM/ExtendedNFA.cpp
@@ -6,6 +6,7 @@
  */
 
 #include "ExtendedNFA.h"
+#include "../../std/map.hpp"
 #include "../AutomatonException.h"
 #include <ostream>
 #include <algorithm>
@@ -96,4 +97,22 @@ std::map<std::pair<State, regexp::RegExp>, std::set<State> > ExtendedNFA::getTra
 	return transitionsToState;
 }
 
+bool ExtendedNFA::operator==(const Automaton& other) const {
+	return other == *this;
+}
+
+bool ExtendedNFA::operator==(const ExtendedNFA& other) const {
+	return this->states == other.states && this->inputAlphabet == other.inputAlphabet && this->initialStates == other.initialStates && this->finalStates == other.finalStates && this->transitions == other.transitions;
+}
+
+void ExtendedNFA::operator>>(std::ostream& out) const {
+	out << "(ExtendedNFA"
+		<< " states = " << states
+		<< " inputAlphabet = " << inputAlphabet
+		<< " initialStates = " << initialStates
+		<< " finalStates = " << finalStates
+		<< " transitions = " << transitions
+		<< ")";
+}
+
 } /* namespace automaton */
diff --git a/alib2/src/automaton/FSM/ExtendedNFA.h b/alib2/src/automaton/FSM/ExtendedNFA.h
index b7cd2c7b85..2e36838be7 100644
--- a/alib2/src/automaton/FSM/ExtendedNFA.h
+++ b/alib2/src/automaton/FSM/ExtendedNFA.h
@@ -20,7 +20,7 @@ namespace automaton {
  * Represents Finite Automaton.
  * Can store nondeterministic finite automaton without epsilon transitions.
  */
-class ExtendedNFA : public Automaton, public MultiInitialStates, public InputAlphabet {
+class ExtendedNFA : public Automaton, public std::element<ExtendedNFA, Automaton::visitor_type>, public MultiInitialStates, public InputAlphabet {
 protected:
 	std::map<std::pair<State, regexp::RegExp>, std::set<State> > transitions;
 public:
@@ -64,8 +64,12 @@ public:
 	 * @return automaton transitions to state
 	 */
 	std::map<std::pair<State, regexp::RegExp>, std::set<State> > getTransitionsToState(const State& from) const;
-	
-	friend std::ostream& operator<<(std::ostream& out, const ExtendedNFA& automaton);
+
+	virtual bool operator==(const Automaton& other) const;
+
+	virtual bool operator==(const ExtendedNFA& other) const;
+
+	virtual void operator>>(std::ostream& os) const;
 };
 
 } /* namespace automaton */
diff --git a/alib2/src/automaton/FSM/NFA.cpp b/alib2/src/automaton/FSM/NFA.cpp
index faa1235750..e588e515cb 100644
--- a/alib2/src/automaton/FSM/NFA.cpp
+++ b/alib2/src/automaton/FSM/NFA.cpp
@@ -112,4 +112,22 @@ bool NFA::isTotal() const {
 	return isDeterministic() && transitions.size() == inputAlphabet.size() * states.size();
 }
 
+bool NFA::operator==(const Automaton& other) const {
+	return other == *this;
+}
+
+bool NFA::operator==(const NFA& other) const {
+	return this->states == other.states && this->inputAlphabet == other.inputAlphabet && this->initialStates == other.initialStates && this->finalStates == other.finalStates && this->transitions == other.transitions;
+}
+
+void NFA::operator>>(std::ostream& out) const {
+	out << "(NFA"
+		<< " states = " << states
+		<< " inputAlphabet = " << inputAlphabet
+		<< " initialStates = " << initialStates
+		<< " finalStates = " << finalStates
+		<< " transitions = " << transitions
+		<< ")";
+}
+
 } /* namespace automaton */
diff --git a/alib2/src/automaton/FSM/NFA.h b/alib2/src/automaton/FSM/NFA.h
index a71aad4991..6fb134f24a 100644
--- a/alib2/src/automaton/FSM/NFA.h
+++ b/alib2/src/automaton/FSM/NFA.h
@@ -9,6 +9,7 @@
 #define NFA_H_
 
 #include <map>
+#include "../../std/map.hpp"
 #include "../Automaton.h"
 #include "../common/MultiInitialStates.h"
 #include "../common/InputAlphabet.h"
@@ -20,7 +21,7 @@ namespace automaton {
  * Represents Finite Automaton.
  * Can store nondeterministic finite automaton without epsilon transitions.
  */
-class NFA : public Automaton, public MultiInitialStates, public InputAlphabet {
+class NFA : public Automaton, public std::element<NFA, Automaton::visitor_type>, public MultiInitialStates, public InputAlphabet {
 protected:
 	std::map<std::pair<State, alphabet::Symbol>, std::set<State> > transitions;
 public:
@@ -83,8 +84,12 @@ public:
 	 * @return true when automaton is total deterministic, false otherwise
 	 */
 	bool isTotal() const;
-	
-	friend std::ostream& operator<<(std::ostream& out, const NFA& automaton);
+
+	virtual bool operator==(const Automaton& other) const;
+
+	virtual bool operator==(const NFA& other) const;
+
+	virtual void operator>>(std::ostream& os) const;
 };
 
 } /* namespace automaton */
diff --git a/alib2/src/automaton/PDA/PDA.cpp b/alib2/src/automaton/PDA/PDA.cpp
index aef4aa46eb..8c2278582f 100644
--- a/alib2/src/automaton/PDA/PDA.cpp
+++ b/alib2/src/automaton/PDA/PDA.cpp
@@ -6,6 +6,7 @@
  */
 
 #include "PDA.h"
+#include "../../std/map.hpp"
 #include "../AutomatonException.h"
 #include <algorithm>
 
@@ -158,4 +159,24 @@ const std::set<alphabet::Symbol>& PDA::getInitialSymbols() const {
 	return initialSymbols;
 }
 
+bool PDA::operator==(const Automaton& other) const {
+	return other == *this;
+}
+
+bool PDA::operator==(const PDA& other) const {
+	return this->states == other.states && this->inputAlphabet == other.inputAlphabet && this->initialStates == other.initialStates && this->finalStates == other.finalStates && this->stackAlphabet == other.stackAlphabet && this->initialSymbols == other.initialSymbols && this->transitions == other.transitions;
+}
+
+void PDA::operator>>(std::ostream& out) const {
+	out << "(PDA"
+		<< "states = " << states
+		<< "inputAlphabet = " << inputAlphabet
+		<< "initialStates = " << initialStates
+		<< "finalStates = " << finalStates
+		<< "stackAlphabet = " << stackAlphabet
+		<< "initialSymbols = " << initialSymbols
+		<< "transitions = " << transitions
+		<< ")";
+}
+
 } /* namespace automaton */
diff --git a/alib2/src/automaton/PDA/PDA.h b/alib2/src/automaton/PDA/PDA.h
index a550b236f2..bd4f2079d1 100644
--- a/alib2/src/automaton/PDA/PDA.h
+++ b/alib2/src/automaton/PDA/PDA.h
@@ -23,7 +23,7 @@ namespace automaton {
 /**
  * Push Down Automaton
  */
-class PDA: public Automaton, public MultiInitialStates, public InputAlphabet {
+class PDA: public Automaton, public std::element<PDA, Automaton::visitor_type>, public MultiInitialStates, public InputAlphabet {
 protected:
 	std::set<alphabet::Symbol> stackAlphabet;
 	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;
@@ -117,6 +117,12 @@ public:
 	 */
 	const std::set<alphabet::Symbol>& getInitialSymbols() const;
 
+	virtual bool operator==(const Automaton& other) const;
+
+	virtual bool operator==(const PDA& other) const;
+
+	virtual void operator>>(std::ostream& os) const;
+
 };
 
 } /* namespace automaton */
diff --git a/alib2/src/automaton/TM/OneTapeDTM.cpp b/alib2/src/automaton/TM/OneTapeDTM.cpp
index 6e695ef72a..1b496fe653 100644
--- a/alib2/src/automaton/TM/OneTapeDTM.cpp
+++ b/alib2/src/automaton/TM/OneTapeDTM.cpp
@@ -6,6 +6,7 @@
  */
 
 #include "OneTapeDTM.h"
+#include "../../std/map.hpp"
 #include "../AutomatonException.h"
 #include "../../alphabet/Blank.h"
 
@@ -105,4 +106,24 @@ const std::map<std::pair<State, alphabet::Symbol>, std::tuple<State, alphabet::S
 	return transitions;
 }
 
+bool OneTapeDTM::operator==(const Automaton& other) const {
+	return other == *this;
+}
+
+bool OneTapeDTM::operator==(const OneTapeDTM& other) const {
+	return this->states == other.states && this->inputAlphabet == other.inputAlphabet && this->initialState == other.initialState && this->finalStates == other.finalStates && this->tapeAlphabet == other.tapeAlphabet && this->blankSymbol == other.blankSymbol && this->transitions == other.transitions;
+}
+
+void OneTapeDTM::operator>>(std::ostream& out) const {
+	out << "(OneTapeDTM"
+			<< "states = " << states
+			<< "inputAlphabet = " << inputAlphabet
+			<< "initialState = " << initialState
+			<< "finalStates = " << finalStates
+			<< "tapeAlphabet = " << tapeAlphabet
+			<< "blankSymbol = " << blankSymbol
+			<< "transitions = " << transitions
+			<< ")";
+}
+
 } /* namespace automaton */
diff --git a/alib2/src/automaton/TM/OneTapeDTM.h b/alib2/src/automaton/TM/OneTapeDTM.h
index 7726bebc5a..91b6b53994 100644
--- a/alib2/src/automaton/TM/OneTapeDTM.h
+++ b/alib2/src/automaton/TM/OneTapeDTM.h
@@ -22,7 +22,7 @@ namespace automaton {
 /**
  * One tape turing machine
  */
-class OneTapeDTM : public Automaton, public SingleInitialState, public BlankSymbolInputTapeAlphabet {
+class OneTapeDTM : public Automaton, public std::element<OneTapeDTM, Automaton::visitor_type>, public SingleInitialState, public BlankSymbolInputTapeAlphabet {
 protected:
 	std::map<std::pair<State, alphabet::Symbol>, std::tuple<State, alphabet::Symbol, Shift> > transitions;
 
@@ -69,6 +69,11 @@ public:
 	 */
 	const std::map<std::pair<State, alphabet::Symbol>, std::tuple<State, alphabet::Symbol, Shift> >& getTransitions() const;
 
+	virtual bool operator==(const Automaton& other) const;
+
+	virtual bool operator==(const OneTapeDTM& other) const;
+
+	virtual void operator>>(std::ostream& os) const;
 };
 
 } /* namespace automaton */
diff --git a/alib2/src/automaton/UnknownAutomaton.cpp b/alib2/src/automaton/UnknownAutomaton.cpp
index c85d2ee291..12ac46e0e2 100644
--- a/alib2/src/automaton/UnknownAutomaton.cpp
+++ b/alib2/src/automaton/UnknownAutomaton.cpp
@@ -171,7 +171,11 @@ const std::set<UnknownTransition>& UnknownAutomaton::getTransitions() const {
 }
 
 
-bool UnknownAutomaton::operator==(const UnknownAutomaton& other) {
+bool UnknownAutomaton::operator==(const Automaton& other) const {
+	return other == *this;
+}
+
+bool UnknownAutomaton::operator==(const UnknownAutomaton& other) const {
 	return states == other.states
 		&& inputAlphabet == other.inputAlphabet
 		&& initialStates == other.initialStates
@@ -183,20 +187,19 @@ bool UnknownAutomaton::operator==(const UnknownAutomaton& other) {
 		&& transitions == other.transitions;
 }
 
-std::ostream& operator<<(std::ostream& out, const UnknownAutomaton& automaton) {
+void UnknownAutomaton::operator>>(std::ostream& out) const {
 	out << "(UnknownAutomaton"
-		<< " states = " << automaton.states
-		<< " inputAlphabet = " << automaton.inputAlphabet
-		<< " initialStates = " << automaton.initialStates
-		<< " finalStates = " << automaton.finalStates
-		<< " stackAlphabet = " << automaton.stackAlphabet
-		<< " initialSymbols = " << automaton.initialSymbols
-		<< " tapeAlphabet = " << automaton.tapeAlphabet
+		<< " states = " << states
+		<< " inputAlphabet = " << inputAlphabet
+		<< " initialStates = " << initialStates
+		<< " finalStates = " << finalStates
+		<< " stackAlphabet = " << stackAlphabet
+		<< " initialSymbols = " << initialSymbols
+		<< " tapeAlphabet = " << tapeAlphabet
 		<< " blankSymbol = ";
-	if(automaton.blankSymbol == NULL) out << "NULL"; else out << *automaton.blankSymbol;
-	out << " transitions = " << automaton.transitions
+	if(blankSymbol == NULL) out << "NULL"; else out << *blankSymbol;
+	out << " transitions = " << transitions
 		<< ")";
-	return out;
 }
 
 } /* namespace automaton */
diff --git a/alib2/src/automaton/UnknownAutomaton.h b/alib2/src/automaton/UnknownAutomaton.h
index 550083484f..eb22448943 100644
--- a/alib2/src/automaton/UnknownAutomaton.h
+++ b/alib2/src/automaton/UnknownAutomaton.h
@@ -21,7 +21,7 @@ namespace automaton {
 /**
  * Class representing unknown automaton parsed from XML.
  */
-class UnknownAutomaton : public Automaton {
+class UnknownAutomaton : public Automaton, public std::element<UnknownAutomaton, Automaton::visitor_type> {
 protected:
 	std::set<State> states;
 	std::set<State> initialStates;
@@ -271,9 +271,11 @@ public:
 	 * Compares two instances of UnknownAutomata
 	 * @return true if this and other instance are same
 	 */
-	bool operator==(const UnknownAutomaton& other);
+	virtual bool operator==(const UnknownAutomaton& other) const;
 
-	friend std::ostream& operator<<(std::ostream&, const UnknownAutomaton&);
+	virtual bool operator==(const Automaton& other) const;
+
+	virtual void operator>>(std::ostream& os) const;
 };
 
 } /* namespace automaton */
diff --git a/alib2/src/automaton/UnknownAutomatonToXMLComposer.cpp b/alib2/src/automaton/UnknownAutomatonToXMLComposer.cpp
deleted file mode 100644
index cc08fd1137..0000000000
--- a/alib2/src/automaton/UnknownAutomatonToXMLComposer.cpp
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * UnknownAutomatonToXMLComposer.cpp
- *
- *  Created on: Nov 11, 2013
- *      Author: martin
- */
-
-#include "UnknownAutomatonToXMLComposer.h"
-
-namespace automaton {
-
-void UnknownAutomatonToXMLComposer::printStates(std::list<sax::Token>& out, const std::set<State>& states, std::string tagName) {
-	out.push_back(sax::Token(tagName, sax::Token::START_ELEMENT));
-	for (auto& state : states) {
-		printState(out, state, "state");
-	}
-	out.push_back(sax::Token(tagName, sax::Token::END_ELEMENT));
-}
-
-void UnknownAutomatonToXMLComposer::printSymbols(std::list<sax::Token>& out, const std::set<alphabet::Symbol>& alphabet, std::string tagName) {
-	out.push_back(sax::Token(tagName, sax::Token::START_ELEMENT));
-	for (auto& symbol : alphabet) {
-		printSymbol(out, symbol, "symbol");
-	}
-	out.push_back(sax::Token(tagName, sax::Token::END_ELEMENT));
-}
-
-void UnknownAutomatonToXMLComposer::printSymbols(std::list<sax::Token>& out, const std::vector<alphabet::Symbol>& alphabet, std::string tagName) {
-	out.push_back(sax::Token(tagName, sax::Token::START_ELEMENT));
-	for (auto& symbol : alphabet) {
-		printSymbol(out, symbol, "symbol");
-	}
-	out.push_back(sax::Token(tagName, sax::Token::END_ELEMENT));
-}
-
-void UnknownAutomatonToXMLComposer::printUnknownTransitions(std::list<sax::Token>& out, const std::set<UnknownTransition>& transitions) {
-	out.push_back(sax::Token("transitions", sax::Token::START_ELEMENT));
-	for (auto& transition : transitions) {
-		out.push_back(sax::Token("transition", sax::Token::START_ELEMENT));
-		
-		if (transition.hasFrom()) {
-			printState(out, transition.getFrom(), "from");
-		}
-
-		if(transition.hasInput()) {
-			printInput(out, transition.getInput(), "input");
-		}
-		
-		if(transition.hasTo()) {
-			printState(out, transition.getTo(), "to");
-		}
-
-		if (transition.getPop().size() > 0) {
-			printSymbols(out, transition.getPop(), "pop");
-		}
-		if (transition.getPush().size() > 0) {
-			printSymbols(out, transition.getPush(), "push");
-		}
-
-		if (transition.hasOutput()) {
-			printInput(out, transition.getOutput(), "output");
-		}
-
-		if (transition.getShift() != Shift::NOT_SET) {
-			printShift(out, transition.getShift(), "shift");
-		}
-
-		out.push_back(sax::Token("transition", sax::Token::END_ELEMENT));
-	}
-
-	out.push_back(sax::Token("transitions", sax::Token::END_ELEMENT));
-}
-
-void UnknownAutomatonToXMLComposer::printState(std::list<sax::Token>& out, const State& state, std::string tagName) {
-	out.push_back(sax::Token(tagName, sax::Token::START_ELEMENT));
-	out.push_back(sax::Token(state.getName(), sax::Token::CHARACTER));
-	out.push_back(sax::Token(tagName, sax::Token::END_ELEMENT));
-}
-
-void UnknownAutomatonToXMLComposer::printInput(std::list<sax::Token>& out, const std::variant<string::Epsilon, alphabet::Symbol>& symbol, std::string tagName) {
-	out.push_back(sax::Token(tagName, sax::Token::START_ELEMENT));
-	if(symbol.is<string::Epsilon>()) {
-		out.push_back(sax::Token("epsilon", sax::Token::START_ELEMENT));
-		out.push_back(sax::Token("epsilon", sax::Token::END_ELEMENT));
-	} else if(symbol.get<alphabet::Symbol>() == alphabet::Blank::BLANK) {
-		out.push_back(sax::Token("blank", sax::Token::START_ELEMENT));
-		out.push_back(sax::Token("blank", sax::Token::END_ELEMENT));
-	} else {
-		out.push_back(sax::Token(symbol.get<alphabet::Symbol>().getSymbol(), sax::Token::CHARACTER));
-	}
-	out.push_back(sax::Token(tagName, sax::Token::END_ELEMENT));
-}
-
-void UnknownAutomatonToXMLComposer::printSymbol(std::list<sax::Token>& out, const alphabet::Symbol& symbol, std::string tagName) {
-	if(symbol == alphabet::Blank::BLANK) {
-		out.push_back(sax::Token("blank", sax::Token::START_ELEMENT));
-		out.push_back(sax::Token("blank", sax::Token::START_ELEMENT));
-	} else {
-		out.push_back(sax::Token(tagName, sax::Token::START_ELEMENT));
-		out.push_back(sax::Token(symbol.getSymbol(), sax::Token::CHARACTER));
-		out.push_back(sax::Token(tagName, sax::Token::END_ELEMENT));
-	}
-}
-
-void UnknownAutomatonToXMLComposer::printShift(std::list<sax::Token>& out, const Shift& shift, std::string tagName) {
-	out.push_back(sax::Token(tagName, sax::Token::START_ELEMENT));
-	out.push_back(sax::Token(SHIFT_NAMES [shift], sax::Token::CHARACTER));
-	out.push_back(sax::Token(tagName, sax::Token::END_ELEMENT));
-}
-
-std::list<sax::Token> UnknownAutomatonToXMLComposer::compose(const UnknownAutomaton& automaton) {
-	std::list<sax::Token> out;
-	out.push_back(sax::Token("automaton", sax::Token::START_ELEMENT));
-
-	if (automaton.getStates().size() > 0) {
-		printStates(out, automaton.getStates(), "states");
-	}
-
-	if (automaton.getInputSymbols().size() > 0) {
-		printSymbols(out, automaton.getInputSymbols(), "inputAlphabet");
-	}
-	if (automaton.getTapeSymbols().size() > 0) {
-		printSymbols(out, automaton.getTapeSymbols(), "tapeAlphabet");
-	}
-	if (automaton.getStackSymbols().size() > 0) {
-		printSymbols(out, automaton.getStackSymbols(), "stackAlphabet");
-	}
-
-	if (automaton.getTransitions().size() > 0) {
-		printUnknownTransitions(out, automaton.getTransitions());
-	}
-
-	if (automaton.hasBlankSymbol()) {
-		printSymbol(out, automaton.getBlankSymbol(), "blankSymbol");
-	}
-	if (automaton.getInitialSymbols().size() > 0) {
-		printSymbols(out, automaton.getInitialSymbols(), "startSymbols");
-	}
-
-	if (automaton.getInitialStates().size() > 0) {
-		printStates(out, automaton.getInitialStates(), "initialStates");
-	}
-	if (automaton.getFinalStates().size() > 0) {
-		printStates(out, automaton.getFinalStates(), "finalStates");
-	}
-
-	out.push_back(sax::Token("automaton", sax::Token::END_ELEMENT));
-	return out;
-}
-
-} /* namespace automaton */
-
diff --git a/alib2/src/automaton/UnknownAutomatonToXMLComposer.h b/alib2/src/automaton/UnknownAutomatonToXMLComposer.h
deleted file mode 100644
index 7325ebd1cf..0000000000
--- a/alib2/src/automaton/UnknownAutomatonToXMLComposer.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * UnknownAutomatonToXMLComposer.h
- *
- *  Created on: Nov 11, 2013
- *      Author: Jan Travnicek
- */
-
-#ifndef UNKNOWN_AUTOMATON_TO_XML_COMPOSER_H_
-#define UNKNOWN_AUTOMATON_TO_XML_COMPOSER_H_
-
-#include <string>
-#include "UnknownAutomaton.h"
-#include "../sax/Token.h"
-#include "../alphabet/Blank.h"
-
-namespace automaton {
-
-/**
- * This class contains methods to print XML representation of automata to the output stream.
- */
-class UnknownAutomatonToXMLComposer {
-protected:
-	static void printStates(std::list<sax::Token>&, const std::set<State>& states, std::string tagName);
-	static void printSymbols(std::list<sax::Token>&, const std::set<alphabet::Symbol>& alphabet, std::string tagName);
-	static void printSymbols(std::list<sax::Token>&, const std::vector<alphabet::Symbol>& alphabet, std::string tagName);
-	
-	static void printUnknownTransitions(std::list<sax::Token>&, const std::set<UnknownTransition>& transitions);
-
-	static void printState(std::list<sax::Token>&, const State& state, std::string tagName);
-	static void printSymbol(std::list<sax::Token>&, const alphabet::Symbol& symbol, std::string tagName);
-	static void printInput(std::list<sax::Token>&, const std::variant<string::Epsilon, alphabet::Symbol>&, std::string);
-	static void printShift(std::list<sax::Token>&, const Shift& shift, std::string tagName);
-
-public:
-	/**
-	 * Prints XML representation of UnknownAutomaton to the output stream.
-	 * @param automaton automaton to print
-	 * @return list of xml tokens representing the automaton
-	 */
-	std::list<sax::Token> compose(const UnknownAutomaton& automaton);
-};
-
-} /* namespace automaton */
-
-#endif /* AUTOMATON_TO_XML_COMPOSER_H_ */
-
diff --git a/alib2/src/factory/AutomatonFactory.cpp b/alib2/src/factory/AutomatonFactory.cpp
index 847bbf3c86..48a8a5a770 100644
--- a/alib2/src/factory/AutomatonFactory.cpp
+++ b/alib2/src/factory/AutomatonFactory.cpp
@@ -40,28 +40,28 @@ Automaton* AutomatonFactory::parse(std::list<sax::Token> tokens) {
 	return parser.parse(tokens);
 }
 
-void AutomatonFactory::toFile(const Automaton* automaton, const std::string& filename) {
+void AutomatonFactory::toFile(const Automaton& automaton, const std::string& filename) {
 	std::list<sax::Token> tokens = compose(automaton);
 	sax::SaxComposeInterface::printFile(filename, tokens);
 }
 
-std::string AutomatonFactory::toString(const Automaton* automaton) {
+std::string AutomatonFactory::toString(const Automaton& automaton) {
 	std::list<sax::Token> tokens = compose(automaton);
 	std::string str;
 	sax::SaxComposeInterface::printMemory(str, tokens);
 	return str;
 }
 
-void AutomatonFactory::toStdout(const Automaton* automaton) {
+void AutomatonFactory::toStdout(const Automaton& automaton) {
 	return AutomatonFactory::toStream(automaton, std::cout);
 }
 
-void AutomatonFactory::toStream(const Automaton* automaton, std::ostream& out) {
+void AutomatonFactory::toStream(const Automaton& automaton, std::ostream& out) {
 	std::list<sax::Token> tokens = compose(automaton);
 	sax::SaxComposeInterface::printStream(out, tokens);
 }
 
-std::list<sax::Token> AutomatonFactory::compose(const Automaton* automaton) {
+std::list<sax::Token> AutomatonFactory::compose(const Automaton& automaton) {
 	AutomatonToXMLComposer composer;
 	return composer.compose(automaton);
 }
diff --git a/alib2/src/factory/AutomatonFactory.h b/alib2/src/factory/AutomatonFactory.h
index 4f7152240f..91726ce29d 100644
--- a/alib2/src/factory/AutomatonFactory.h
+++ b/alib2/src/factory/AutomatonFactory.h
@@ -51,26 +51,26 @@ public:
 	 * @param filename path to the file
 	 * @return RegExp
 	 */
-	static void toFile(const Automaton*, const std::string& filename);
+	static void toFile(const Automaton&, const std::string& filename);
 
 	/**
 	 * Parses the XML and returns the RegExp.
 	 * @param str string containing the XML
 	 * @return RegExp
 	 */
-	static std::string toString(const Automaton*);
+	static std::string toString(const Automaton&);
 	
 	/**
 	 * Parses the XML from stdin and returns the RegExp.
 	 * @return RegExp
 	 */
-	static void toStdout(const Automaton*);
+	static void toStdout(const Automaton&);
 	
 	/**
 	 * Parses the XML from stream and returns the RegExp.
 	 * @return RegExp
 	 */
-	static void toStream(const Automaton*, std::ostream& out);
+	static void toStream(const Automaton&, std::ostream& out);
 	
 protected:
 
@@ -86,7 +86,7 @@ protected:
 	 * @param tokens XML represented as list of tokens
 	 * @return parsed RegExp
 	 */
-	static std::list<sax::Token> compose(const Automaton*);
+	static std::list<sax::Token> compose(const Automaton&);
 };
 
 } /* namespace automaton */
diff --git a/alib2/src/std/list.hpp b/alib2/src/std/list.hpp
index e208e17b3a..7833c1b8be 100644
--- a/alib2/src/std/list.hpp
+++ b/alib2/src/std/list.hpp
@@ -2,6 +2,15 @@
 #define __LIST_HPP_
 
 #include <list>
+
+template< class T >
+std::ostream& operator<<(std::ostream& out, const std::list<T>& list);
+
+#include "set.hpp"
+#include "map.hpp"
+#include "pair.hpp"
+#include "tuple.hpp"
+#include "vector.hpp"
 #include <iostream>
 
 namespace std {
@@ -23,5 +32,5 @@ std::ostream& operator<<(std::ostream& out, const std::list<T>& list) {
 
 } /* namespace std */
 
-#endif /* LIST_HPP_ */
+#endif /* __LIST_HPP_ */
 
diff --git a/alib2/src/std/map.hpp b/alib2/src/std/map.hpp
new file mode 100644
index 0000000000..4b2d78146a
--- /dev/null
+++ b/alib2/src/std/map.hpp
@@ -0,0 +1,36 @@
+#ifndef __MAP_HPP_
+#define __MAP_HPP_
+
+#include <map>
+
+template< class T, class R >
+std::ostream& operator<<(std::ostream& out, const std::map<T, R>& map);
+
+#include "set.hpp"
+#include "pair.hpp"
+#include "list.hpp"
+#include "tuple.hpp"
+#include "vector.hpp"
+#include <iostream>
+
+namespace std {
+
+template< class T, class R >
+std::ostream& operator<<(std::ostream& out, const std::map<T, R>& map) {
+	out << "{";
+
+	bool first = true;
+	for(const std::pair<T, R>& item : map) {
+		if(!first) out << ", ";
+		first = false;
+		out << item;
+	}
+
+	out << "}";
+	return out;
+}
+
+} /* namespace std */
+
+#endif /* __MAP_HPP_ */
+
diff --git a/alib2/src/std/pair.hpp b/alib2/src/std/pair.hpp
new file mode 100644
index 0000000000..c410e9f7d1
--- /dev/null
+++ b/alib2/src/std/pair.hpp
@@ -0,0 +1,27 @@
+#ifndef __PAIR_HPP_
+#define __PAIR_HPP_
+
+#include <map>
+
+template< class T, class R >
+std::ostream& operator<<(std::ostream& out, const std::pair<T, R>& pair);
+
+#include "set.hpp"
+#include "map.hpp"
+#include "list.hpp"
+#include "tuple.hpp"
+#include "vector.hpp"
+#include <iostream>
+
+namespace std {
+
+template< class T, class R >
+std::ostream& operator<<(std::ostream& out, const std::pair<T, R>& pair) {
+	out << "(" << pair.first << ", " << pair.second << ")";
+	return out;
+}
+
+} /* namespace std */
+
+#endif /* __PAIR_HPP_ */
+
diff --git a/alib2/src/std/set.hpp b/alib2/src/std/set.hpp
index 706f5f6b23..ef4e849372 100644
--- a/alib2/src/std/set.hpp
+++ b/alib2/src/std/set.hpp
@@ -2,6 +2,15 @@
 #define __SET_HPP_
 
 #include <set>
+
+template< class T >
+std::ostream& operator<<(std::ostream& out, const std::set<T>& list);
+
+#include "map.hpp"
+#include "pair.hpp"
+#include "list.hpp"
+#include "tuple.hpp"
+#include "vector.hpp"
 #include <iostream>
 
 namespace std {
@@ -23,5 +32,5 @@ std::ostream& operator<<(std::ostream& out, const std::set<T>& list) {
 
 } /* namespace std */
 
-#endif /* SET_HPP_ */
+#endif /* __SET_HPP_ */
 
diff --git a/alib2/src/std/tuple.hpp b/alib2/src/std/tuple.hpp
new file mode 100644
index 0000000000..f91f3402bf
--- /dev/null
+++ b/alib2/src/std/tuple.hpp
@@ -0,0 +1,52 @@
+#ifndef __TUPLE_HPP_
+#define __TUPLE_HPP_
+
+#include <tuple>
+
+template< class... Ts>
+std::ostream& operator<<(std::ostream& out, const std::tuple<Ts...>& tuple);
+
+#include "set.hpp"
+#include "map.hpp"
+#include "list.hpp"
+#include "pair.hpp"
+#include "vector.hpp"
+#include <iostream>
+
+namespace std {
+
+template<int I, class Tuple>
+struct operator_shift_left_impl;
+
+template<int I, class Tuple>
+struct operator_shift_left_impl {
+	static void operator_shift_left(ostream& out, const Tuple& t) {
+		operator_shift_left_impl<I - 1, Tuple>::operator_shift_left(out, t);
+		out << ", " << get<I>(t);
+	}
+};
+
+template<class Tuple>
+struct operator_shift_left_impl<0, Tuple> {
+	static void operator_shift_left(ostream& out, const Tuple& t) {
+		out << get<0>(t);
+	}
+};
+
+template<class Tuple>
+void operator_shift_left(ostream& out, const Tuple& t) {
+	operator_shift_left_impl<tuple_size<Tuple>::value - 1, Tuple>::operator_shift_left(out, t);
+}
+
+template< class... Ts>
+std::ostream& operator<<(std::ostream& out, const std::tuple<Ts...>& tuple) {
+	out << "(";
+	operator_shift_left(out, tuple);
+	out << ")";
+	return out;
+}
+
+} /* namespace std */
+
+#endif /* __TUPLE_HPP_ */
+
diff --git a/alib2/src/std/vector.hpp b/alib2/src/std/vector.hpp
index 9593e944da..a9c4017052 100644
--- a/alib2/src/std/vector.hpp
+++ b/alib2/src/std/vector.hpp
@@ -2,6 +2,15 @@
 #define __VECTOR_HPP_
 
 #include <vector>
+
+template< class T >
+std::ostream& operator<<(std::ostream& out, const std::vector<T>& vector);
+
+#include "set.hpp"
+#include "map.hpp"
+#include "pair.hpp"
+#include "tuple.hpp"
+#include "list.hpp"
 #include <iostream>
 
 namespace std {
@@ -23,4 +32,5 @@ std::ostream& operator<<(std::ostream& out, const std::vector<T>& vector) {
 
 } /* namespace std */
 
-#endif /* VECTOR_HPP_ */
\ No newline at end of file
+#endif /* __VECTOR_HPP_ */
+
diff --git a/alib2/test-src/automaton/AutomatonTest.cpp b/alib2/test-src/automaton/AutomatonTest.cpp
index 4178429211..919d79efeb 100644
--- a/alib2/test-src/automaton/AutomatonTest.cpp
+++ b/alib2/test-src/automaton/AutomatonTest.cpp
@@ -5,7 +5,6 @@
 #include "sax/SaxComposeInterface.h"
 
 #include "automaton/UnknownAutomaton.h"
-#include "automaton/UnknownAutomatonToXMLComposer.h"
 
 #include "automaton/FSM/DFA.h"
 #include "automaton/AutomatonFromXMLParser.h"
@@ -31,7 +30,7 @@ void AutomatonTest::testXMLParser() {
   
   CPPUNIT_ASSERT( automaton == automaton );
   {
-	automaton::UnknownAutomatonToXMLComposer composer;
+	automaton::AutomatonToXMLComposer composer;
 	std::list<sax::Token> tokens = composer.compose(automaton);
 	std::string tmp;
 	sax::SaxComposeInterface::printMemory(tmp, tokens);
@@ -44,11 +43,10 @@ void AutomatonTest::testXMLParser() {
 	CPPUNIT_ASSERT( automaton == automaton2 );
   }
   {
-//	std::string tmp = automaton::AutomatonFactory::toString(automaton);
-//	automaton::UnknownAutomaton automaton2 = automaton::AutomatonFactory::fromString(tmp);
-
-//	CPPUNIT_ASSERT( automaton == automaton2 );
+	std::string tmp = automaton::AutomatonFactory::toString(automaton);
+	automaton::Automaton* automaton2 = automaton::AutomatonFactory::fromString(tmp);
 
+	CPPUNIT_ASSERT( automaton == *automaton2 );
   }
 }
 
-- 
GitLab