From 7278c7e47fd07aeed878ee6745c88a473243f97d Mon Sep 17 00:00:00 2001
From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz>
Date: Mon, 22 Aug 2016 19:40:55 +0200
Subject: [PATCH] make automata compose helper templated

---
 .../common/AutomatonToXMLComposer.cpp         | 245 +-----------
 .../automaton/common/AutomatonToXMLComposer.h | 349 ++++++++++++++++--
 2 files changed, 323 insertions(+), 271 deletions(-)

diff --git a/alib2data/src/automaton/common/AutomatonToXMLComposer.cpp b/alib2data/src/automaton/common/AutomatonToXMLComposer.cpp
index 704c8af4a6..80af7ebe4a 100644
--- a/alib2data/src/automaton/common/AutomatonToXMLComposer.cpp
+++ b/alib2data/src/automaton/common/AutomatonToXMLComposer.cpp
@@ -7,252 +7,13 @@
 
 #include "AutomatonToXMLComposer.h"
 
-#include <XmlApi.hpp>
 #include "../../label/Label.h"
-#include "../../alphabet/RankedSymbol.h"
 #include "Shift.h"
 #include "../../string/StringClasses.h"
 #include "../../regexp/RegExp.h"
 
 namespace automaton {
 
-void AutomatonToXMLComposer::composeStates(std::deque<sax::Token>& out, const std::set<label::Label>& states) {
-	out.emplace_back("states", sax::Token::TokenType::START_ELEMENT);
-	for (const auto& state : states) {
-		alib::xmlApi<label::Label>::compose(out, state);
-	}
-	out.emplace_back("states", sax::Token::TokenType::END_ELEMENT);
-}
-
-void AutomatonToXMLComposer::composeInputAlphabet(std::deque<sax::Token>& out, const std::set<alphabet::Symbol>& symbols) {
-	out.emplace_back("inputAlphabet", sax::Token::TokenType::START_ELEMENT);
-	for (const auto& symbol : symbols) {
-		alib::xmlApi<alphabet::Symbol>::compose(out, symbol);
-	}
-	out.emplace_back("inputAlphabet", sax::Token::TokenType::END_ELEMENT);
-}
-
-void AutomatonToXMLComposer::composeCallInputAlphabet(std::deque<sax::Token>& out, const std::set<alphabet::Symbol>& symbols) {
-	out.emplace_back("callInputAlphabet", sax::Token::TokenType::START_ELEMENT);
-	for (const auto& symbol : symbols) {
-		alib::xmlApi<alphabet::Symbol>::compose(out, symbol);
-	}
-	out.emplace_back("callInputAlphabet", sax::Token::TokenType::END_ELEMENT);
-}
-
-void AutomatonToXMLComposer::composeReturnInputAlphabet(std::deque<sax::Token>& out, const std::set<alphabet::Symbol>& symbols) {
-	out.emplace_back("returnInputAlphabet", sax::Token::TokenType::START_ELEMENT);
-	for (const auto& symbol : symbols) {
-		alib::xmlApi<alphabet::Symbol>::compose(out, symbol);
-	}
-	out.emplace_back("returnInputAlphabet", sax::Token::TokenType::END_ELEMENT);
-}
-
-void AutomatonToXMLComposer::composeLocalInputAlphabet(std::deque<sax::Token>& out, const std::set<alphabet::Symbol>& symbols) {
-	out.emplace_back("localInputAlphabet", sax::Token::TokenType::START_ELEMENT);
-	for (const auto& symbol : symbols) {
-		alib::xmlApi<alphabet::Symbol>::compose(out, symbol);
-	}
-	out.emplace_back("localInputAlphabet", sax::Token::TokenType::END_ELEMENT);
-}
-
-void AutomatonToXMLComposer::composeRankedInputAlphabet(std::deque<sax::Token>& out, const std::set<alphabet::RankedSymbol>& symbols) {
-	out.emplace_back(sax::Token("rankedInputAlphabet", sax::Token::TokenType::START_ELEMENT));
-	for (const auto& symbol : symbols) {
-		alib::xmlApi<alphabet::RankedSymbol>::compose(out, symbol);
-	}
-	out.emplace_back(sax::Token("rankedInputAlphabet", sax::Token::TokenType::END_ELEMENT));
-}
-
-void AutomatonToXMLComposer::composeInitialStates(std::deque<sax::Token>& out, const std::set<label::Label>& states) {
-	out.emplace_back("initialStates", sax::Token::TokenType::START_ELEMENT);
-	for (const auto& state : states) {
-		alib::xmlApi<label::Label>::compose(out, state);
-	}
-	out.emplace_back("initialStates", sax::Token::TokenType::END_ELEMENT);
-}
-
-void AutomatonToXMLComposer::composeInitialState(std::deque<sax::Token>& out, const label::Label& state) {
-	out.emplace_back("initialState", sax::Token::TokenType::START_ELEMENT);
-	alib::xmlApi<label::Label>::compose(out, state);
-	out.emplace_back("initialState", sax::Token::TokenType::END_ELEMENT);
-}
-
-void AutomatonToXMLComposer::composeFinalStates(std::deque<sax::Token>& out, const std::set<label::Label>& states) {
-	out.emplace_back("finalStates", sax::Token::TokenType::START_ELEMENT);
-	for (const auto& state : states) {
-		alib::xmlApi<label::Label>::compose(out, state);
-	}
-	out.emplace_back("finalStates", sax::Token::TokenType::END_ELEMENT);
-}
-
-void AutomatonToXMLComposer::composePushdownStoreAlphabet(std::deque<sax::Token>& out, const std::set<alphabet::Symbol>& symbols) {
-	out.emplace_back("pushdownStoreAlphabet", sax::Token::TokenType::START_ELEMENT);
-	for (const auto& symbol : symbols) {
-		alib::xmlApi<alphabet::Symbol>::compose(out, symbol);
-	}
-	out.emplace_back("pushdownStoreAlphabet", sax::Token::TokenType::END_ELEMENT);
-}
-
-void AutomatonToXMLComposer::composeInitialPushdownStoreSymbols(std::deque<sax::Token>& out, const std::set<alphabet::Symbol>& symbols) {
-	out.emplace_back("initialPushdownStoreSymbols", sax::Token::TokenType::START_ELEMENT);
-	for (const auto& symbol : symbols) {
-		alib::xmlApi<alphabet::Symbol>::compose(out, symbol);
-	}
-	out.emplace_back("initialPushdownStoreSymbols", sax::Token::TokenType::END_ELEMENT);
-}
-
-void AutomatonToXMLComposer::composeInitialPushdownStoreSymbol(std::deque<sax::Token>& out, const alphabet::Symbol& symbol) {
-	out.emplace_back("initialPushdownStoreSymbol", sax::Token::TokenType::START_ELEMENT);
-	alib::xmlApi<alphabet::Symbol>::compose(out, symbol);
-	out.emplace_back("initialPushdownStoreSymbol", sax::Token::TokenType::END_ELEMENT);
-}
-
-void AutomatonToXMLComposer::composeOutputAlphabet(std::deque<sax::Token>& out, const std::set<alphabet::Symbol>& symbols) {
-	out.emplace_back("outputAlphabet", sax::Token::TokenType::START_ELEMENT);
-	for (const auto& symbol : symbols) {
-		alib::xmlApi<alphabet::Symbol>::compose(out, symbol);
-	}
-	out.emplace_back("outputAlphabet", sax::Token::TokenType::END_ELEMENT);
-}
-
-void AutomatonToXMLComposer::composeTapeAlphabet(std::deque<sax::Token>& out, const std::set<alphabet::Symbol>& symbols) {
-	out.emplace_back("tapeAlphabet", sax::Token::TokenType::START_ELEMENT);
-	for (const auto& symbol : symbols) {
-		alib::xmlApi<alphabet::Symbol>::compose(out, symbol);
-	}
-	out.emplace_back("tapeAlphabet", sax::Token::TokenType::END_ELEMENT);
-}
-
-void AutomatonToXMLComposer::composeBlankSymbol(std::deque<sax::Token>& out, const alphabet::Symbol& symbol) {
-	out.emplace_back("blankSymbol", sax::Token::TokenType::START_ELEMENT);
-	alib::xmlApi<alphabet::Symbol>::compose(out, symbol);
-	out.emplace_back("blankSymbol", sax::Token::TokenType::END_ELEMENT);
-}
-
-void AutomatonToXMLComposer::composeBottomOfTheStackSymbol(std::deque<sax::Token>& out, const alphabet::Symbol& symbol) {
-	out.emplace_back("bottomOfTheStackSymbol", sax::Token::TokenType::START_ELEMENT);
-	alib::xmlApi<alphabet::Symbol>::compose(out, symbol);
-	out.emplace_back("bottomOfTheStackSymbol", sax::Token::TokenType::END_ELEMENT);
-}
-
-void AutomatonToXMLComposer::composeInputToPushdownStoreOperation(std::deque<sax::Token>& out, const std::map<alphabet::Symbol, std::pair<std::vector<alphabet::Symbol>, std::vector<alphabet::Symbol> > >& operations) {
-	out.emplace_back("inputToPushdownStoreOperations", sax::Token::TokenType::START_ELEMENT);
-	for(const auto& pushdownStoreOperation : operations) {
-		out.emplace_back("operation", sax::Token::TokenType::START_ELEMENT);
-
-		alib::xmlApi<alphabet::Symbol>::compose(out, pushdownStoreOperation.first);
-
-		composeTransitionPop(out, pushdownStoreOperation.second.first);
-		composeTransitionPush(out, pushdownStoreOperation.second.second);
-
-		out.emplace_back("operation", sax::Token::TokenType::END_ELEMENT);
-	}
-	out.emplace_back("inputToPushdownStoreOperations", sax::Token::TokenType::END_ELEMENT);
-}
-
-void AutomatonToXMLComposer::composeTransitionTo(std::deque<sax::Token>& out, const label::Label& state) {
-	out.emplace_back("to", sax::Token::TokenType::START_ELEMENT);
-	alib::xmlApi<label::Label>::compose(out, state);
-	out.emplace_back("to", sax::Token::TokenType::END_ELEMENT);
-}
-
-void AutomatonToXMLComposer::composeTransitionFrom(std::deque<sax::Token>& out, const label::Label& state) {
-	out.emplace_back("from", sax::Token::TokenType::START_ELEMENT);
-	alib::xmlApi<label::Label>::compose(out, state);
-	out.emplace_back("from", sax::Token::TokenType::END_ELEMENT);
-}
-
-void AutomatonToXMLComposer::composeTransitionFrom(std::deque<sax::Token>& out, const std::vector<label::Label> & states) {
-	out.emplace_back(sax::Token("from", sax::Token::TokenType::START_ELEMENT));
-	for (const auto& state : states) {
-		alib::xmlApi<label::Label>::compose(out, state);
-	}
-	out.emplace_back(sax::Token("from", sax::Token::TokenType::END_ELEMENT));
-}
-
-void AutomatonToXMLComposer::composeTransitionShift(std::deque<sax::Token>& out, Shift shift) {
-	out.emplace_back("shift", sax::Token::TokenType::START_ELEMENT);
-	out.emplace_back(SHIFT_NAMES [shiftToInt(shift)], sax::Token::TokenType::CHARACTER);
-	out.emplace_back("shift", sax::Token::TokenType::END_ELEMENT);
-}
-
-void AutomatonToXMLComposer::composeTransitionPop(std::deque<sax::Token>& out, const std::vector<alphabet::Symbol>& symbols) {
-	out.emplace_back("pop", sax::Token::TokenType::START_ELEMENT);
-	for (const auto& symbol : symbols) {
-		alib::xmlApi<alphabet::Symbol>::compose(out, symbol);
-	}
-	out.emplace_back("pop", sax::Token::TokenType::END_ELEMENT);
-}
-
-void AutomatonToXMLComposer::composeTransitionSinglePop(std::deque<sax::Token>& out, const alphabet::Symbol& symbol) {
-	out.emplace_back("pop", sax::Token::TokenType::START_ELEMENT);
-	alib::xmlApi<alphabet::Symbol>::compose(out, symbol);
-	out.emplace_back("pop", sax::Token::TokenType::END_ELEMENT);
-}
-
-void AutomatonToXMLComposer::composeTransitionPush(std::deque<sax::Token>& out, const std::vector<alphabet::Symbol>& symbols) {
-	out.emplace_back("push", sax::Token::TokenType::START_ELEMENT);
-	for (const auto& symbol : symbols) {
-		alib::xmlApi<alphabet::Symbol>::compose(out, symbol);
-	}
-	out.emplace_back("push", sax::Token::TokenType::END_ELEMENT);
-}
-
-void AutomatonToXMLComposer::composeTransitionSinglePush(std::deque<sax::Token>& out, const alphabet::Symbol& symbol) {
-	out.emplace_back("push", sax::Token::TokenType::START_ELEMENT);
-	alib::xmlApi<alphabet::Symbol>::compose(out, symbol);
-	out.emplace_back("push", sax::Token::TokenType::END_ELEMENT);
-}
-
-void AutomatonToXMLComposer::composeTransitionInputSymbol(std::deque<sax::Token>& out, const alphabet::Symbol& symbol) {
-	out.emplace_back("input", sax::Token::TokenType::START_ELEMENT);
-	alib::xmlApi<alphabet::Symbol>::compose(out, symbol);
-	out.emplace_back("input", sax::Token::TokenType::END_ELEMENT);
-}
-
-void AutomatonToXMLComposer::composeTransitionInputSymbol(std::deque<sax::Token>& out, const alphabet::RankedSymbol& symbol) {
-	out.emplace_back(sax::Token("input", sax::Token::TokenType::START_ELEMENT));
-	alib::xmlApi<alphabet::RankedSymbol>::compose(out, symbol);
-	out.emplace_back(sax::Token("input", sax::Token::TokenType::END_ELEMENT));
-}
-
-void AutomatonToXMLComposer::composeTransitionOutputSymbol(std::deque<sax::Token>& out, const alphabet::Symbol& symbol) {
-	out.emplace_back("output", sax::Token::TokenType::START_ELEMENT);
-	alib::xmlApi<alphabet::Symbol>::compose(out, symbol);
-	out.emplace_back("output", sax::Token::TokenType::END_ELEMENT);
-}
-
-void AutomatonToXMLComposer::composeTransitionOutputSymbolMultiple(std::deque<sax::Token>& out, const std::vector<alphabet::Symbol>& symbols) {
-	out.emplace_back("output", sax::Token::TokenType::START_ELEMENT);
-	for (const auto& symbol : symbols) {
-		alib::xmlApi<alphabet::Symbol>::compose(out, symbol);
-	}
-	out.emplace_back("output", sax::Token::TokenType::END_ELEMENT);
-}
-
-void AutomatonToXMLComposer::composeTransitionInputEpsilonSymbol(std::deque<sax::Token>& out, const std::variant<string::Epsilon, alphabet::Symbol>& symbol) {
-	out.emplace_back("input", sax::Token::TokenType::START_ELEMENT);
-	if(symbol.is<string::Epsilon>()) {
-		out.emplace_back("epsilon", sax::Token::TokenType::START_ELEMENT);
-		out.emplace_back("epsilon", sax::Token::TokenType::END_ELEMENT);
-	} else {
-		alib::xmlApi<alphabet::Symbol>::compose(out, symbol.get<alphabet::Symbol>());
-	}
-	out.emplace_back("input", sax::Token::TokenType::END_ELEMENT);
-}
-
-void AutomatonToXMLComposer::composeTransitionOutputEpsilonSymbol(std::deque<sax::Token>& out, const std::variant<string::Epsilon, alphabet::Symbol>& symbol) {
-	out.emplace_back("output", sax::Token::TokenType::START_ELEMENT);
-	if(symbol.is<string::Epsilon>()) {
-		out.emplace_back("epsilon", sax::Token::TokenType::START_ELEMENT);
-		out.emplace_back("epsilon", sax::Token::TokenType::END_ELEMENT);
-	} else {
-		alib::xmlApi<alphabet::Symbol>::compose(out, symbol.get<alphabet::Symbol>());
-	}
-	out.emplace_back("output", sax::Token::TokenType::END_ELEMENT);
-}
-
 void AutomatonToXMLComposer::composeTransitionInputString(std::deque<sax::Token>& out, const string::LinearString& string) {
 	out.emplace_back("input", sax::Token::TokenType::START_ELEMENT);
 	alib::xmlApi<string::LinearString>::compose(out, string);
@@ -265,5 +26,11 @@ void AutomatonToXMLComposer::composeTransitionInputRegexp(std::deque<sax::Token>
 	out.emplace_back("input", sax::Token::TokenType::END_ELEMENT);
 }
 
+void AutomatonToXMLComposer::composeTransitionShift(std::deque<sax::Token>& out, Shift shift) {
+	out.emplace_back("shift", sax::Token::TokenType::START_ELEMENT);
+	out.emplace_back(SHIFT_NAMES [shiftToInt(shift)], sax::Token::TokenType::CHARACTER);
+	out.emplace_back("shift", sax::Token::TokenType::END_ELEMENT);
+}
+
 } /* namespace automaton */
 
diff --git a/alib2data/src/automaton/common/AutomatonToXMLComposer.h b/alib2data/src/automaton/common/AutomatonToXMLComposer.h
index 92fc72f83c..271df1301f 100644
--- a/alib2data/src/automaton/common/AutomatonToXMLComposer.h
+++ b/alib2data/src/automaton/common/AutomatonToXMLComposer.h
@@ -20,6 +20,7 @@
 #include "../../string/StringFeatures.h"
 #include "../../label/LabelFeatures.h"
 #include <sax/Token.h>
+#include <XmlApi.hpp>
 
 namespace automaton {
 
@@ -28,42 +29,326 @@ namespace automaton {
  */
 class AutomatonToXMLComposer {
 public:
-	static void composeStates(std::deque<sax::Token>&, const std::set<label::Label>& states);
-	static void composeInputAlphabet(std::deque<sax::Token>&, const std::set<alphabet::Symbol>& symbols);
-	static void composeCallInputAlphabet(std::deque<sax::Token>&, const std::set<alphabet::Symbol>& symbols);
-	static void composeReturnInputAlphabet(std::deque<sax::Token>&, const std::set<alphabet::Symbol>& symbols);
-	static void composeLocalInputAlphabet(std::deque<sax::Token>&, const std::set<alphabet::Symbol>& symbols);
-	static void composeRankedInputAlphabet(std::deque<sax::Token>&, const std::set<alphabet::RankedSymbol>& symbols);
-	static void composeInitialStates(std::deque<sax::Token>&, const std::set<label::Label>& states);
-	static void composeInitialState(std::deque<sax::Token>&, const label::Label& state);
-	static void composeFinalStates(std::deque<sax::Token>&, const std::set<label::Label>& states);
-	static void composePushdownStoreAlphabet(std::deque<sax::Token>&, const std::set<alphabet::Symbol>& symbols);
-	static void composeInitialPushdownStoreSymbols(std::deque<sax::Token>&, const std::set<alphabet::Symbol>& symbols);
-	static void composeInitialPushdownStoreSymbol(std::deque<sax::Token>&, const alphabet::Symbol& symbols);
-	static void composeOutputAlphabet(std::deque<sax::Token>&, const std::set<alphabet::Symbol>& symbols);
-	static void composeTapeAlphabet(std::deque<sax::Token>&, const std::set<alphabet::Symbol>& symbols);
-	static void composeBlankSymbol(std::deque<sax::Token>&, const alphabet::Symbol& symbol);
-	static void composeBottomOfTheStackSymbol(std::deque<sax::Token>&, const alphabet::Symbol& symbol);
-	static void composeInputToPushdownStoreOperation(std::deque<sax::Token>&, const std::map<alphabet::Symbol, std::pair<std::vector<alphabet::Symbol>, std::vector<alphabet::Symbol> > >& operations);
-
-	static void composeTransitionTo(std::deque<sax::Token>&, const label::Label& state);
-	static void composeTransitionFrom(std::deque<sax::Token>&, const label::Label& state);
-	static void composeTransitionFrom(std::deque<sax::Token>&, const std::vector<label::Label> & states);
-	static void composeTransitionShift(std::deque<sax::Token>&, Shift shift);
-	static void composeTransitionPop(std::deque<sax::Token>&, const std::vector<alphabet::Symbol>& symbols);
-	static void composeTransitionSinglePop(std::deque<sax::Token>&, const alphabet::Symbol& symbol);
-	static void composeTransitionPush(std::deque<sax::Token>&, const std::vector<alphabet::Symbol>& symbols);
-	static void composeTransitionSinglePush(std::deque<sax::Token>&, const alphabet::Symbol& symbol);
-	static void composeTransitionInputSymbol(std::deque<sax::Token>&, const alphabet::Symbol& symbol);
-	static void composeTransitionInputSymbol(std::deque<sax::Token>&, const alphabet::RankedSymbol& symbol);
-	static void composeTransitionInputEpsilonSymbol(std::deque<sax::Token>&, const std::variant<string::Epsilon, alphabet::Symbol>&);
-	static void composeTransitionOutputSymbol(std::deque<sax::Token>&, const alphabet::Symbol& symbol);
-	static void composeTransitionOutputEpsilonSymbol(std::deque<sax::Token>&, const std::variant<string::Epsilon, alphabet::Symbol>&);
-	static void composeTransitionOutputSymbolMultiple(std::deque<sax::Token>&, const std::vector<alphabet::Symbol>& symbols);
+	template<class StateType>
+	static void composeStates(std::deque<sax::Token>&, const std::set<StateType>& states);
+	template<class SymbolType>
+	static void composeInputAlphabet(std::deque<sax::Token>&, const std::set<SymbolType>& symbols);
+	template<class SymbolType>
+	static void composeCallInputAlphabet(std::deque<sax::Token>&, const std::set<SymbolType>& symbols);
+	template<class SymbolType>
+	static void composeReturnInputAlphabet(std::deque<sax::Token>&, const std::set<SymbolType>& symbols);
+	template<class SymbolType>
+	static void composeLocalInputAlphabet(std::deque<sax::Token>&, const std::set<SymbolType>& symbols);
+	template<class SymbolType>
+	static void composeRankedInputAlphabet(std::deque<sax::Token>&, const std::set<SymbolType>& symbols);
+	template<class StateType>
+	static void composeInitialStates(std::deque<sax::Token>&, const std::set<StateType>& states);
+	template<class StateType>
+	static void composeInitialState(std::deque<sax::Token>&, const StateType& state);
+	template<class StateType>
+	static void composeFinalStates(std::deque<sax::Token>&, const std::set<StateType>& states);
+	template<class SymbolType>
+	static void composePushdownStoreAlphabet(std::deque<sax::Token>&, const std::set<SymbolType>& symbols);
+	template<class SymbolType>
+	static void composeInitialPushdownStoreSymbols(std::deque<sax::Token>&, const std::set<SymbolType>& symbols);
+	template<class SymbolType>
+	static void composeInitialPushdownStoreSymbol(std::deque<sax::Token>&, const SymbolType& symbols);
+	template<class SymbolType>
+	static void composeOutputAlphabet(std::deque<sax::Token>&, const std::set<SymbolType>& symbols);
+	template<class SymbolType>
+	static void composeTapeAlphabet(std::deque<sax::Token>&, const std::set<SymbolType>& symbols);
+	template<class SymbolType>
+	static void composeBlankSymbol(std::deque<sax::Token>&, const SymbolType& symbol);
+	template<class SymbolType>
+	static void composeBottomOfTheStackSymbol(std::deque<sax::Token>&, const SymbolType& symbol);
+	template<class SymbolType>
+	static void composeInputToPushdownStoreOperation(std::deque<sax::Token>&, const std::map<SymbolType, std::pair<std::vector<SymbolType>, std::vector<SymbolType> > >& operations);
+
+	template<class StateType>
+	static void composeTransitionTo(std::deque<sax::Token>&, const StateType& state);
+	template<class StateType>
+	static void composeTransitionFrom(std::deque<sax::Token>&, const StateType& state);
+	template<class StateType>
+	static void composeTransitionFrom(std::deque<sax::Token>&, const std::vector<StateType> & states);
+	template<class SymbolType>
+	static void composeTransitionPop(std::deque<sax::Token>&, const std::vector<SymbolType>& symbols);
+	template<class SymbolType>
+	static void composeTransitionSinglePop(std::deque<sax::Token>&, const SymbolType& symbol);
+	template<class SymbolType>
+	static void composeTransitionPush(std::deque<sax::Token>&, const std::vector<SymbolType>& symbols);
+	template<class SymbolType>
+	static void composeTransitionSinglePush(std::deque<sax::Token>&, const SymbolType& symbol);
+	template<class SymbolType>
+	static void composeTransitionInputSymbol(std::deque<sax::Token>&, const SymbolType& symbol);
+	template<class EpsilonType, class SymbolType>
+	static void composeTransitionInputEpsilonSymbol(std::deque<sax::Token>&, const std::variant<EpsilonType, SymbolType>&);
+	template<class SymbolType>
+	static void composeTransitionOutputSymbol(std::deque<sax::Token>&, const SymbolType& symbol);
+	template<class EpsilonType, class SymbolType>
+	static void composeTransitionOutputEpsilonSymbol(std::deque<sax::Token>&, const std::variant<EpsilonType, SymbolType>&);
+	template<class SymbolType>
+	static void composeTransitionOutputSymbolMultiple(std::deque<sax::Token>&, const std::vector<SymbolType>& symbols);
+
 	static void composeTransitionInputString(std::deque<sax::Token>&, const string::LinearString& string);
 	static void composeTransitionInputRegexp(std::deque<sax::Token>&, const regexp::RegExp& regexp);
+
+	static void composeTransitionShift(std::deque<sax::Token>&, Shift shift);
 };
 
+template < class StateType >
+void AutomatonToXMLComposer::composeStates(std::deque<sax::Token>& out, const std::set<StateType>& states) {
+	out.emplace_back("states", sax::Token::TokenType::START_ELEMENT);
+	for (const auto& state : states) {
+		alib::xmlApi<StateType>::compose(out, state);
+	}
+	out.emplace_back("states", sax::Token::TokenType::END_ELEMENT);
+}
+
+template < class SymbolType >
+void AutomatonToXMLComposer::composeInputAlphabet(std::deque<sax::Token>& out, const std::set<SymbolType>& symbols) {
+	out.emplace_back("inputAlphabet", sax::Token::TokenType::START_ELEMENT);
+	for (const auto& symbol : symbols) {
+		alib::xmlApi<SymbolType>::compose(out, symbol);
+	}
+	out.emplace_back("inputAlphabet", sax::Token::TokenType::END_ELEMENT);
+}
+
+template < class SymbolType >
+void AutomatonToXMLComposer::composeCallInputAlphabet(std::deque<sax::Token>& out, const std::set<SymbolType>& symbols) {
+	out.emplace_back("callInputAlphabet", sax::Token::TokenType::START_ELEMENT);
+	for (const auto& symbol : symbols) {
+		alib::xmlApi<SymbolType>::compose(out, symbol);
+	}
+	out.emplace_back("callInputAlphabet", sax::Token::TokenType::END_ELEMENT);
+}
+
+template < class SymbolType >
+void AutomatonToXMLComposer::composeReturnInputAlphabet(std::deque<sax::Token>& out, const std::set<SymbolType>& symbols) {
+	out.emplace_back("returnInputAlphabet", sax::Token::TokenType::START_ELEMENT);
+	for (const auto& symbol : symbols) {
+		alib::xmlApi<SymbolType>::compose(out, symbol);
+	}
+	out.emplace_back("returnInputAlphabet", sax::Token::TokenType::END_ELEMENT);
+}
+
+template < class SymbolType >
+void AutomatonToXMLComposer::composeLocalInputAlphabet(std::deque<sax::Token>& out, const std::set<SymbolType>& symbols) {
+	out.emplace_back("localInputAlphabet", sax::Token::TokenType::START_ELEMENT);
+	for (const auto& symbol : symbols) {
+		alib::xmlApi<SymbolType>::compose(out, symbol);
+	}
+	out.emplace_back("localInputAlphabet", sax::Token::TokenType::END_ELEMENT);
+}
+
+template < class SymbolType >
+void AutomatonToXMLComposer::composeRankedInputAlphabet(std::deque<sax::Token>& out, const std::set<SymbolType>& symbols) {
+	out.emplace_back("rankedInputAlphabet", sax::Token::TokenType::START_ELEMENT);
+	for (const auto& symbol : symbols) {
+		alib::xmlApi<SymbolType>::compose(out, symbol);
+	}
+	out.emplace_back("rankedInputAlphabet", sax::Token::TokenType::END_ELEMENT);
+}
+
+template < class StateType >
+void AutomatonToXMLComposer::composeInitialStates(std::deque<sax::Token>& out, const std::set<StateType>& states) {
+	out.emplace_back("initialStates", sax::Token::TokenType::START_ELEMENT);
+	for (const auto& state : states) {
+		alib::xmlApi<StateType>::compose(out, state);
+	}
+	out.emplace_back("initialStates", sax::Token::TokenType::END_ELEMENT);
+}
+
+template < class StateType >
+void AutomatonToXMLComposer::composeInitialState(std::deque<sax::Token>& out, const StateType& state) {
+	out.emplace_back("initialState", sax::Token::TokenType::START_ELEMENT);
+	alib::xmlApi<StateType>::compose(out, state);
+	out.emplace_back("initialState", sax::Token::TokenType::END_ELEMENT);
+}
+
+template < class StateType >
+void AutomatonToXMLComposer::composeFinalStates(std::deque<sax::Token>& out, const std::set<StateType>& states) {
+	out.emplace_back("finalStates", sax::Token::TokenType::START_ELEMENT);
+	for (const auto& state : states) {
+		alib::xmlApi<StateType>::compose(out, state);
+	}
+	out.emplace_back("finalStates", sax::Token::TokenType::END_ELEMENT);
+}
+
+template < class SymbolType >
+void AutomatonToXMLComposer::composePushdownStoreAlphabet(std::deque<sax::Token>& out, const std::set<SymbolType>& symbols) {
+	out.emplace_back("pushdownStoreAlphabet", sax::Token::TokenType::START_ELEMENT);
+	for (const auto& symbol : symbols) {
+		alib::xmlApi<SymbolType>::compose(out, symbol);
+	}
+	out.emplace_back("pushdownStoreAlphabet", sax::Token::TokenType::END_ELEMENT);
+}
+
+template < class SymbolType >
+void AutomatonToXMLComposer::composeInitialPushdownStoreSymbols(std::deque<sax::Token>& out, const std::set<SymbolType>& symbols) {
+	out.emplace_back("initialPushdownStoreSymbols", sax::Token::TokenType::START_ELEMENT);
+	for (const auto& symbol : symbols) {
+		alib::xmlApi<SymbolType>::compose(out, symbol);
+	}
+	out.emplace_back("initialPushdownStoreSymbols", sax::Token::TokenType::END_ELEMENT);
+}
+
+template < class SymbolType >
+void AutomatonToXMLComposer::composeInitialPushdownStoreSymbol(std::deque<sax::Token>& out, const SymbolType& symbol) {
+	out.emplace_back("initialPushdownStoreSymbol", sax::Token::TokenType::START_ELEMENT);
+	alib::xmlApi<SymbolType>::compose(out, symbol);
+	out.emplace_back("initialPushdownStoreSymbol", sax::Token::TokenType::END_ELEMENT);
+}
+
+template < class SymbolType >
+void AutomatonToXMLComposer::composeOutputAlphabet(std::deque<sax::Token>& out, const std::set<SymbolType>& symbols) {
+	out.emplace_back("outputAlphabet", sax::Token::TokenType::START_ELEMENT);
+	for (const auto& symbol : symbols) {
+		alib::xmlApi<SymbolType>::compose(out, symbol);
+	}
+	out.emplace_back("outputAlphabet", sax::Token::TokenType::END_ELEMENT);
+}
+
+template < class SymbolType >
+void AutomatonToXMLComposer::composeTapeAlphabet(std::deque<sax::Token>& out, const std::set<SymbolType>& symbols) {
+	out.emplace_back("tapeAlphabet", sax::Token::TokenType::START_ELEMENT);
+	for (const auto& symbol : symbols) {
+		alib::xmlApi<SymbolType>::compose(out, symbol);
+	}
+	out.emplace_back("tapeAlphabet", sax::Token::TokenType::END_ELEMENT);
+}
+
+template < class SymbolType >
+void AutomatonToXMLComposer::composeBlankSymbol(std::deque<sax::Token>& out, const SymbolType& symbol) {
+	out.emplace_back("blankSymbol", sax::Token::TokenType::START_ELEMENT);
+	alib::xmlApi<SymbolType>::compose(out, symbol);
+	out.emplace_back("blankSymbol", sax::Token::TokenType::END_ELEMENT);
+}
+
+template < class SymbolType >
+void AutomatonToXMLComposer::composeBottomOfTheStackSymbol(std::deque<sax::Token>& out, const SymbolType& symbol) {
+	out.emplace_back("bottomOfTheStackSymbol", sax::Token::TokenType::START_ELEMENT);
+	alib::xmlApi<SymbolType>::compose(out, symbol);
+	out.emplace_back("bottomOfTheStackSymbol", sax::Token::TokenType::END_ELEMENT);
+}
+
+template < class SymbolType >
+void AutomatonToXMLComposer::composeInputToPushdownStoreOperation(std::deque<sax::Token>& out, const std::map<SymbolType, std::pair<std::vector<SymbolType>, std::vector<SymbolType> > >& operations) {
+	out.emplace_back("inputToPushdownStoreOperations", sax::Token::TokenType::START_ELEMENT);
+	for(const auto& pushdownStoreOperation : operations) {
+		out.emplace_back("operation", sax::Token::TokenType::START_ELEMENT);
+
+		alib::xmlApi<SymbolType>::compose(out, pushdownStoreOperation.first);
+
+		composeTransitionPop(out, pushdownStoreOperation.second.first);
+		composeTransitionPush(out, pushdownStoreOperation.second.second);
+
+		out.emplace_back("operation", sax::Token::TokenType::END_ELEMENT);
+	}
+	out.emplace_back("inputToPushdownStoreOperations", sax::Token::TokenType::END_ELEMENT);
+}
+
+template < class StateType >
+void AutomatonToXMLComposer::composeTransitionTo(std::deque<sax::Token>& out, const StateType& state) {
+	out.emplace_back("to", sax::Token::TokenType::START_ELEMENT);
+	alib::xmlApi<StateType>::compose(out, state);
+	out.emplace_back("to", sax::Token::TokenType::END_ELEMENT);
+}
+
+template < class StateType >
+void AutomatonToXMLComposer::composeTransitionFrom(std::deque<sax::Token>& out, const StateType& state) {
+	out.emplace_back("from", sax::Token::TokenType::START_ELEMENT);
+	alib::xmlApi<StateType>::compose(out, state);
+	out.emplace_back("from", sax::Token::TokenType::END_ELEMENT);
+}
+
+template < class StateType >
+void AutomatonToXMLComposer::composeTransitionFrom(std::deque<sax::Token>& out, const std::vector<StateType> & states) {
+	out.emplace_back("from", sax::Token::TokenType::START_ELEMENT);
+	for (const auto& state : states) {
+		alib::xmlApi<StateType>::compose(out, state);
+	}
+	out.emplace_back("from", sax::Token::TokenType::END_ELEMENT);
+}
+
+template < class SymbolType >
+void AutomatonToXMLComposer::composeTransitionPop(std::deque<sax::Token>& out, const std::vector<SymbolType>& symbols) {
+	out.emplace_back("pop", sax::Token::TokenType::START_ELEMENT);
+	for (const auto& symbol : symbols) {
+		alib::xmlApi<SymbolType>::compose(out, symbol);
+	}
+	out.emplace_back("pop", sax::Token::TokenType::END_ELEMENT);
+}
+
+template < class SymbolType >
+void AutomatonToXMLComposer::composeTransitionSinglePop(std::deque<sax::Token>& out, const SymbolType& symbol) {
+	out.emplace_back("pop", sax::Token::TokenType::START_ELEMENT);
+	alib::xmlApi<SymbolType>::compose(out, symbol);
+	out.emplace_back("pop", sax::Token::TokenType::END_ELEMENT);
+}
+
+template < class SymbolType >
+void AutomatonToXMLComposer::composeTransitionPush(std::deque<sax::Token>& out, const std::vector<SymbolType>& symbols) {
+	out.emplace_back("push", sax::Token::TokenType::START_ELEMENT);
+	for (const auto& symbol : symbols) {
+		alib::xmlApi<SymbolType>::compose(out, symbol);
+	}
+	out.emplace_back("push", sax::Token::TokenType::END_ELEMENT);
+}
+
+template < class SymbolType >
+void AutomatonToXMLComposer::composeTransitionSinglePush(std::deque<sax::Token>& out, const SymbolType& symbol) {
+	out.emplace_back("push", sax::Token::TokenType::START_ELEMENT);
+	alib::xmlApi<SymbolType>::compose(out, symbol);
+	out.emplace_back("push", sax::Token::TokenType::END_ELEMENT);
+}
+
+template < class SymbolType >
+void AutomatonToXMLComposer::composeTransitionInputSymbol(std::deque<sax::Token>& out, const SymbolType& symbol) {
+	out.emplace_back("input", sax::Token::TokenType::START_ELEMENT);
+	alib::xmlApi<SymbolType>::compose(out, symbol);
+	out.emplace_back("input", sax::Token::TokenType::END_ELEMENT);
+}
+
+template < class SymbolType >
+void AutomatonToXMLComposer::composeTransitionOutputSymbol(std::deque<sax::Token>& out, const SymbolType& symbol) {
+	out.emplace_back("output", sax::Token::TokenType::START_ELEMENT);
+	alib::xmlApi<SymbolType>::compose(out, symbol);
+	out.emplace_back("output", sax::Token::TokenType::END_ELEMENT);
+}
+
+template < class SymbolType >
+void AutomatonToXMLComposer::composeTransitionOutputSymbolMultiple(std::deque<sax::Token>& out, const std::vector<SymbolType>& symbols) {
+	out.emplace_back("output", sax::Token::TokenType::START_ELEMENT);
+	for (const auto& symbol : symbols) {
+		alib::xmlApi<SymbolType>::compose(out, symbol);
+	}
+	out.emplace_back("output", sax::Token::TokenType::END_ELEMENT);
+}
+
+template < class EpsilonType, class SymbolType >
+void AutomatonToXMLComposer::composeTransitionInputEpsilonSymbol(std::deque<sax::Token>& out, const std::variant<EpsilonType, SymbolType>& symbol) {
+	out.emplace_back("input", sax::Token::TokenType::START_ELEMENT);
+	if(symbol.template is<EpsilonType>()) {
+		out.emplace_back("epsilon", sax::Token::TokenType::START_ELEMENT);
+		out.emplace_back("epsilon", sax::Token::TokenType::END_ELEMENT);
+	} else {
+		alib::xmlApi<SymbolType>::compose(out, symbol.template get<SymbolType>());
+	}
+	out.emplace_back("input", sax::Token::TokenType::END_ELEMENT);
+}
+
+template < class EpsilonType, class SymbolType >
+void AutomatonToXMLComposer::composeTransitionOutputEpsilonSymbol(std::deque<sax::Token>& out, const std::variant<EpsilonType, SymbolType>& symbol) {
+	out.emplace_back("output", sax::Token::TokenType::START_ELEMENT);
+	if(symbol.template is<EpsilonType>()) {
+		out.emplace_back("epsilon", sax::Token::TokenType::START_ELEMENT);
+		out.emplace_back("epsilon", sax::Token::TokenType::END_ELEMENT);
+	} else {
+		alib::xmlApi<SymbolType>::compose(out, symbol.template get<SymbolType>());
+	}
+	out.emplace_back("output", sax::Token::TokenType::END_ELEMENT);
+}
+
 } /* namespace automaton */
 
 #endif /* AUTOMATON_TO_XML_COMPOSER_H_ */
-- 
GitLab