diff --git a/aepsilon2/src/aepsilon.cpp b/aepsilon2/src/aepsilon.cpp
index 0c2ac5def5cbc57dd03902a53857ee47c0f64aaa..3c8cf8f8c712958a522135bf9a4377c7f1875c3d 100644
--- a/aepsilon2/src/aepsilon.cpp
+++ b/aepsilon2/src/aepsilon.cpp
@@ -9,7 +9,7 @@
 #include <factory/DataFactory.hpp>
 #include <exception/AlibException.h>
 
-#include "epsilon/epsilonNfa/EpsilonNFAEpsilonRemover.h"
+#include "epsilon/fsm/FSMEpsilonRemover.h"
 
 int main(int argc, char** argv) {
 	int fileParameterIndex = -1;
@@ -45,21 +45,9 @@ int main(int argc, char** argv) {
 
 		if(alib::FromXMLParsers::automatonParser.first(tokens)) {
 			std::string xmlMark = tokens.front( ).getData( );
-			if(xmlMark == "EpsilonNFA") {
-				automaton::EpsilonNFA automaton = alib::DataFactory::fromTokens<automaton::EpsilonNFA>(tokens);
-				automaton::NFA res = epsilon::EpsilonNFAEpsilonRemover::remove( automaton );
-				alib::DataFactory::toStdout(res);
-			} else if(xmlMark == "NFA") {
-				automaton::NFA automaton = alib::DataFactory::fromTokens<automaton::NFA>(tokens);
-				alib::DataFactory::toStdout(automaton);
-			} else if(xmlMark == "DFA") {
-				automaton::DFA automaton = alib::DataFactory::fromTokens<automaton::DFA>(tokens);
-				alib::DataFactory::toStdout(automaton);
-			} else {
-				automaton::EpsilonNFA automaton = alib::DataFactory::fromTokens<automaton::EpsilonNFA>(tokens);
-				automaton::NFA res = epsilon::EpsilonNFAEpsilonRemover::remove( automaton );
-				alib::DataFactory::toStdout(res);
-			}
+			automaton::Automaton automaton = alib::DataFactory::fromTokens<automaton::Automaton>(tokens);
+			automaton::Automaton res = epsilon::FSMEpsilonRemover::remove( automaton );
+			alib::DataFactory::toStdout(res);
 		} else {
 			throw exception::AlibException("Invalid argument expected Epsilon NFA.");
 		}
diff --git a/alib2algo/src/automaton/EpsilonClosure.h b/alib2algo/src/automaton/EpsilonClosure.h
index 41030ec815f51d223813c4ad58ceb9c3868319d1..603f85ba9cbb065755197799a1c69264c8ea630f 100644
--- a/alib2algo/src/automaton/EpsilonClosure.h
+++ b/alib2algo/src/automaton/EpsilonClosure.h
@@ -17,7 +17,7 @@
 
 namespace automaton {
 
-class EpsilonClosure  : public VisitableAutomatonBase::const_visitor_type {
+class EpsilonClosure : public VisitableAutomatonBase::const_visitor_type {
 public:
 	static std::set<automaton::State> epsilonClosure( const automaton::Automaton & automaton, const automaton::State & state );
 
diff --git a/alib2algo/src/epsilon/epsilonNfa/EpsilonNFAEpsilonRemover.cpp b/alib2algo/src/epsilon/epsilonNfa/EpsilonNFAEpsilonRemover.cpp
deleted file mode 100644
index 4173dea1290fc588498bc1d32a1e2cdcec09f243..0000000000000000000000000000000000000000
--- a/alib2algo/src/epsilon/epsilonNfa/EpsilonNFAEpsilonRemover.cpp
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * EpsilonNFAEpsilonRemover.cpp
- *
- *  Created on: 16. 1. 2014
- *	  Author: Tomas Pecka
- */
-
-#include "EpsilonNFAEpsilonRemover.h"
-
-#include "../../automaton/EpsilonClosure.h"
-
-namespace epsilon {
-
-automaton::NFA EpsilonNFAEpsilonRemover::remove(const automaton::NFA& origFSM)
-{
-    return origFSM;
-}
-
-automaton::NFA EpsilonNFAEpsilonRemover::remove( const automaton::EpsilonNFA & origFSM ) {
-	automaton::NFA fsm;
-
-	for( const auto & state : origFSM.getStates() )
-		fsm.addState( state );
-
-	for( const auto & state : origFSM.getInitialStates() )
-		fsm.addInitialState( state );
-
-	for( const auto & symbol : origFSM.getInputAlphabet() )
-		fsm.addInputSymbol( symbol );
-
-	/**
-	 * Step 1 from Melichar 2.41
-	 */
-	for( const auto & from : origFSM.getStates( ) )
-		for( const auto & fromClosure : automaton::EpsilonClosure::epsilonClosure( origFSM, from ) )
-			for( const auto & transition : origFSM.getSymbolTransitionsFromState( fromClosure ) )
-				for( const auto & to : transition.second )
-					fsm.addTransition( from, transition.first.second, to );
-
-	/**
-	 * Step 2 from Melichar 2.41
-	 */
-	std::set<automaton::State> finalStates;
-
-	for( const auto & q : fsm.getStates( ) )
-	{
-		const std::set<automaton::State> & cl = automaton::EpsilonClosure::epsilonClosure( origFSM, q );
-		const std::set<automaton::State> & F = origFSM.getFinalStates( );
-		std::set<automaton::State> intersect;
-
-		set_intersection( cl.begin(), cl.end(), F.begin(), F.end(), std::inserter( intersect, intersect.begin() ) );
-		if( intersect.size( ) != 0 )
-			finalStates.insert( q );
-	}
-
-	for( const auto & q : finalStates )
-		fsm.addFinalState( q );
-
-	return fsm;
-}
-
-} /* namespace epsilon */
diff --git a/alib2algo/src/epsilon/epsilonNfa/EpsilonNFAEpsilonRemover.h b/alib2algo/src/epsilon/epsilonNfa/EpsilonNFAEpsilonRemover.h
deleted file mode 100644
index c65beebcc4197cbe78ed70ed3e2316aefdb7420d..0000000000000000000000000000000000000000
--- a/alib2algo/src/epsilon/epsilonNfa/EpsilonNFAEpsilonRemover.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * EpsilonNFAEpsilonRemover.h
- *
- *  Created on: 16. 1. 2014
- *      Author: Tomas Pecka
- */
-
-#ifndef EPSILON_NFA_EPSILON_REMOVER_H_
-#define EPSILON_NFA_EPSILON_REMOVER_H_
-
-#include <map>
-#include <algorithm>
-
-#include <automaton/FSM/EpsilonNFA.h>
-#include <automaton/FSM/NFA.h>
-#include <exception/AlibException.h>
-
-namespace epsilon {
-
-class EpsilonNFAEpsilonRemover {
-public:
-    static automaton::NFA remove(const automaton::EpsilonNFA &);
-    static automaton::NFA remove(const automaton::NFA &);
-};
-
-} /* namespace epsilon */
-
-#endif /* EPSILON_NFA_EPSILON_REMOVER_H_ */
diff --git a/alib2algo/src/epsilon/fsm/FSMEpsilonRemover.cpp b/alib2algo/src/epsilon/fsm/FSMEpsilonRemover.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d05c5caafc90f05eb798d8130999e221dd61886f
--- /dev/null
+++ b/alib2algo/src/epsilon/fsm/FSMEpsilonRemover.cpp
@@ -0,0 +1,116 @@
+/*
+ * FSMEpsilonRemover.cpp
+ *
+ *  Created on: 16. 1. 2014
+ *	  Author: Tomas Pecka
+ */
+
+#include "FSMEpsilonRemover.h"
+
+#include "../../automaton/EpsilonClosure.h"
+
+namespace epsilon {
+
+automaton::DFA FSMEpsilonRemover::remove(const automaton::DFA& origFSM)
+{
+    return origFSM;
+}
+
+automaton::NFA FSMEpsilonRemover::remove(const automaton::NFA& origFSM)
+{
+    return origFSM;
+}
+
+automaton::NFA FSMEpsilonRemover::remove( const automaton::EpsilonNFA & origFSM ) {
+	automaton::NFA fsm;
+
+	for( const auto & state : origFSM.getStates() )
+		fsm.addState( state );
+
+	for( const auto & state : origFSM.getInitialStates() )
+		fsm.addInitialState( state );
+
+	for( const auto & symbol : origFSM.getInputAlphabet() )
+		fsm.addInputSymbol( symbol );
+
+	/**
+	 * Step 1 from Melichar 2.41
+	 */
+	for( const auto & from : origFSM.getStates( ) )
+		for( const auto & fromClosure : automaton::EpsilonClosure::epsilonClosure( origFSM, from ) )
+			for( const auto & transition : origFSM.getSymbolTransitionsFromState( fromClosure ) )
+				for( const auto & to : transition.second )
+					fsm.addTransition( from, transition.first.second, to );
+
+	/**
+	 * Step 2 from Melichar 2.41
+	 */
+	std::set<automaton::State> finalStates;
+
+	for( const auto & q : fsm.getStates( ) )
+	{
+		const std::set<automaton::State> & cl = automaton::EpsilonClosure::epsilonClosure( origFSM, q );
+		const std::set<automaton::State> & F = origFSM.getFinalStates( );
+		std::set<automaton::State> intersect;
+
+		set_intersection( cl.begin(), cl.end(), F.begin(), F.end(), std::inserter( intersect, intersect.begin() ) );
+		if( intersect.size( ) != 0 )
+			finalStates.insert( q );
+	}
+
+	for( const auto & q : finalStates )
+		fsm.addFinalState( q );
+
+	return fsm;
+}
+
+automaton::Automaton FSMEpsilonRemover::remove(const automaton::Automaton& automaton) {
+	automaton::Automaton* out = NULL;
+	automaton.getData().Accept((void*) &out, FSMEpsilonRemover::FSM_EPSILON_REMOVER);
+	automaton::Automaton res = std::move(*out);
+	delete out;
+	return res;
+}
+
+void FSMEpsilonRemover::Visit(void*, const automaton::UnknownAutomaton&) const {
+	throw exception::AlibException("Unsupported automaton type UnknownAutomaton");
+}
+
+void FSMEpsilonRemover::Visit(void* data, const automaton::EpsilonNFA& automaton) const {
+	automaton::Automaton* & out = *((automaton::Automaton**) data);
+	out = new automaton::Automaton(this->remove(automaton));
+}
+
+void FSMEpsilonRemover::Visit(void* data, const automaton::NFA& automaton) const {
+	automaton::Automaton* & out = *((automaton::Automaton**) data);
+	out = new automaton::Automaton(this->remove(automaton));
+}
+
+void FSMEpsilonRemover::Visit(void* data, const automaton::DFA& automaton) const {
+	automaton::Automaton* & out = *((automaton::Automaton**) data);
+	out = new automaton::Automaton(this->remove(automaton));
+}
+
+void FSMEpsilonRemover::Visit(void*, const automaton::ExtendedNFA& ) const {
+	throw exception::AlibException("Unsupported automaton type UnknownAutomaton");
+}
+
+void FSMEpsilonRemover::Visit(void*, const automaton::CompactNFA& ) const {
+	throw exception::AlibException("Unsupported automaton type UnknownAutomaton");
+}
+
+void FSMEpsilonRemover::Visit(void*, const automaton::NPDA&) const {
+	throw exception::AlibException("Unsupported automaton type UnknownAutomaton");
+}
+
+void FSMEpsilonRemover::Visit(void*, const automaton::SinglePopNPDA&) const {
+	throw exception::AlibException("Unsupported automaton type UnknownAutomaton");
+}
+
+void FSMEpsilonRemover::Visit(void*, const automaton::OneTapeDTM&) const {
+	throw exception::AlibException("Unsupported automaton type UnknownAutomaton");
+}
+
+const FSMEpsilonRemover FSMEpsilonRemover::FSM_EPSILON_REMOVER;
+
+} /* namespace epsilon */
diff --git a/alib2algo/src/epsilon/fsm/FSMEpsilonRemover.h b/alib2algo/src/epsilon/fsm/FSMEpsilonRemover.h
new file mode 100644
index 0000000000000000000000000000000000000000..4b19f9b36cabb462e58728eb64ecdb02b031bbb1
--- /dev/null
+++ b/alib2algo/src/epsilon/fsm/FSMEpsilonRemover.h
@@ -0,0 +1,50 @@
+/*
+ * FSMEpsilonRemover.h
+ *
+ *  Created on: 16. 1. 2014
+ *      Author: Tomas Pecka
+ */
+
+#ifndef FMS_EPSILON_REMOVER_H_
+#define FMS_EPSILON_REMOVER_H_
+
+#include <map>
+#include <algorithm>
+
+#include <automaton/Automaton.h>
+
+#include <automaton/FSM/EpsilonNFA.h>
+#include <automaton/FSM/NFA.h>
+#include <automaton/FSM/DFA.h>
+#include <exception/AlibException.h>
+
+namespace epsilon {
+
+class FSMEpsilonRemover : public automaton::VisitableAutomatonBase::const_visitor_type {
+public:
+	static automaton::Automaton remove( const automaton::Automaton & automaton );
+
+	/**
+	 * Computes epsilon closure of a state in epsilon nonfree automaton
+	 */
+	static automaton::NFA remove( const automaton::EpsilonNFA & fsm );
+	static automaton::NFA remove( const automaton::NFA & fsm );
+	static automaton::DFA remove( const automaton::DFA & fsm );
+
+private:
+	void Visit(void*, const automaton::UnknownAutomaton& automaton) const;
+	void Visit(void*, const automaton::EpsilonNFA& automaton) const;
+	void Visit(void*, const automaton::NFA& automaton) const;
+	void Visit(void*, const automaton::DFA& automaton) const;
+	void Visit(void*, const automaton::ExtendedNFA& automaton) const;
+	void Visit(void*, const automaton::CompactNFA& automaton) const;
+	void Visit(void*, const automaton::NPDA& automaton) const;
+	void Visit(void*, const automaton::SinglePopNPDA& automaton) const;
+	void Visit(void*, const automaton::OneTapeDTM& automaton) const;
+
+	static const FSMEpsilonRemover FSM_EPSILON_REMOVER;
+};
+
+} /* namespace epsilon */
+
+#endif /* FMS_EPSILON_REMOVER_H_ */
diff --git a/alib2algo/test-src/conversions/playTest.cpp b/alib2algo/test-src/conversions/playTest.cpp
index 03a7af3387c5ee02b60d63767a15f99e83ba8932..ee74dc2a748395cc747988e15936c36b49b2267a 100644
--- a/alib2algo/test-src/conversions/playTest.cpp
+++ b/alib2algo/test-src/conversions/playTest.cpp
@@ -10,7 +10,7 @@
 #include "generator/RandomAutomatonFactory.h"
 #include "normalize/dfa/NormalizeDFA.h"
 #include "trim/automaton/TrimFSM.h"
-#include "epsilon/epsilonNfa/EpsilonNFAEpsilonRemover.h"
+#include "epsilon/fsm/FSMEpsilonRemover.h"
 #include "minimize/dfa/MinimizeDFA.h"
 
 //#include "conversions/fa2re/StateElimination.h"
@@ -57,7 +57,7 @@ automaton::NFA playTest::randomNFA(void) const
 
 automaton::DFA playTest::mDFA(const automaton::NFA& automaton) const
 {
-    automaton::NFA nfa = epsilon::EpsilonNFAEpsilonRemover::remove(automaton);
+    automaton::NFA nfa = epsilon::FSMEpsilonRemover::remove(automaton);
     nfa = trim::TrimFSM::trim(nfa);
     automaton::DFA dfa = determinize::NFADeterminizer::determinize(nfa);
     dfa = trim::TrimFSM::trim(dfa);
diff --git a/alib2algo/test-src/conversions/re2fa/re2faTest.cpp b/alib2algo/test-src/conversions/re2fa/re2faTest.cpp
index 23f3376fe3c24dd5b9f74d1c04e0a1539fa52718..0d0d507550e7fb53051897ccf10760b69bc88d4b 100644
--- a/alib2algo/test-src/conversions/re2fa/re2faTest.cpp
+++ b/alib2algo/test-src/conversions/re2fa/re2faTest.cpp
@@ -7,7 +7,7 @@
 #include "conversions/fa2re/BrzozowskiAlgebraic.h"
 #include "determinize/nfa/NFADeterminizer.h"
 #include "minimize/dfa/MinimizeDFA.h"
-#include "epsilon/epsilonNfa/EpsilonNFAEpsilonRemover.h"
+#include "epsilon/fsm/FSMEpsilonRemover.h"
 
 #include "regexp/unbounded/UnboundedRegExp.h"
 #include "regexp/RegExpFromStringParser.h"
@@ -37,8 +37,8 @@ void re2faTest::testThompson() {
 	re2fa::Thompson thompson2;
 	automaton::EpsilonNFA enfa2 = thompson2.convert(regexp2);
 
-	automaton::NFA nfa1 = epsilon::EpsilonNFAEpsilonRemover::remove(enfa1);
-	automaton::NFA nfa2 = epsilon::EpsilonNFAEpsilonRemover::remove(enfa2);
+	automaton::NFA nfa1 = epsilon::FSMEpsilonRemover::remove(enfa1);
+	automaton::NFA nfa2 = epsilon::FSMEpsilonRemover::remove(enfa2);
 
 	automaton::DFA dfa1 = determinize::NFADeterminizer::determinize(nfa1);
 	automaton::DFA dfa2 = determinize::NFADeterminizer::determinize(nfa2);