From 2a40d60fee56d592f7f1b87128bcc6416f26c0b3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Pecka?= <tomaspecka@gmail.com>
Date: Fri, 17 Jan 2014 20:06:20 +0100
Subject: [PATCH] aEpsilon: removes eps-transitions. TODO: implement atrim to
 get rid of unreachable states.

---
 aepsilon/.cproject              | 127 ++++++++++++++++++++++++++++++++
 aepsilon/.project               |  27 +++++++
 aepsilon/src/EpsilonClosure.cpp |  64 ++++++++++++++++
 aepsilon/src/EpsilonClosure.h   |  40 ++++++++++
 aepsilon/src/EpsilonRemover.cpp |  84 +++++++++++++++++++++
 aepsilon/src/EpsilonRemover.h   |  43 +++++++++++
 aepsilon/src/aepsilon.fsm.cpp   |  67 +++++++++++++++++
 7 files changed, 452 insertions(+)
 create mode 100644 aepsilon/.cproject
 create mode 100644 aepsilon/.project
 create mode 100644 aepsilon/src/EpsilonClosure.cpp
 create mode 100644 aepsilon/src/EpsilonClosure.h
 create mode 100644 aepsilon/src/EpsilonRemover.cpp
 create mode 100644 aepsilon/src/EpsilonRemover.h
 create mode 100644 aepsilon/src/aepsilon.fsm.cpp

diff --git a/aepsilon/.cproject b/aepsilon/.cproject
new file mode 100644
index 0000000000..0117c53712
--- /dev/null
+++ b/aepsilon/.cproject
@@ -0,0 +1,127 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
+	<storageModule moduleId="org.eclipse.cdt.core.settings">
+		<cconfiguration id="cdt.managedbuild.config.gnu.exe.debug.301702221">
+			<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.config.gnu.exe.debug.301702221" moduleId="org.eclipse.cdt.core.settings" name="Debug">
+				<externalSettings/>
+				<extensions>
+					<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
+				</extensions>
+			</storageModule>
+			<storageModule moduleId="cdtBuildSystem" version="4.0.0">
+				<configuration artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug,org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.exe.debug.301702221" name="Debug" parent="cdt.managedbuild.config.gnu.exe.debug">
+					<folderInfo id="cdt.managedbuild.config.gnu.exe.debug.301702221." name="/" resourcePath="">
+						<toolChain id="cdt.managedbuild.toolchain.gnu.exe.debug.1965136465" name="Linux GCC" superClass="cdt.managedbuild.toolchain.gnu.exe.debug">
+							<targetPlatform id="cdt.managedbuild.target.gnu.platform.exe.debug.1571136388" name="Debug Platform" superClass="cdt.managedbuild.target.gnu.platform.exe.debug"/>
+							<builder buildPath="${workspace_loc:/aepsilon}/Debug" id="cdt.managedbuild.target.gnu.builder.exe.debug.337087363" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" superClass="cdt.managedbuild.target.gnu.builder.exe.debug"/>
+							<tool id="cdt.managedbuild.tool.gnu.archiver.base.1633479823" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.base"/>
+							<tool id="cdt.managedbuild.tool.gnu.cpp.compiler.exe.debug.1356595110" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.exe.debug">
+								<option id="gnu.cpp.compiler.exe.debug.option.optimization.level.771995285" name="Optimization Level" superClass="gnu.cpp.compiler.exe.debug.option.optimization.level" value="gnu.cpp.compiler.optimization.level.none" valueType="enumerated"/>
+								<option id="gnu.cpp.compiler.exe.debug.option.debugging.level.1569347947" name="Debug Level" superClass="gnu.cpp.compiler.exe.debug.option.debugging.level" value="gnu.cpp.compiler.debugging.level.max" valueType="enumerated"/>
+								<option id="gnu.cpp.compiler.option.include.paths.586841051" name="Include paths (-I)" superClass="gnu.cpp.compiler.option.include.paths" valueType="includePath">
+									<listOptionValue builtIn="false" value="&quot;${workspace_loc:/alib/src}&quot;"/>
+									<listOptionValue builtIn="false" value="/usr/include/libxml2"/>
+								</option>
+								<option id="gnu.cpp.compiler.option.other.other.349305529" name="Other flags" superClass="gnu.cpp.compiler.option.other.other" value="-c -fmessage-length=0 -std=c++11" valueType="string"/>
+								<inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.784818493" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
+							</tool>
+							<tool id="cdt.managedbuild.tool.gnu.c.compiler.exe.debug.510163848" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.exe.debug">
+								<option defaultValue="gnu.c.optimization.level.none" id="gnu.c.compiler.exe.debug.option.optimization.level.1861897714" name="Optimization Level" superClass="gnu.c.compiler.exe.debug.option.optimization.level" valueType="enumerated"/>
+								<option id="gnu.c.compiler.exe.debug.option.debugging.level.1116496550" name="Debug Level" superClass="gnu.c.compiler.exe.debug.option.debugging.level" value="gnu.c.debugging.level.max" valueType="enumerated"/>
+								<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.604475552" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
+							</tool>
+							<tool id="cdt.managedbuild.tool.gnu.c.linker.exe.debug.1704484664" name="GCC C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.exe.debug"/>
+							<tool id="cdt.managedbuild.tool.gnu.cpp.linker.exe.debug.482915176" name="GCC C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.exe.debug">
+								<option id="gnu.cpp.link.option.libs.1247816176" name="Libraries (-l)" superClass="gnu.cpp.link.option.libs" valueType="libs">
+									<listOptionValue builtIn="false" value="alib"/>
+								</option>
+								<option id="gnu.cpp.link.option.paths.1118907515" name="Library search path (-L)" superClass="gnu.cpp.link.option.paths" valueType="libPaths">
+									<listOptionValue builtIn="false" value="&quot;${workspace_loc:/alib/Debug}&quot;"/>
+								</option>
+								<inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.1471550573" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input">
+									<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
+									<additionalInput kind="additionalinput" paths="$(LIBS)"/>
+								</inputType>
+							</tool>
+							<tool id="cdt.managedbuild.tool.gnu.assembler.exe.debug.1234033066" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.exe.debug">
+								<inputType id="cdt.managedbuild.tool.gnu.assembler.input.1944208227" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
+							</tool>
+						</toolChain>
+					</folderInfo>
+				</configuration>
+			</storageModule>
+			<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
+		</cconfiguration>
+		<cconfiguration id="cdt.managedbuild.config.gnu.exe.release.590630146">
+			<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.config.gnu.exe.release.590630146" moduleId="org.eclipse.cdt.core.settings" name="Release">
+				<externalSettings/>
+				<extensions>
+					<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
+				</extensions>
+			</storageModule>
+			<storageModule moduleId="cdtBuildSystem" version="4.0.0">
+				<configuration artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release,org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.exe.release.590630146" name="Release" parent="cdt.managedbuild.config.gnu.exe.release">
+					<folderInfo id="cdt.managedbuild.config.gnu.exe.release.590630146." name="/" resourcePath="">
+						<toolChain id="cdt.managedbuild.toolchain.gnu.exe.release.1710969835" name="Linux GCC" superClass="cdt.managedbuild.toolchain.gnu.exe.release">
+							<targetPlatform id="cdt.managedbuild.target.gnu.platform.exe.release.1053111294" name="Debug Platform" superClass="cdt.managedbuild.target.gnu.platform.exe.release"/>
+							<builder buildPath="${workspace_loc:/aepsilon}/Release" id="cdt.managedbuild.target.gnu.builder.exe.release.1659891820" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" superClass="cdt.managedbuild.target.gnu.builder.exe.release"/>
+							<tool id="cdt.managedbuild.tool.gnu.archiver.base.425902240" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.base"/>
+							<tool id="cdt.managedbuild.tool.gnu.cpp.compiler.exe.release.882969905" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.exe.release">
+								<option id="gnu.cpp.compiler.exe.release.option.optimization.level.1454707367" name="Optimization Level" superClass="gnu.cpp.compiler.exe.release.option.optimization.level" value="gnu.cpp.compiler.optimization.level.most" valueType="enumerated"/>
+								<option id="gnu.cpp.compiler.exe.release.option.debugging.level.642441439" name="Debug Level" superClass="gnu.cpp.compiler.exe.release.option.debugging.level" value="gnu.cpp.compiler.debugging.level.none" valueType="enumerated"/>
+								<inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.621269693" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
+							</tool>
+							<tool id="cdt.managedbuild.tool.gnu.c.compiler.exe.release.1766472279" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.exe.release">
+								<option defaultValue="gnu.c.optimization.level.most" id="gnu.c.compiler.exe.release.option.optimization.level.939566081" name="Optimization Level" superClass="gnu.c.compiler.exe.release.option.optimization.level" valueType="enumerated"/>
+								<option id="gnu.c.compiler.exe.release.option.debugging.level.346029365" name="Debug Level" superClass="gnu.c.compiler.exe.release.option.debugging.level" value="gnu.c.debugging.level.none" valueType="enumerated"/>
+								<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.1454390559" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
+							</tool>
+							<tool id="cdt.managedbuild.tool.gnu.c.linker.exe.release.192937594" name="GCC C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.exe.release"/>
+							<tool id="cdt.managedbuild.tool.gnu.cpp.linker.exe.release.206295145" name="GCC C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.exe.release">
+								<inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.871437344" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input">
+									<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
+									<additionalInput kind="additionalinput" paths="$(LIBS)"/>
+								</inputType>
+							</tool>
+							<tool id="cdt.managedbuild.tool.gnu.assembler.exe.release.1248212114" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.exe.release">
+								<inputType id="cdt.managedbuild.tool.gnu.assembler.input.746139405" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
+							</tool>
+						</toolChain>
+					</folderInfo>
+				</configuration>
+			</storageModule>
+			<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
+		</cconfiguration>
+	</storageModule>
+	<storageModule moduleId="cdtBuildSystem" version="4.0.0">
+		<project id="aepsilon.cdt.managedbuild.target.gnu.exe.307189470" name="Executable" projectType="cdt.managedbuild.target.gnu.exe"/>
+	</storageModule>
+	<storageModule moduleId="scannerConfiguration">
+		<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
+		<scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.exe.release.590630146;cdt.managedbuild.config.gnu.exe.release.590630146.;cdt.managedbuild.tool.gnu.cpp.compiler.exe.release.882969905;cdt.managedbuild.tool.gnu.cpp.compiler.input.621269693">
+			<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
+		</scannerConfigBuildInfo>
+		<scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.exe.debug.301702221;cdt.managedbuild.config.gnu.exe.debug.301702221.;cdt.managedbuild.tool.gnu.cpp.compiler.exe.debug.1356595110;cdt.managedbuild.tool.gnu.cpp.compiler.input.784818493">
+			<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
+		</scannerConfigBuildInfo>
+		<scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.exe.debug.301702221;cdt.managedbuild.config.gnu.exe.debug.301702221.;cdt.managedbuild.tool.gnu.c.compiler.exe.debug.510163848;cdt.managedbuild.tool.gnu.c.compiler.input.604475552">
+			<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
+		</scannerConfigBuildInfo>
+		<scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.exe.release.590630146;cdt.managedbuild.config.gnu.exe.release.590630146.;cdt.managedbuild.tool.gnu.c.compiler.exe.release.1766472279;cdt.managedbuild.tool.gnu.c.compiler.input.1454390559">
+			<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
+		</scannerConfigBuildInfo>
+	</storageModule>
+	<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
+	<storageModule moduleId="refreshScope"/>
+	<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
+</cproject>
diff --git a/aepsilon/.project b/aepsilon/.project
new file mode 100644
index 0000000000..f3aff09913
--- /dev/null
+++ b/aepsilon/.project
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>aepsilon</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
+			<triggers>clean,full,incremental,</triggers>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
+			<triggers>full,incremental,</triggers>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.cdt.core.cnature</nature>
+		<nature>org.eclipse.cdt.core.ccnature</nature>
+		<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
+		<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
+	</natures>
+</projectDescription>
diff --git a/aepsilon/src/EpsilonClosure.cpp b/aepsilon/src/EpsilonClosure.cpp
new file mode 100644
index 0000000000..06972d3baf
--- /dev/null
+++ b/aepsilon/src/EpsilonClosure.cpp
@@ -0,0 +1,64 @@
+/*
+ * EpsilonClosure.cpp
+ *
+ *  Created on: 16. 1. 2014
+ *      Author: tomas
+ */
+
+#include "EpsilonClosure.h"
+
+using namespace alib;
+using namespace automaton;
+using namespace std;
+
+namespace epsilon
+{
+
+EpsilonClosure::EpsilonClosure( const set<State> & states,
+        const std::map<automaton::State, std::set<automaton::TransitionFSM>> & transitionsBySource ) :
+        m_transitionsBySource( transitionsBySource ), m_states ( states )
+{
+    for( auto state : m_states )
+        closure( state );
+}
+
+set<TransitionFSM> EpsilonClosure::getTr ( const State & state ) const
+{
+    if( m_transitionsBySource.find( state ) == m_transitionsBySource.end( ) )
+        return set<TransitionFSM>();
+
+    return m_transitionsBySource.at( state );
+}
+
+void EpsilonClosure::closure( const State & state )
+{
+    queue<State> q;
+    map<State, bool> visited;
+
+    for( auto state : m_states )
+        visited[ state ] = false;
+
+    q.push( state );
+    while( ! q.empty( ) )
+    {
+        State & s = q.front( );
+        q.pop( );
+        visited[s] = true;
+        m_closure[ state ].insert( s );
+
+        for( auto transition : getTr( s ) )
+            if( transition.getInput() == Symbol( "" ) && visited [ transition.getTo( ) ] == false )
+                q.push( transition.getTo( ) );
+
+    }
+}
+
+set<State> EpsilonClosure::getClosure( const State & state ) const
+{
+    if( m_closure.find( state ) == m_closure.end( ) )
+        throw AlibException( "EpsilonClosure: Trying to get closure of state not in automata." );
+
+    return m_closure.at( state );
+}
+
+} /* namespace epsilon */
diff --git a/aepsilon/src/EpsilonClosure.h b/aepsilon/src/EpsilonClosure.h
new file mode 100644
index 0000000000..226afd11bf
--- /dev/null
+++ b/aepsilon/src/EpsilonClosure.h
@@ -0,0 +1,40 @@
+/*
+ * EpsilonClosure.h
+ *
+ *  Created on: 16. 1. 2014
+ *      Author: tomas
+ */
+
+#ifndef EPSILONCLOSURE_H_
+#define EPSILONCLOSURE_H_
+
+#include <automaton/FSM/FSM.h>
+#include <automaton/State.h>
+
+#include <AlibException.h>
+
+#include <set>
+#include <map>
+#include <queue>
+
+namespace epsilon
+{
+
+class EpsilonClosure
+{
+public:
+    EpsilonClosure( const std::set<automaton::State> & states, const std::map<automaton::State, std::set<automaton::TransitionFSM>> & transitionsBySource );
+    std::set<automaton::State> getClosure( const automaton::State & state ) const;
+
+private:
+    void closure( const automaton::State & state );
+    std::set<automaton::TransitionFSM> getTr ( const automaton::State & state ) const;
+
+    std::map<const automaton::State, std::set<automaton::State>> m_closure;
+    const std::map<automaton::State, std::set<automaton::TransitionFSM>> & m_transitionsBySource;
+    const std::set<automaton::State> & m_states;
+};
+
+} /* namespace epsilon */
+
+#endif /* EPSILONCLOSURE_H_ */
diff --git a/aepsilon/src/EpsilonRemover.cpp b/aepsilon/src/EpsilonRemover.cpp
new file mode 100644
index 0000000000..31de47e53a
--- /dev/null
+++ b/aepsilon/src/EpsilonRemover.cpp
@@ -0,0 +1,84 @@
+/*
+ * EpsilonRemover.cpp
+ *
+ *  Created on: 16. 1. 2014
+ *      Author: tomas
+ */
+
+#include "EpsilonRemover.h"
+
+using namespace alib;
+using namespace automaton;
+
+namespace epsilon
+{
+
+EpsilonRemover::EpsilonRemover( const FSM & fsm ) : m_origFSM( fsm )
+{
+    for( auto t : fsm.getTransitions( ) )
+        m_transitionsBySourceState[ t.getFrom() ].insert( t );
+
+    m_closure = new EpsilonClosure( fsm.getStates( ), m_transitionsBySourceState );
+
+    for( auto state : fsm.getStates() )
+        m_fsm.addState( state );
+
+    for( auto state : fsm.getInitialStates() )
+        m_fsm.addInitialState( state );
+
+    for( auto symbol : fsm.getInputAlphabet() )
+        m_fsm.addInputSymbol( symbol );
+}
+
+EpsilonRemover::~EpsilonRemover( void )
+{
+    delete m_closure;
+}
+
+const FSM EpsilonRemover::remove( void )
+{
+    setTransitions( );
+    setFinalStates( );
+
+    return m_fsm;
+}
+
+/**
+ * Step 1 from Melichar 2.41
+ */
+void EpsilonRemover::setTransitions( void )
+{
+    for( auto q : m_fsm.getStates( ) )
+        for( auto p : m_closure->getClosure( q ) )
+            for( auto transition : m_transitionsBySourceState[p] )
+                if( transition.getInput() != Symbol( "" ) )
+                    m_fsm.addTransition( q, transition.getInput( ), transition.getTo( ) );
+}
+
+/**
+ * Step 2 from Melichar 2.41
+ */
+void EpsilonRemover::setFinalStates( void )
+{
+    for( auto q : m_fsm.getStates( ) )
+    {
+        set<State> cl = m_closure->getClosure( q );
+        set<State> f = m_origFSM.getFinalStates( );
+        set<State> intersect;
+
+        set_intersection( cl.begin(), cl.end(), f.begin(), f.end(), std::inserter( intersect, intersect.begin() ) );
+        if( intersect.size() != 0 )
+        {
+            try
+            {
+                m_fsm.addFinalState( q );
+            }
+            catch( AlibException & e )
+            {
+                // already final state. proceed
+            }
+        }
+    }
+}
+
+} /* namespace epsilon */
diff --git a/aepsilon/src/EpsilonRemover.h b/aepsilon/src/EpsilonRemover.h
new file mode 100644
index 0000000000..748a514cfa
--- /dev/null
+++ b/aepsilon/src/EpsilonRemover.h
@@ -0,0 +1,43 @@
+/*
+ * EpsilonRemover.h
+ *
+ *  Created on: 16. 1. 2014
+ *      Author: tomas
+ */
+
+#ifndef EPSILONREMOVER_H_
+#define EPSILONREMOVER_H_
+
+#include <map>
+#include <algorithm>
+
+#include <automaton/FSM/FSM.h>
+#include <AlibException.h>
+
+#include "EpsilonClosure.h"
+
+namespace epsilon
+{
+
+class EpsilonRemover
+{
+public:
+    EpsilonRemover( const automaton::FSM & fsm );
+    ~EpsilonRemover( void );
+    const automaton::FSM remove( void );
+
+private:
+    void setTransitions( void );
+    void setFinalStates( void );
+
+    const automaton::FSM & m_origFSM;
+    automaton::FSM m_fsm;
+
+    EpsilonClosure * m_closure;
+    std::map<automaton::State, std::set<automaton::TransitionFSM>> m_transitionsBySourceState;
+
+};
+
+} /* namespace epsilon */
+
+#endif /* EPSILONREMOVER_H_ */
diff --git a/aepsilon/src/aepsilon.fsm.cpp b/aepsilon/src/aepsilon.fsm.cpp
new file mode 100644
index 0000000000..dadd23e802
--- /dev/null
+++ b/aepsilon/src/aepsilon.fsm.cpp
@@ -0,0 +1,67 @@
+    #include <iostream>
+
+#include <AutomatonFactory.h>
+#include <AlibException.h>
+#include <automaton/AutomatonParser.h>
+
+#include <sax/SaxInterface.h>
+#include <sax/ParserException.h>
+
+#include "EpsilonRemover.h"
+
+using namespace std;
+using namespace automaton;
+using namespace alib;
+using namespace sax;
+
+using namespace epsilon;
+
+int main(int argc, char** argv) {
+    int fileParameterIndex = -1;
+
+    try {
+        if( argc > 1 )
+        {
+            for( int i = 1; i < argc; i++ )
+            {
+                if( string( "-h" ).compare( argv[i] ) == 0 )
+                {
+                    std::cout << "Removes eps transitions from NFA." << std::endl;
+                    std::cout << "Usage: aepsilon [automaton.xml]" << std::endl;
+                    return 1;
+                }
+                else
+                {
+                    if(fileParameterIndex == -1)
+                        fileParameterIndex = i;
+                    else
+                        throw AlibException("Only one file can be passed as parameter - " + string(argv[i]) + " " + string(argv[fileParameterIndex]));
+                }
+            }
+        }
+
+        std::list<Token> tokens;
+
+        if(fileParameterIndex != -1)
+        {
+            SaxInterface::parseFile(argv[fileParameterIndex],tokens);
+        }
+        else
+        {
+            string input(istreambuf_iterator<char>(cin), (istreambuf_iterator<char>()));
+            SaxInterface::parseMemory(input, tokens);
+        }
+
+        UnknownAutomaton automaton = AutomatonParser::parse( tokens );
+        FSM fsm = AutomatonFactory::buildFSM( automaton );
+
+        EpsilonRemover epsrem ( fsm );
+        epsrem.remove().toXML( cout );
+
+    } catch (AlibException& e) {
+        cout << e.what() << endl;
+        return -1;
+    }
+
+    cout.flush();
+}
-- 
GitLab