/*
 * GasTexConverter.h
 *
 *  Created on: Jan 1, 2014
 *      Author: Martin Zak
 */

#pragma once

#include <ostream>
#include <alib/map>
#include <alib/utility>
#include <alib/vector>
#include <alib/set>
#include <alib/typeinfo>

#include <exception/CommonException.h>
#include <string/String.h>

#include <automaton/FSM/NFA.h>
#include <automaton/FSM/MultiInitialStateNFA.h>
#include <automaton/FSM/EpsilonNFA.h>
#include <automaton/FSM/DFA.h>
#include <automaton/FSM/ExtendedNFA.h>
#include <automaton/FSM/CompactNFA.h>
#include <automaton/TA/NFTA.h>
#include <automaton/TA/DFTA.h>
#include <automaton/PDA/DPDA.h>
#include <automaton/PDA/SinglePopDPDA.h>
#include <automaton/PDA/InputDrivenDPDA.h>
#include <automaton/PDA/InputDrivenNPDA.h>
#include <automaton/PDA/VisiblyPushdownDPDA.h>
#include <automaton/PDA/VisiblyPushdownNPDA.h>
#include <automaton/PDA/RealTimeHeightDeterministicDPDA.h>
#include <automaton/PDA/RealTimeHeightDeterministicNPDA.h>
#include <automaton/PDA/NPDA.h>
#include <automaton/PDA/SinglePopNPDA.h>
#include <automaton/TM/OneTapeDTM.h>

#include "common/converterCommon.hpp"

#include <factory/StringDataFactory.hpp>
#include <string/string/LinearString.h>
#include <regexp/string/UnboundedRegExp.h>

namespace convert {

class GasTexConverter {
	static void printTransitionMap( const ext::map<std::pair<std::string, std::string>, std::string> & transitionMap, std::ostream& out);

	template < class SymbolType >
	static std::string getStackSymbols(const ext::vector<SymbolType>& stackSymbols);

	template < class SymbolType, class StateType >
	static void transitions(const automaton::DFA < SymbolType, StateType > & fsm, std::ostream & out);

	template < class SymbolType, class StateType >
	static void transitions(const automaton::NFA < SymbolType, StateType > & fsm, std::ostream & out);

	template < class SymbolType, class StateType >
	static void transitions(const automaton::MultiInitialStateNFA < SymbolType, StateType > & fsm, std::ostream & out);

	template < class SymbolType, class StateType >
	static void transitions(const automaton::EpsilonNFA < SymbolType, StateType > & fsm, std::ostream & out);

	template < class SymbolType, class StateType >
	static void transitions(const automaton::ExtendedNFA < SymbolType, StateType > & fsm, std::ostream & out);

	template < class SymbolType, class StateType >
	static void transitions(const automaton::CompactNFA < SymbolType, StateType > & fsm, std::ostream & out);

	template < class SymbolType, class StateType >
	static void transitions(const automaton::NFTA < SymbolType, StateType > & fsm, std::ostream & out);

	template < class SymbolType, class StateType >
	static void transitions(const automaton::DFTA < SymbolType, StateType > & fsm, std::ostream & out);

	template < class InputSymbolType, class PushdownStoreSymbolType, class StateType >
	static void transitions(const automaton::DPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & pda, std::ostream & out);

	template < class InputSymbolType, class PushdownStoreSymbolType, class StateType >
	static void transitions(const automaton::NPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & pda, std::ostream & out);

	template < class InputSymbolType, class PushdownStoreSymbolType, class StateType >
	static void transitions(const automaton::SinglePopDPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & pda, std::ostream & out);

	template < class InputSymbolType, class PushdownStoreSymbolType, class StateType >
	static void transitions(const automaton::SinglePopNPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & pda, std::ostream & out);

	template < class InputSymbolType, class PushdownStoreSymbolType, class StateType >
	static void transitions(const automaton::InputDrivenDPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & pda, std::ostream & out);

	template < class InputSymbolType, class PushdownStoreSymbolType, class StateType >
	static void transitions(const automaton::InputDrivenNPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & pda, std::ostream & out);

	template < class InputSymbolType, class PushdownStoreSymbolType, class StateType >
	static void transitions(const automaton::VisiblyPushdownDPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & pda, std::ostream & out);

	template < class InputSymbolType, class PushdownStoreSymbolType, class StateType >
	static void transitions(const automaton::VisiblyPushdownNPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & pda, std::ostream & out);

	template < class InputSymbolType, class PushdownStoreSymbolType, class StateType >
	static void transitions(const automaton::RealTimeHeightDeterministicDPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & pda, std::ostream & out);

	template < class InputSymbolType, class PushdownStoreSymbolType, class StateType >
	static void transitions(const automaton::RealTimeHeightDeterministicNPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & pda, std::ostream & out);

	template < class SymbolType, class StateType >
	static void transitions(const automaton::OneTapeDTM < SymbolType, StateType > & tm, std::ostream & out);
public:
	template < class SymbolType, class StateType >
	static void convert(std::ostream& out, const automaton::DFA < SymbolType, StateType > & a);

	template < class SymbolType, class StateType >
	static void convert(std::ostream& out, const automaton::NFA < SymbolType, StateType > & a);

	template < class SymbolType, class StateType >
	static void convert(std::ostream& out, const automaton::MultiInitialStateNFA < SymbolType, StateType >& a);

	template < class SymbolType, class StateType >
	static void convert(std::ostream& out, const automaton::EpsilonNFA < SymbolType, StateType > & a);

	template < class SymbolType, class StateType >
	static void convert(std::ostream& out, const automaton::ExtendedNFA < SymbolType, StateType > & a);

	template < class SymbolType, class StateType >
	static void convert(std::ostream& out, const automaton::CompactNFA < SymbolType, StateType > & a);

	template < class SymbolType, class StateType >
	static void convert(std::ostream& out, const automaton::NFTA < SymbolType, StateType > & a);

	template < class SymbolType, class StateType >
	static void convert(std::ostream& out, const automaton::DFTA < SymbolType, StateType > & a);

	template < class InputSymbolType, class PushdownStoreSymbolType, class StateType >
	static void convert(std::ostream& out, const automaton::DPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & a);

	template < class InputSymbolType, class PushdownStoreSymbolType, class StateType >
	static void convert(std::ostream& out, const automaton::NPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & a);

	template < class InputSymbolType, class PushdownStoreSymbolType, class StateType >
	static void convert(std::ostream& out, const automaton::SinglePopDPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & a);

	template < class InputSymbolType, class PushdownStoreSymbolType, class StateType >
	static void convert(std::ostream& out, const automaton::SinglePopNPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & a);

	template < class InputSymbolType, class PushdownStoreSymbolType, class StateType >
	static void convert(std::ostream& out, const automaton::InputDrivenDPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & a);

	template < class InputSymbolType, class PushdownStoreSymbolType, class StateType >
	static void convert(std::ostream& out, const automaton::InputDrivenNPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & a);

	template < class InputSymbolType, class PushdownStoreSymbolType, class StateType >
	static void convert(std::ostream& out, const automaton::VisiblyPushdownDPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & a);

	template < class InputSymbolType, class PushdownStoreSymbolType, class StateType >
	static void convert(std::ostream& out, const automaton::VisiblyPushdownNPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & a);

	template < class InputSymbolType, class PushdownStoreSymbolType, class StateType >
	static void convert(std::ostream& out, const automaton::RealTimeHeightDeterministicDPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & a);

	template < class InputSymbolType, class PushdownStoreSymbolType, class StateType >
	static void convert(std::ostream& out, const automaton::RealTimeHeightDeterministicNPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & a);

	template < class SymbolType, class StateType >
	static void convert(std::ostream& out, const automaton::OneTapeDTM < SymbolType, StateType > & a);

	template < class T >
	static std::string convert ( const T & automaton ) {
		std::stringstream ss;
		convert ( ss, automaton );
		return ss.str ( );
	}
};

template < class SymbolType, class StateType >
void GasTexConverter::convert(std::ostream& out, const automaton::EpsilonNFA < SymbolType, StateType > & a) {
	out << "\\begin{center}\n";
	out << "\\begin{picture}(,)(,)\n";

	for (auto& state : a.getStates()) {
		bool initial = false;
		bool final = false;

		if(a.getInitialState() == state){
			initial = true;
		}
		if(a.getFinalStates().count(state)){
			final = true;
		}

		if(initial || final) {
			out << "\\node[Nmarks=";
			if(initial){
				out << "i";
			}
			if(final){
				out << "r";
			}
			out<<"](";
		} else {
			out <<"\\node(";
		}

		out << state;
		out << ")(,){";
		out << state;
		out << "}\n";
	}

	transitions(a, out);
	out << "\\end{center}\n";
	out << "\\end{picture}\n";
}

template < class SymbolType, class StateType >
void GasTexConverter::convert(std::ostream& out, const automaton::MultiInitialStateNFA < SymbolType, StateType >& a) {
	out << "\\begin{center}\n";
	out << "\\begin{picture}(,)(,)\n";

	for (auto& state : a.getStates()) {
		bool initial = false;
		bool final = false;

		if(a.getInitialStates().count(state)){
			initial = true;
		}
		if(a.getFinalStates().count(state)){
			final = true;
		}

		if(initial || final) {
			out << "\\node[Nmarks=";
			if(initial){
				out << "i";
			}
			if(final){
				out << "r";
			}
			out<<"](";
		} else {
			out <<"\\node(";
		}

		out << state;
		out << ")(,){";
		out << state;
		out << "}\n";
	}

	transitions(a, out);
	out << "\\end{center}\n";
	out << "\\end{picture}\n";
}

template < class SymbolType, class StateType >
void GasTexConverter::convert(std::ostream& out, const automaton::NFA < SymbolType, StateType > & a) {
	out << "\\begin{center}\n";
	out << "\\begin{picture}(,)(,)\n";

	for (auto& state : a.getStates()) {
		bool initial = false;
		bool final = false;

		if(a.getInitialState() == state){
			initial = true;
		}
		if(a.getFinalStates().count(state)){
			final = true;
		}

		if(initial || final) {
			out << "\\node[Nmarks=";
			if(initial){
				out << "i";
			}
			if(final){
				out << "r";
			}
			out<<"](";
		} else {
			out <<"\\node(";
		}

		out << state;
		out << ")(,){";
		out << state;
		out << "}\n";
	}

	transitions(a, out);
	out << "\\end{center}\n";
	out << "\\end{picture}\n";
}

template < class SymbolType, class StateType >
void GasTexConverter::convert(std::ostream& out, const automaton::DFA < SymbolType, StateType > & a) {
	out << "\\begin{center}\n";
	out << "\\begin{picture}(,)(,)\n";

	for (auto& state : a.getStates()) {
		bool initial = false;
		bool final = false;

		if(a.getInitialState() == state){
			initial = true;
		}
		if(a.getFinalStates().count(state)){
			final = true;
		}

		if(initial || final) {
			out << "\\node[Nmarks=";
			if(initial){
				out << "i";
			}
			if(final){
				out << "r";
			}
			out<<"](";
		} else {
			out <<"\\node(";
		}

		out << state;
		out << ")(,){";
		out << state;
		out << "}\n";
	}

	transitions(a, out);
	out << "\\end{center}\n";
	out << "\\end{picture}\n";
}

template < class SymbolType, class StateType >
void GasTexConverter::convert(std::ostream& out, const automaton::ExtendedNFA < SymbolType, StateType > & a) {
	out << "\\begin{center}\n";
	out << "\\begin{picture}(,)(,)\n";

	for (auto& state : a.getStates()) {
		bool initial = false;
		bool final = false;

		if(a.getInitialState() == state){
			initial = true;
		}
		if(a.getFinalStates().count(state)){
			final = true;
		}

		if(initial || final) {
			out << "\\node[Nmarks=";
			if(initial){
				out << "i";
			}
			if(final){
				out << "r";
			}
			out<<"](";
		} else {
			out <<"\\node(";
		}

		out << state;
		out << ")(,){";
		out << state;
		out << "}\n";
	}

	transitions(a, out);
	out << "\\end{center}\n";
	out << "\\end{picture}\n";
}

template < class SymbolType, class StateType >
void GasTexConverter::convert(std::ostream& out, const automaton::CompactNFA < SymbolType, StateType > & a) {
	out << "\\begin{center}\n";
	out << "\\begin{picture}(,)(,)\n";

	for (auto& state : a.getStates()) {
		bool initial = false;
		bool final = false;

		if(a.getInitialState() == state){
			initial = true;
		}
		if(a.getFinalStates().count(state)){
			final = true;
		}

		if(initial || final) {
			out << "\\node[Nmarks=";
			if(initial){
				out << "i";
			}
			if(final){
				out << "r";
			}
			out<<"](";
		} else {
			out <<"\\node(";
		}

		out << state;
		out << ")(,){";
		out << state;
		out << "}\n";
	}

	transitions(a, out);
	out << "\\end{center}\n";
	out << "\\end{picture}\n";
}

template < class SymbolType, class StateType >
void GasTexConverter::convert(std::ostream&, const automaton::NFTA < SymbolType, StateType > &) {
	//TODO
}

template < class SymbolType, class StateType >
void GasTexConverter::convert(std::ostream&, const automaton::DFTA < SymbolType, StateType > &) {
	//TODO
}

template < class InputSymbolType, class PushdownStoreSymbolType, class StateType >
void GasTexConverter::convert(std::ostream& out, const automaton::DPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & a) {
	out << "\\begin{center}\n";
	out << "\\begin{picture}(,)(,)\n";

	for (auto& state : a.getStates()) {
		bool initial = false;
		bool final = false;

		if(a.getInitialState() == state) {
			initial = true;
		}
		if(a.getFinalStates().count(state)) {
			final = true;
		}

		if(initial || final) {
			out << "\\node[Nmarks=";
			if(initial){
				out << "i";
			}
			if(final){
				out << "r";
			}
			out<<"](";
		} else {
			out <<"\\node(";
		}

		out << state;
		out << ")(,){";
		out << state;
		out << "}\n";
	}

	transitions(a, out);
	out << "\\end{center}\n";
	out << "\\end{picture}\n";
}

template < class InputSymbolType, class PushdownStoreSymbolType, class StateType >
void GasTexConverter::convert(std::ostream& out, const automaton::SinglePopDPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & a) {
	out << "\\begin{center}\n";
	out << "\\begin{picture}(,)(,)\n";

	for (auto& state : a.getStates()) {
		bool initial = false;
		bool final = false;

		if(a.getInitialState() == state) {
			initial = true;
		}
		if(a.getFinalStates().count(state)){
			final = true;
		}

		if(initial || final) {
			out << "\\node[Nmarks=";
			if(initial){
				out << "i";
			}
			if(final){
				out << "r";
			}
			out<<"](";
		} else {
			out <<"\\node(";
		}

		out << state;
		out << ")(,){";
		out << state;
		out << "}\n";
	}

	transitions(a, out);
	out << "\\end{center}\n";
	out << "\\end{picture}\n";
}

template < class InputSymbolType, class PushdownStoreSymbolType, class StateType >
void GasTexConverter::convert(std::ostream& out, const automaton::InputDrivenDPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & a) {
	out << "\\begin{center}\n";
	out << "\\begin{picture}(,)(,)\n";

	for (auto& state : a.getStates()) {
		bool initial = false;
		bool final = false;

		if(a.getInitialState() == state){
			initial = true;
		}
		if(a.getFinalStates().count(state)){
			final = true;
		}

		if(initial || final) {
			out << "\\node[Nmarks=";
			if(initial){
				out << "i";
			}
			if(final){
				out << "r";
			}
			out<<"](";
		} else {
			out <<"\\node(";
		}

		out << state;
		out << ")(,){";
		out << state;
		out << "}\n";
	}

	transitions(a, out);
	out << "\\end{center}\n";
	out << "\\end{picture}\n";
}

template < class InputSymbolType, class PushdownStoreSymbolType, class StateType >
void GasTexConverter::convert(std::ostream& out, const automaton::InputDrivenNPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & a) {
	out << "\\begin{center}\n";
	out << "\\begin{picture}(,)(,)\n";

	for (auto& state : a.getStates()) {
		bool initial = false;
		bool final = false;

		if(a.getInitialState() == state){
			initial = true;
		}
		if(a.getFinalStates().count(state)){
			final = true;
		}

		if(initial || final) {
			out << "\\node[Nmarks=";
			if(initial){
				out << "i";
			}
			if(final){
				out << "r";
			}
			out<<"](";
		} else {
			out <<"\\node(";
		}

		out << state;
		out << ")(,){";
		out << state;
		out << "}\n";
	}

	transitions(a, out);
	out << "\\end{center}\n";
	out << "\\end{picture}\n";
}

template < class InputSymbolType, class PushdownStoreSymbolType, class StateType >
void GasTexConverter::convert(std::ostream& out, const automaton::VisiblyPushdownDPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & a) {
	out << "\\begin{center}\n";
	out << "\\begin{picture}(,)(,)\n";

	for (auto& state : a.getStates()) {
		bool initial = false;
		bool final = false;

		if(a.getInitialState() == state){
			initial = true;
		}
		if(a.getFinalStates().count(state)){
			final = true;
		}

		if(initial || final) {
			out << "\\node[Nmarks=";
			if(initial){
				out << "i";
			}
			if(final){
				out << "r";
			}
			out<<"](";
		} else {
			out <<"\\node(";
		}

		out << state;
		out << ")(,){";
		out << state;
		out << "}\n";
	}

	transitions(a, out);
	out << "\\end{center}\n";
	out << "\\end{picture}\n";
}

template < class InputSymbolType, class PushdownStoreSymbolType, class StateType >
void GasTexConverter::convert(std::ostream& out, const automaton::VisiblyPushdownNPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & a) {
	out << "\\begin{center}\n";
	out << "\\begin{picture}(,)(,)\n";

	for (auto& state : a.getStates()) {
		bool initial = false;
		bool final = false;

		if(a.getInitialStates().count(state)){
			initial = true;
		}
		if(a.getFinalStates().count(state)){
			final = true;
		}

		if(initial || final) {
			out << "\\node[Nmarks=";
			if(initial){
				out << "i";
			}
			if(final){
				out << "r";
			}
			out<<"](";
		} else {
			out <<"\\node(";
		}

		out << state;
		out << ")(,){";
		out << state;
		out << "}\n";
	}

	transitions(a, out);
	out << "\\end{center}\n";
	out << "\\end{picture}\n";
}

template < class InputSymbolType, class PushdownStoreSymbolType, class StateType >
void GasTexConverter::convert(std::ostream& out, const automaton::RealTimeHeightDeterministicDPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & a) {
	out << "\\begin{center}\n";
	out << "\\begin{picture}(,)(,)\n";

	for (auto& state : a.getStates()) {
		bool initial = false;
		bool final = false;

		if(a.getInitialState() == state){
			initial = true;
		}
		if(a.getFinalStates().count(state)){
			final = true;
		}

		if(initial || final) {
			out << "\\node[Nmarks=";
			if(initial){
				out << "i";
			}
			if(final){
				out << "r";
			}
			out<<"](";
		} else {
			out <<"\\node(";
		}

		out << state;
		out << ")(,){";
		out << state;
		out << "}\n";
	}

	transitions(a, out);
	out << "\\end{center}\n";
	out << "\\end{picture}\n";
}

template < class InputSymbolType, class PushdownStoreSymbolType, class StateType >
void GasTexConverter::convert(std::ostream& out, const automaton::RealTimeHeightDeterministicNPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & a) {
	out << "\\begin{center}\n";
	out << "\\begin{picture}(,)(,)\n";

	for (auto& state : a.getStates()) {
		bool initial = false;
		bool final = false;

		if(a.getInitialStates().count(state)){
			initial = true;
		}
		if(a.getFinalStates().count(state)){
			final = true;
		}

		if(initial || final) {
			out << "\\node[Nmarks=";
			if(initial){
				out << "i";
			}
			if(final){
				out << "r";
			}
			out<<"](";
		} else {
			out <<"\\node(";
		}

		out << state;
		out << ")(,){";
		out << state;
		out << "}\n";
	}

	transitions(a, out);
	out << "\\end{center}\n";
	out << "\\end{picture}\n";
}

template < class InputSymbolType, class PushdownStoreSymbolType, class StateType >
void GasTexConverter::convert(std::ostream& out, const automaton::NPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & a) {
	out << "\\begin{center}\n";
	out << "\\begin{picture}(,)(,)\n";

	for (auto& state : a.getStates()) {
		bool initial = false;
		bool final = false;

		if(a.getInitialState() == state){
			initial = true;
		}
		if(a.getFinalStates().count(state)){
			final = true;
		}

		if(initial || final) {
			out << "\\node[Nmarks=";
			if(initial){
				out << "i";
			}
			if(final){
				out << "r";
			}
			out<<"](";
		} else {
			out <<"\\node(";
		}

		out << state;
		out << ")(,){";
		out << state;
		out << "}\n";
	}

	transitions(a, out);
	out << "\\end{center}\n";
	out << "\\end{picture}\n";
}

template < class InputSymbolType, class PushdownStoreSymbolType, class StateType >
void GasTexConverter::convert(std::ostream& out, const automaton::SinglePopNPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & a) {
	out << "\\begin{center}\n";
	out << "\\begin{picture}(,)(,)\n";

	for (auto& state : a.getStates()) {
		bool initial = false;
		bool final = false;

		if(a.getInitialState() == state){
			initial = true;
		}
		if(a.getFinalStates().count(state)){
			final = true;
		}

		if(initial || final) {
			out << "\\node[Nmarks=";
			if(initial){
				out << "i";
			}
			if(final){
				out << "r";
			}
			out<<"](";
		} else {
			out <<"\\node(";
		}

		out << state;
		out << ")(,){";
		out << state;
		out << "}\n";
	}

	transitions(a, out);
	out << "\\end{center}\n";
	out << "\\end{picture}\n";
}

template < class SymbolType, class StateType >
void GasTexConverter::convert(std::ostream& out, const automaton::OneTapeDTM < SymbolType, StateType > & a) {
	out << "\\begin{center}\n";
	out << "\\begin{picture}(,)(,)\n";

	for (auto& state : a.getStates()) {
		bool initial = false;
		bool final = false;

		if(a.getInitialState() == state){
			initial = true;
		}
		if(a.getFinalStates().count(state)){
			final = true;
		}

		if(initial || final) {
			out << "\\node[Nmarks=";
			if(initial){
				out << "i";
			}
			if(final){
				out << "r";
			}
			out<<"](";
		} else {
			out <<"\\node(";
		}

		out << state;
		out << ")(,){";
		out << state;
		out << "}\n";
	}

	transitions(a, out);
	out << "\\end{center}\n";
	out << "\\end{picture}\n";
}

template< class SymbolType >
std::string GasTexConverter::getStackSymbols(const ext::vector<SymbolType>& stackSymbols) {
	if (stackSymbols.empty ( )) {
		return "$\\varepsilon$";
	}

	std::string symbols = "";
	int i=0;
	for (const SymbolType & symbol : stackSymbols) {
		if(i++ !=0) {
			symbols +=" ";
		}
		symbols += replace ( factory::StringDataFactory::toString ( symbol ), "\"", "\\\"" );
	}
	return symbols;
}

template<class SymbolType, class StateType>
void GasTexConverter::transitions(const automaton::EpsilonNFA < SymbolType, StateType > & fsm, std::ostream& out) {
	ext::map<std::pair<std::string, std::string>, std::string> transitionMap;
	for (const auto& transition : fsm.getTransitions()) {
		std::pair<std::string, std::string> key(replace ( factory::StringDataFactory::toString ( transition.first.first ), "\"", "\\\"" ), replace ( factory::StringDataFactory::toString ( transition.second ), "\"", "\\\"" ) );

		std::string symbol;
		if (transition.first.second.is_epsilon()) {
			symbol = "$\\varepsilon$";
		} else {
			symbol = replace ( factory::StringDataFactory::toString ( transition.first.second.getSymbol ( ) ), "\"", "\\\"" );
		}

		auto mapIterator = transitionMap.find(key);
		if (mapIterator == transitionMap.end()) {
			transitionMap.insert(make_pair(key, symbol));
		} else {
			mapIterator->second += ", " + symbol;
		}
	}
	printTransitionMap(transitionMap, out);
}

template<class SymbolType, class StateType>
void GasTexConverter::transitions(const automaton::MultiInitialStateNFA < SymbolType, StateType >& fsm, std::ostream& out) {
	ext::map<std::pair<std::string, std::string>, std::string> transitionMap;
	for (const auto& transition : fsm.getTransitions()) {
		std::pair<std::string, std::string> key(replace ( factory::StringDataFactory::toString ( transition.first.first ), "\"", "\\\"" ), replace ( factory::StringDataFactory::toString ( transition.second ), "\"", "\\\"" ) );

		std::string symbol = replace ( factory::StringDataFactory::toString ( transition.first.second ), "\"", "\\\"" );

		auto mapIterator = transitionMap.find(key);
		if (mapIterator == transitionMap.end()) {
			transitionMap.insert(make_pair(key, symbol));
		} else {
			mapIterator->second += ", " + symbol;
		}
	}
	printTransitionMap(transitionMap, out);
}

template<class SymbolType, class StateType>
void GasTexConverter::transitions(const automaton::NFA < SymbolType, StateType > & fsm, std::ostream& out) {
	ext::map<std::pair<std::string, std::string>, std::string> transitionMap;
	for (const auto& transition : fsm.getTransitions()) {
		std::pair<std::string, std::string> key( replace ( factory::StringDataFactory::toString ( transition.first.first ), "\"", "\\\"" ), replace ( factory::StringDataFactory::toString ( transition.second ), "\"", "\\\"" ) );

		std::string symbol = replace ( factory::StringDataFactory::toString ( transition.first.second ), "\"", "\\\"" );

		auto mapIterator = transitionMap.find(key);
		if (mapIterator == transitionMap.end()) {
			transitionMap.insert(make_pair(key, symbol));
		} else {
			mapIterator->second += ", " + symbol;
		}
	}
	printTransitionMap(transitionMap, out);
}

template<class SymbolType, class StateType>
void GasTexConverter::transitions(const automaton::DFA < SymbolType, StateType > & fsm, std::ostream& out) {
	ext::map<std::pair<std::string, std::string>, std::string> transitionMap;
	for (const auto& transition : fsm.getTransitions()) {
		std::pair<std::string, std::string> key( replace ( factory::StringDataFactory::toString ( transition.first.first ), "\"", "\\\"" ), replace ( factory::StringDataFactory::toString ( transition.second ), "\"", "\\\"" ) );

		std::string symbol = replace ( factory::StringDataFactory::toString ( transition.first.second ), "\"", "\\\"" );

		auto mapIterator = transitionMap.find(key);
		if (mapIterator == transitionMap.end()) {
			transitionMap.insert(make_pair(key, symbol));
		} else {
			mapIterator->second += ", " + symbol;
		}
	}
	printTransitionMap(transitionMap, out);
}

template<class SymbolType, class StateType>
void GasTexConverter::transitions(const automaton::ExtendedNFA < SymbolType, StateType > & fsm, std::ostream& out) {
	ext::map<std::pair<std::string, std::string>, std::string> transitionMap;

	for (const auto& transition : fsm.getTransitions()) {
		std::pair<std::string, std::string> key( replace ( factory::StringDataFactory::toString ( transition.first.first ), "\"", "\\\"" ), replace ( factory::StringDataFactory::toString ( transition.second ), "\"", "\\\"" ) );

		std::string symbol = replace ( factory::StringDataFactory::toString ( transition.first.second ), "\"", "\\\"" );

		auto mapIterator = transitionMap.find(key);
		if (mapIterator == transitionMap.end()) {
			transitionMap.insert(make_pair(key, symbol));
		} else {
			mapIterator->second += ", " + symbol;
		}
	}
	printTransitionMap(transitionMap, out);
}

template<class SymbolType, class StateType>
void GasTexConverter::transitions(const automaton::CompactNFA < SymbolType, StateType > & fsm, std::ostream& out) {
	ext::map<std::pair<std::string, std::string>, std::string> transitionMap;

	for (const auto& transition : fsm.getTransitions()) {
		std::pair<std::string, std::string> key(replace ( factory::StringDataFactory::toString ( transition.first.first ), "\"", "\\\"" ), replace ( factory::StringDataFactory::toString ( transition.second ), "\"", "\\\"" ) );

		std::string symbol = replace ( factory::StringDataFactory::toString ( string::stringFrom(transition.first.second )), "\"", "\\\"" );

		auto mapIterator = transitionMap.find(key);
		if (mapIterator == transitionMap.end()) {
			transitionMap.insert(make_pair(key, symbol));
		} else {
			mapIterator->second += ", " + symbol;
		}
	}
	printTransitionMap(transitionMap, out);
}

template<class SymbolType, class StateType>
void GasTexConverter::transitions(const automaton::NFTA < SymbolType, StateType > &, std::ostream&) {
	//TODO
}

template<class SymbolType, class StateType>
void GasTexConverter::transitions(const automaton::DFTA < SymbolType, StateType > &, std::ostream&) {
	//TODO
}

template<class InputSymbolType, class PushdownStoreSymbolType, class StateType>
void GasTexConverter::transitions(const automaton::DPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & pda, std::ostream& out) {
	ext::map<std::pair<std::string, std::string>, std::string> transitionMap;

	for (const auto& transition : pda.getTransitions()) {
		std::pair<std::string, std::string> key(replace ( factory::StringDataFactory::toString ( std::get<0>(transition.first ) ), "\"", "\\\"" ), replace ( factory::StringDataFactory::toString ( transition.second.first ), "\"", "\\\"" ) );
		auto mapIterator = transitionMap.find(key);

		std::string symbol;
		if (std::get<1>(transition.first).is_epsilon ( ) ) {
			symbol = "$\\varepsilon;$";
		} else {
			symbol = replace ( factory::StringDataFactory::toString ( std::get<1>(transition.first ).getSymbol ( ) ), "\"", "\\\"" );
		}

		symbol += "|";

		symbol += getStackSymbols(std::get<2>(transition.first));
		symbol += "\\rarrow";
		symbol += getStackSymbols(transition.second.second);

		if (mapIterator == transitionMap.end()) {
			transitionMap.insert(std::make_pair(key, symbol));
		} else {
			mapIterator->second += "; " + symbol;
		}
	}

	printTransitionMap(transitionMap, out);
}

template<class InputSymbolType, class PushdownStoreSymbolType, class StateType>
void GasTexConverter::transitions(const automaton::SinglePopDPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & pda, std::ostream& out) {
	ext::map<std::pair<std::string, std::string>, std::string> transitionMap;

	for (const auto& transition : pda.getTransitions()) {
		std::pair<std::string, std::string> key(replace ( factory::StringDataFactory::toString ( std::get<0>(transition.first ) ), "\"", "\\\"" ), replace ( factory::StringDataFactory::toString ( transition.second.first ), "\"", "\\\"" ) );
		auto mapIterator = transitionMap.find(key);

		std::string symbol;
		if (std::get<1>(transition.first).is_epsilon ( )) {
			symbol = "$\\varepsilon;$";
		} else {
			symbol = replace ( factory::StringDataFactory::toString ( std::get<1>(transition.first ).getSymbol ( )), "\"", "\\\"" );
		}

		symbol += "|";

		symbol += replace ( factory::StringDataFactory::toString ( std::get<2>(transition.first )), "\"", "\\\"" );
		symbol += "\\rarrow";
		symbol += getStackSymbols(transition.second.second);

		if (mapIterator == transitionMap.end()) {
			transitionMap.insert(std::make_pair(key, symbol));
		} else {
			mapIterator->second += "; " + symbol;
		}
	}

	printTransitionMap(transitionMap, out);
}

template<class SymbolType, class PushdownStoreSymbolType, class StateType>
void GasTexConverter::transitions(const automaton::InputDrivenDPDA < SymbolType, PushdownStoreSymbolType, StateType > & pda, std::ostream& out) {
	ext::map<std::pair<std::string, std::string>, std::string> transitionMap;

	const auto& symbolToPDSOperation = pda.getPushdownStoreOperations();
	for (const auto& transition : pda.getTransitions()) {
		const auto& pop = symbolToPDSOperation.find(std::get<1>(transition.first))->second.first;
		const auto& push = symbolToPDSOperation.find(std::get<1>(transition.first))->second.second;

		const auto& to = transition.second;
		std::pair<std::string, std::string> key(replace ( factory::StringDataFactory::toString ( transition.first.first ), "\"", "\\\"" ), replace ( factory::StringDataFactory::toString ( to ), "\"", "\\\"" ) );
		auto mapIterator = transitionMap.find(key);

		std::string symbol = replace ( factory::StringDataFactory::toString ( transition.first.second ), "\"", "\\\"" );

		symbol += "|";

		symbol += getStackSymbols(pop);
		symbol += "\\rarrow";
		symbol += getStackSymbols(push);

		if (mapIterator == transitionMap.end()) {
			transitionMap.insert(std::make_pair(key, symbol));
		} else {
			mapIterator->second += "; " + symbol;
		}
	}

	printTransitionMap(transitionMap, out);
}

template<class InputSymbolType, class PushdownStoreSymbolType, class StateType>
void GasTexConverter::transitions(const automaton::InputDrivenNPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & pda, std::ostream& out) {
	ext::map<std::pair<std::string, std::string>, std::string> transitionMap;

	const auto& symbolToPDSOperation = pda.getPushdownStoreOperations();
	for (const auto& transition : pda.getTransitions()) {
		const auto& pop = symbolToPDSOperation.find(std::get<1>(transition.first))->second.first;
		const auto& push = symbolToPDSOperation.find(std::get<1>(transition.first))->second.second;

		std::pair<std::string, std::string> key( replace ( factory::StringDataFactory::toString ( transition.first.first ), "\"", "\\\"" ), replace ( factory::StringDataFactory::toString ( transition.second ), "\"", "\\\"" ) );
		auto mapIterator = transitionMap.find(key);

		std::string symbol = replace ( factory::StringDataFactory::toString ( transition.first.second ), "\"", "\\\"" );

		symbol += "|";

		symbol += getStackSymbols(pop);
		symbol += "\\rarrow";
		symbol += getStackSymbols(push);

		if (mapIterator == transitionMap.end()) {
			transitionMap.insert(std::make_pair(key, symbol));
		} else {
			mapIterator->second += "; " + symbol;
		}
	}

	printTransitionMap(transitionMap, out);
}

template<class InputSymbolType, class PushdownStoreSymbolType, class StateType>
void GasTexConverter::transitions(const automaton::VisiblyPushdownDPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & pda, std::ostream& out) {
	ext::map<std::pair<std::string, std::string>, std::string> transitionMap;

	for (const auto& transition : pda.getCallTransitions()) {
		std::pair<std::string, std::string> key( replace ( factory::StringDataFactory::toString ( transition.first.first ), "\"", "\\\"" ), replace ( factory::StringDataFactory::toString ( transition.second.first ), "\"", "\\\"" ) );
		auto mapIterator = transitionMap.find(key);

		std::string symbol = replace ( factory::StringDataFactory::toString ( transition.first.second ), "\"", "\\\"" );

		symbol += "|";

		symbol += "$\\varepsilon;$";
		symbol += "\\rarrow";
		symbol += replace ( factory::StringDataFactory::toString ( transition.second.second ), "\"", "\\\"" );

		if (mapIterator == transitionMap.end()) {
			transitionMap.insert(std::make_pair(key, symbol));
		} else {
			mapIterator->second += "; " + symbol;
		}
	}

	for (const auto& transition : pda.getReturnTransitions()) {
		std::pair<std::string, std::string> key( replace ( factory::StringDataFactory::toString ( std::get<0>(transition.first ) ), "\"", "\\\"" ), replace ( factory::StringDataFactory::toString ( transition.second ), "\"", "\\\"" ) );
		auto mapIterator = transitionMap.find(key);

		std::string symbol = replace ( factory::StringDataFactory::toString ( std::get<1>(transition.first )), "\"", "\\\"" );

		symbol += "|";

		symbol += replace ( factory::StringDataFactory::toString ( std::get<2>(transition.first )), "\"", "\\\"" );
		symbol += "\\rarrow";
		symbol += "$\\varepsilon;$";

		if (mapIterator == transitionMap.end()) {
			transitionMap.insert(std::make_pair(key, symbol));
		} else {
			mapIterator->second += "; " + symbol;
		}
	}

	for (const auto& transition : pda.getLocalTransitions()) {
		std::pair<std::string, std::string> key( replace ( factory::StringDataFactory::toString ( transition.first.first ), "\"", "\\\"" ), replace ( factory::StringDataFactory::toString ( transition.second ), "\"", "\\\"" ) );
		auto mapIterator = transitionMap.find(key);

		std::string symbol = replace ( factory::StringDataFactory::toString ( transition.first.second ), "\"", "\\\"" );

		symbol += "|";

		symbol += "$\\varepsilon;$";
		symbol += "\\rarrow";
		symbol += "$\\varepsilon;$";

		if (mapIterator == transitionMap.end()) {
			transitionMap.insert(std::make_pair(key, symbol));
		} else {
			mapIterator->second += "; " + symbol;
		}
	}

	printTransitionMap(transitionMap, out);
}

template<class InputSymbolType, class PushdownStoreSymbolType, class StateType>
void GasTexConverter::transitions(const automaton::VisiblyPushdownNPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & pda, std::ostream& out) {
	ext::map<std::pair<std::string, std::string>, std::string> transitionMap;

	for (const auto& transition : pda.getCallTransitions()) {
		std::pair<std::string, std::string> key( replace ( factory::StringDataFactory::toString ( transition.first.first ), "\"", "\\\"" ), replace ( factory::StringDataFactory::toString ( transition.second.first ), "\"", "\\\"" ) );
		auto mapIterator = transitionMap.find(key);

		std::string symbol = replace ( factory::StringDataFactory::toString ( transition.first.second ), "\"", "\\\"" );

		symbol += "|";

		symbol += "$\\varepsilon;$";
		symbol += "\\rarrow";
		symbol += replace ( factory::StringDataFactory::toString ( transition.second.second ), "\"", "\\\"" );

		if (mapIterator == transitionMap.end()) {
			transitionMap.insert(std::make_pair(key, symbol));
		} else {
			mapIterator->second += "; " + symbol;
		}
	}

	for (const auto& transition : pda.getReturnTransitions()) {
		std::pair<std::string, std::string> key( replace ( factory::StringDataFactory::toString ( std::get<0>(transition.first ) ), "\"", "\\\"" ), replace ( factory::StringDataFactory::toString ( transition.second ), "\"", "\\\"" ) );
		auto mapIterator = transitionMap.find(key);

		std::string symbol = replace ( factory::StringDataFactory::toString ( std::get<1>(transition.first )), "\"", "\\\"" );

		symbol += "|";

		symbol += replace ( factory::StringDataFactory::toString ( std::get<2>(transition.first )), "\"", "\\\"" );
		symbol += "\\rarrow";
		symbol += "$\\varepsilon;$";

		if (mapIterator == transitionMap.end()) {
			transitionMap.insert(std::make_pair(key, symbol));
		} else {
			mapIterator->second += "; " + symbol;
		}
	}

	for (const auto& transition : pda.getLocalTransitions()) {
		std::pair<std::string, std::string> key( replace ( factory::StringDataFactory::toString ( transition.first.first ), "\"", "\\\"" ), replace ( factory::StringDataFactory::toString ( transition.second ), "\"", "\\\"" ) );
		auto mapIterator = transitionMap.find(key);

		std::string symbol = replace ( factory::StringDataFactory::toString ( transition.first.second ), "\"", "\\\"" );

		symbol += "|";

		symbol += "$\\varepsilon;$";
		symbol += "\\rarrow";
		symbol += "$\\varepsilon;$";

		if (mapIterator == transitionMap.end()) {
			transitionMap.insert(std::make_pair(key, symbol));
		} else {
			mapIterator->second += "; " + symbol;
		}
	}

	printTransitionMap(transitionMap, out);
}

template<class InputSymbolType, class PushdownStoreSymbolType, class StateType>
void GasTexConverter::transitions(const automaton::RealTimeHeightDeterministicDPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & pda, std::ostream& out) {
	ext::map<std::pair<std::string, std::string>, std::string> transitionMap;

	for (const auto& transition : pda.getCallTransitions()) {
		std::pair<std::string, std::string> key( replace ( factory::StringDataFactory::toString ( transition.first.first ), "\"", "\\\"" ), replace ( factory::StringDataFactory::toString ( transition.second.first ), "\"", "\\\"" ) );
		auto mapIterator = transitionMap.find(key);

		std::string symbol;
		if(transition.first.second.is_epsilon ( ))
			symbol = "$\\varepsilon;$";
		else
			symbol = replace ( factory::StringDataFactory::toString ( transition.first.second.getSymbol ( )), "\"", "\\\"" );

		symbol += "|";

		symbol += "$\\varepsilon;$";
		symbol += "\\rarrow";
		symbol += replace ( factory::StringDataFactory::toString ( transition.second.second ), "\"", "\\\"" );

		if (mapIterator == transitionMap.end()) {
			transitionMap.insert(std::make_pair(key, symbol));
		} else {
			mapIterator->second += "; " + symbol;
		}
	}

	for (const auto& transition : pda.getReturnTransitions()) {
		std::pair<std::string, std::string> key( replace ( factory::StringDataFactory::toString ( std::get<0>(transition.first ) ), "\"", "\\\"" ), replace ( factory::StringDataFactory::toString ( transition.second ), "\"", "\\\"" ) );
		auto mapIterator = transitionMap.find(key);

		std::string symbol;
		if(std::get<1>(transition.first).is_epsilon ( ))
			symbol = "$\\varepsilon;$";
		else
			symbol = replace ( factory::StringDataFactory::toString ( std::get<1>(transition.first ).getSymbol ( )), "\"", "\\\"" );

		symbol += "|";

		symbol += replace ( factory::StringDataFactory::toString ( std::get<2>(transition.first )), "\"", "\\\"" );
		symbol += "\\rarrow";
		symbol += "$\\varepsilon;$";

		if (mapIterator == transitionMap.end()) {
			transitionMap.insert(std::make_pair(key, symbol));
		} else {
			mapIterator->second += "; " + symbol;
		}
	}

	for (const auto& transition : pda.getLocalTransitions()) {
		std::pair<std::string, std::string> key( replace ( factory::StringDataFactory::toString ( transition.first.first ), "\"", "\\\"" ), replace ( factory::StringDataFactory::toString ( transition.second ), "\"", "\\\"" ) );
		auto mapIterator = transitionMap.find(key);

		std::string symbol;
		if(transition.first.second.is_epsilon ( ))
			symbol = "$\\varepsilon;$";
		else
			symbol = replace ( factory::StringDataFactory::toString ( transition.first.second.getSymbol ( )), "\"", "\\\"" );

		symbol += "|";

		symbol += "$\\varepsilon;$";
		symbol += "\\rarrow";
		symbol += "$\\varepsilon;$";

		if (mapIterator == transitionMap.end()) {
			transitionMap.insert(std::make_pair(key, symbol));
		} else {
			mapIterator->second += "; " + symbol;
		}
	}

	printTransitionMap(transitionMap, out);
}

template<class InputSymbolType, class PushdownStoreSymbolType, class StateType>
void GasTexConverter::transitions(const automaton::RealTimeHeightDeterministicNPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & pda, std::ostream& out) {
	ext::map<std::pair<std::string, std::string>, std::string> transitionMap;

	for (const auto& transition : pda.getCallTransitions()) {
		std::pair<std::string, std::string> key( replace ( factory::StringDataFactory::toString ( transition.first.first ), "\"", "\\\"" ), replace ( factory::StringDataFactory::toString ( transition.second.first ), "\"", "\\\"" ) );
		auto mapIterator = transitionMap.find(key);

		std::string symbol;
		if(transition.first.second.is_epsilon ( ))
			symbol = "$\\varepsilon;$";
		else
			symbol = replace ( factory::StringDataFactory::toString ( transition.first.second.getSymbol ( )), "\"", "\\\"" );

		symbol += "|";

		symbol += "$\\varepsilon;$";
		symbol += "\\rarrow";
		symbol += replace ( factory::StringDataFactory::toString ( transition.second.second ), "\"", "\\\"" );

		if (mapIterator == transitionMap.end()) {
			transitionMap.insert(std::make_pair(key, symbol));
		} else {
			mapIterator->second += "; " + symbol;
		}
	}

	for (const auto& transition : pda.getReturnTransitions()) {
		std::pair<std::string, std::string> key( replace ( factory::StringDataFactory::toString ( std::get<0>(transition.first ) ), "\"", "\\\"" ), replace ( factory::StringDataFactory::toString ( transition.second ), "\"", "\\\"" ) );
		auto mapIterator = transitionMap.find(key);

		std::string symbol;
		if(std::get<1>(transition.first).is_epsilon ( ))
			symbol = "$\\varepsilon;$";
		else
			symbol = replace ( factory::StringDataFactory::toString ( std::get<1>(transition.first ).getSymbol ( )), "\"", "\\\"" );

		symbol += "|";

		symbol += replace ( factory::StringDataFactory::toString ( std::get<2>(transition.first )), "\"", "\\\"" );
		symbol += "\\rarrow";
		symbol += "$\\varepsilon;$";

		if (mapIterator == transitionMap.end()) {
			transitionMap.insert(std::make_pair(key, symbol));
		} else {
			mapIterator->second += "; " + symbol;
		}
	}

	for (const auto& transition : pda.getLocalTransitions()) {
		std::pair<std::string, std::string> key( replace ( factory::StringDataFactory::toString ( transition.first.first ), "\"", "\\\"" ), replace ( factory::StringDataFactory::toString ( transition.second ), "\"", "\\\"" ) );
		auto mapIterator = transitionMap.find(key);

		std::string symbol;
		if(transition.first.second.is_epsilon ( ))
			symbol = "$\\varepsilon;$";
		else
			symbol = replace ( factory::StringDataFactory::toString ( transition.first.second.getSymbol ( )), "\"", "\\\"" );

		symbol += "|";

		symbol += "$\\varepsilon;$";
		symbol += "\\rarrow";
		symbol += "$\\varepsilon;$";

		if (mapIterator == transitionMap.end()) {
			transitionMap.insert(std::make_pair(key, symbol));
		} else {
			mapIterator->second += "; " + symbol;
		}
	}

	printTransitionMap(transitionMap, out);
}

template<class InputSymbolType, class PushdownStoreSymbolType, class StateType>
void GasTexConverter::transitions(const automaton::NPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & pda, std::ostream& out) {
	ext::map<std::pair<std::string, std::string>, std::string> transitionMap;

	for (const auto& transition : pda.getTransitions()) {
		std::pair<std::string, std::string> key( replace ( factory::StringDataFactory::toString ( std::get<0>(transition.first ) ), "\"", "\\\"" ), replace ( factory::StringDataFactory::toString ( transition.second.first ), "\"", "\\\"" ) );
		auto mapIterator = transitionMap.find(key);

		std::string symbol;
		if (std::get<1>(transition.first).is_epsilon ( ) ) {
			symbol = "$\\varepsilon;$";
		} else {
			symbol = replace ( factory::StringDataFactory::toString ( std::get<1>(transition.first ).getSymbol ( ) ), "\"", "\\\"" );
		}

		symbol += "|";

		symbol += getStackSymbols(std::get<2>(transition.first));
		symbol += "\\rarrow";
		symbol += getStackSymbols(transition.second.second);

		if (mapIterator == transitionMap.end()) {
			transitionMap.insert(std::make_pair(key, symbol));
		} else {
			mapIterator->second += "; " + symbol;
		}
	}

	printTransitionMap(transitionMap, out);
}

template<class InputSymbolType, class PushdownStoreSymbolType, class StateType>
void GasTexConverter::transitions(const automaton::SinglePopNPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & pda, std::ostream& out) {
	ext::map<std::pair<std::string, std::string>, std::string> transitionMap;

	for (const auto& transition : pda.getTransitions()) {
		std::pair<std::string, std::string> key( replace ( factory::StringDataFactory::toString ( std::get<0>(transition.first ) ), "\"", "\\\"" ), replace ( factory::StringDataFactory::toString ( transition.second.first ), "\"", "\\\"" ) );
		auto mapIterator = transitionMap.find(key);

		std::string symbol;
		if (std::get<1>(transition.first).is_epsilon ( )) {
			symbol = "$\\varepsilon;$";
		} else {
			symbol = replace ( factory::StringDataFactory::toString ( std::get<1>(transition.first ).getSymbol ( )), "\"", "\\\"" );
		}

		symbol += "|";

		symbol += replace ( factory::StringDataFactory::toString ( std::get<2>(transition.first )), "\"", "\\\"" );
		symbol += "\\rarrow";
		symbol += getStackSymbols(transition.second.second);

		if (mapIterator == transitionMap.end()) {
			transitionMap.insert(std::make_pair(key, symbol));
		} else {
			mapIterator->second += "; " + symbol;
		}
	}

	printTransitionMap(transitionMap, out);
}

template<class SymbolType, class StateType>
void GasTexConverter::transitions(const automaton::OneTapeDTM < SymbolType, StateType > & tm, std::ostream& out) {
	ext::map<std::pair<std::string, std::string>, std::string> transitionMap;

	for (auto& transition : tm.getTransitions()) {
		std::pair<std::string, std::string> key( replace ( factory::StringDataFactory::toString ( transition.first.first ), "\"", "\\\"" ), replace ( factory::StringDataFactory::toString ( std::get<0>(transition.second )), "\"", "\\\"" ));
		auto mapIterator = transitionMap.find(key);

		std::string symbol = replace ( factory::StringDataFactory::toString ( transition.first.second ), "\"", "\\\"" );
		symbol += "/";
		symbol += replace ( factory::StringDataFactory::toString ( std::get<1>(transition.second )), "\"", "\\\"" );
		symbol += ",";
		switch(std::get<2>(transition.second)) {
		case automaton::Shift::LEFT:
			symbol += "$\\leftarrow$";
			break;
		case automaton::Shift::RIGHT:
			symbol += "$\\rightarrow$";
			break;
		case automaton::Shift::NONE:
			symbol += "$\\times$";
			break;
		default:
			throw exception::CommonException("Unexpected shift direction");
		}

		if (mapIterator == transitionMap.end()) {
			transitionMap.insert(std::make_pair(key, symbol));
		} else {
			mapIterator->second += "; " + symbol;
		}
	}

	printTransitionMap(transitionMap, out);
}

} /* namespace convert */

