diff --git a/alib2algo/src/grammar/generate/CockeYoungerKasami.cpp b/alib2algo/src/grammar/generate/CockeYoungerKasami.cpp
index 76c1ae8dc497732a349cc1e63298ff322c0dea37..bc75619a6bafa0ca86315695596fad4fdb0d9e02 100644
--- a/alib2algo/src/grammar/generate/CockeYoungerKasami.cpp
+++ b/alib2algo/src/grammar/generate/CockeYoungerKasami.cpp
@@ -6,76 +6,11 @@
  */
 
 #include "CockeYoungerKasami.h"
-#include <global/GlobalData.h>
 
 namespace grammar {
 
 namespace generate {
 
-bool CockeYoungerKasami::generate ( const grammar::CNF < > & grammar, const string::LinearString < > & string ) {
-	unsigned stringSize = string.getContent ( ).size ( );
-
-	if ( ( stringSize == 0 ) && grammar.getGeneratesEpsilon ( ) ) return true;
-
-	std::vector < std::vector < std::set < alphabet::Symbol > > > data;
-	data.resize ( stringSize );
-
-	for ( unsigned i = 0; i < stringSize; i++ )
-		data[i].resize ( stringSize - i );
-
-	for ( unsigned i = 0; i < stringSize; i++ )
-		for ( const std::pair < const alphabet::Symbol, std::set < std::variant < alphabet::Symbol, std::pair < alphabet::Symbol, alphabet::Symbol > > > > rule : grammar.getRules ( ) ) {
-			const alphabet::Symbol & lhs = rule.first;
-
-			for ( const std::variant < alphabet::Symbol, std::pair < alphabet::Symbol, alphabet::Symbol > > rhs : rule.second )
-				if ( rhs.is < alphabet::Symbol > ( ) && ( rhs.get < alphabet::Symbol > ( ) == string.getContent ( )[i] ) )
-					data[0][i].insert ( lhs );
-
-		}
-
-
-
-	for ( unsigned i = 1; i < stringSize; i++ )
-		for ( unsigned j = 0; j < stringSize - i; j++ ) {
-			std::set < alphabet::Symbol > & targetCell = data[i][j]; // Element to compute
-
-			for ( unsigned k = 0; k < i; k++ ) {
-				const std::set < alphabet::Symbol > & vertical = data[k][j];
-				const std::set < alphabet::Symbol > & diagonal = data[i - 1 - k][j + 1 + k]; // Sources of data
-
-				for ( const alphabet::Symbol & verticalElement : vertical ) {
-					for ( const alphabet::Symbol & diagonalElement : diagonal )
-
-						for ( const std::pair < const alphabet::Symbol, std::set < std::variant < alphabet::Symbol, std::pair < alphabet::Symbol, alphabet::Symbol > > > > rule : grammar.getRules ( ) ) {
-							const alphabet::Symbol & lhs = rule.first;
-
-							for ( const std::variant < alphabet::Symbol, std::pair < alphabet::Symbol, alphabet::Symbol > > rhs : rule.second )
-								if ( rhs.is < std::pair < alphabet::Symbol, alphabet::Symbol > > ( ) ) {
-									const std::pair < alphabet::Symbol, alphabet::Symbol > rhsp = rhs.get < std::pair < alphabet::Symbol, alphabet::Symbol > > ( );
-
-									if ( ( rhsp.first == verticalElement ) && ( rhsp.second == diagonalElement ) )
-										targetCell.insert ( lhs );
-								}
-
-						}
-
-				}
-			}
-		}
-
-
-
-	if ( common::GlobalData::verbose )
-		for ( const std::vector < std::set < alphabet::Symbol > > & row : data ) {
-			for ( const std::set < alphabet::Symbol > & element : row )
-				std::clog << element << " ";
-
-			std::clog << std::endl;
-		}
-
-	return data[stringSize - 1][0].count ( grammar.getInitialSymbol ( ) );
-}
-
 auto CockeYoungerKasamiCNF = CockeYoungerKasami::RegistratorWrapper < bool, grammar::CNF < > > ( CockeYoungerKasami::generate );
 
 bool CockeYoungerKasami::generate ( const grammar::Grammar & grammar, const string::LinearString < > & string ) {
diff --git a/alib2algo/src/grammar/generate/CockeYoungerKasami.h b/alib2algo/src/grammar/generate/CockeYoungerKasami.h
index 8926099d0a2f2e131247072f3331d8668992b295..e811bb99e2441a746cb7e7b374c9ccda280123ff 100644
--- a/alib2algo/src/grammar/generate/CockeYoungerKasami.h
+++ b/alib2algo/src/grammar/generate/CockeYoungerKasami.h
@@ -9,6 +9,7 @@
 #define COCKE_YOUNGER_KASAMI_H_
 
 #include <core/multipleDispatch.hpp>
+#include <global/GlobalData.h>
 
 #include <grammar/Grammar.h>
 #include <grammar/ContextFree/CNF.h>
@@ -25,10 +26,74 @@ class CockeYoungerKasami : public std::SingleDispatch < CockeYoungerKasami, bool
 public:
 	static bool generate ( const grammar::Grammar & grammar, const string::LinearString < > & string );
 
-	static bool generate ( const grammar::CNF < > & grammar, const string::LinearString < > & string );
+	template < class SymbolType >
+	static bool generate ( const grammar::CNF < SymbolType > & grammar, const string::LinearString < SymbolType > & string );
 
 };
 
+template < class SymbolType >
+bool CockeYoungerKasami::generate ( const grammar::CNF < SymbolType > & grammar, const string::LinearString < SymbolType > & string ) {
+	unsigned stringSize = string.getContent ( ).size ( );
+
+	if ( ( stringSize == 0 ) && grammar.getGeneratesEpsilon ( ) ) return true;
+
+	std::vector < std::vector < std::set < SymbolType > > > data;
+	data.resize ( stringSize );
+
+	for ( unsigned i = 0; i < stringSize; i++ )
+		data[i].resize ( stringSize - i );
+
+	for ( unsigned i = 0; i < stringSize; i++ )
+		for ( const std::pair < const SymbolType, std::set < std::variant < SymbolType, std::pair < SymbolType, SymbolType > > > > rule : grammar.getRules ( ) ) {
+			const SymbolType & lhs = rule.first;
+
+			for ( const std::variant < SymbolType, std::pair < SymbolType, SymbolType > > rhs : rule.second )
+				if ( rhs.template is < SymbolType > ( ) && ( rhs.template get < SymbolType > ( ) == string.getContent ( )[i] ) )
+					data[0][i].insert ( lhs );
+
+		}
+
+	for ( unsigned i = 1; i < stringSize; i++ )
+		for ( unsigned j = 0; j < stringSize - i; j++ ) {
+			std::set < SymbolType > & targetCell = data[i][j]; // Element to compute
+
+			for ( unsigned k = 0; k < i; k++ ) {
+				const std::set < SymbolType > & vertical = data[k][j];
+				const std::set < SymbolType > & diagonal = data[i - 1 - k][j + 1 + k]; // Sources of data
+
+				for ( const SymbolType & verticalElement : vertical ) {
+					for ( const SymbolType & diagonalElement : diagonal )
+
+						for ( const std::pair < const SymbolType, std::set < std::variant < SymbolType, std::pair < SymbolType, SymbolType > > > > rule : grammar.getRules ( ) ) {
+							const SymbolType & lhs = rule.first;
+
+							for ( const std::variant < SymbolType, std::pair < SymbolType, SymbolType > > rhs : rule.second )
+								if ( rhs.template is < std::pair < SymbolType, SymbolType > > ( ) ) {
+									const std::pair < SymbolType, SymbolType > rhsp = rhs.template get < std::pair < SymbolType, SymbolType > > ( );
+
+									if ( ( rhsp.first == verticalElement ) && ( rhsp.second == diagonalElement ) )
+										targetCell.insert ( lhs );
+								}
+
+						}
+
+				}
+			}
+		}
+
+
+
+	if ( common::GlobalData::verbose )
+		for ( const std::vector < std::set < SymbolType > > & row : data ) {
+			for ( const std::set < SymbolType > & element : row )
+				std::clog << element << " ";
+
+			std::clog << std::endl;
+		}
+
+	return data[stringSize - 1][0].count ( grammar.getInitialSymbol ( ) );
+}
+
 } /* namespace generate */
 
 } /* namespace grammar */
diff --git a/alib2algo/src/grammar/generate/GenerateUpToLength.cpp b/alib2algo/src/grammar/generate/GenerateUpToLength.cpp
index 3a9a881c68160593ca71c2ab1fbfb678aa9c39f9..4ad8f0f544d49e80fd637833c26105a814eef961 100644
--- a/alib2algo/src/grammar/generate/GenerateUpToLength.cpp
+++ b/alib2algo/src/grammar/generate/GenerateUpToLength.cpp
@@ -7,60 +7,10 @@
 
 #include "GenerateUpToLength.h"
 
-#include <grammar/ContextFree/EpsilonFreeCFG.h>
-#include <grammar/ContextFree/GNF.h>
-#include <grammar/ContextFree/CNF.h>
-#include <grammar/Regular/LeftRG.h>
-#include <grammar/Regular/RightRG.h>
-
-#include <deque>
-
 namespace grammar {
 
 namespace generate {
 
-template<class T>
-std::set<string::LinearString < >> GenerateUpToLength::generate( const T & grammar, unsigned length ) {
-	std::set<string::LinearString < >> res;
-
-	std::map<alphabet::Symbol, std::set<std::vector<alphabet::Symbol>>> rules = grammar.getRawRules();
-	if(grammar.getGeneratesEpsilon()) {
-		res.insert(string::LinearString < > {});
-		rules[grammar.getInitialSymbol()].erase(std::vector<alphabet::Symbol> {});
-	}
-
-	std::deque<std::pair<std::vector<alphabet::Symbol>, std::vector<alphabet::Symbol>>> data;
-	data.push_back(std::make_pair(std::vector<alphabet::Symbol>{}, std::vector<alphabet::Symbol>{grammar.getInitialSymbol()}));
-	while(!data.empty()) {
-		std::pair<std::vector<alphabet::Symbol>, std::vector<alphabet::Symbol>> item = std::move(data.back());
-		data.pop_back();
-
-		alphabet::Symbol nonterminal = std::move(item.second.back());
-		item.second.pop_back();
-		if(rules.find(nonterminal) == rules.end()) continue;
-
-		for(const std::vector<alphabet::Symbol>& rhs : rules.find(nonterminal)->second) {
-			if(item.first.size() + item.second.size() + rhs.size() > length) continue;
-
-			std::vector<alphabet::Symbol> newStack(item.second);
-			std::vector<alphabet::Symbol> newString(item.first);
-			newStack.insert(newStack.end(), rhs.rbegin(), rhs.rend());
-
-			while(!newStack.empty() && grammar.getTerminalAlphabet().count(newStack.back())) {
-				newString.push_back(std::move(newStack.back()));
-				newStack.pop_back();
-			}
-
-			if(newStack.empty()) {
-				res.insert(string::LinearString < >(newString));
-			} else {
-				data.push_back(std::make_pair(std::move(newString), std::move(newStack)));
-			}
-		}
-	}
-	return res;
-}
-
 auto GenerateUpToLengthEpsilonFreeCFG = GenerateUpToLength::RegistratorWrapper<std::set<string::LinearString < >>, grammar::EpsilonFreeCFG < > >(GenerateUpToLength::generate);
 auto GenerateUpToLengthGNF = GenerateUpToLength::RegistratorWrapper<std::set<string::LinearString < >>, grammar::GNF < > >(GenerateUpToLength::generate);
 auto GenerateUpToLengthCNF = GenerateUpToLength::RegistratorWrapper<std::set<string::LinearString < >>, grammar::CNF < > >(GenerateUpToLength::generate);
diff --git a/alib2algo/src/grammar/generate/GenerateUpToLength.h b/alib2algo/src/grammar/generate/GenerateUpToLength.h
index 4fd0ddd8bbd9784b1c28b3aa8ac19752faee358b..30e457abc22d4db3725c4060273511cf8e81aa3b 100644
--- a/alib2algo/src/grammar/generate/GenerateUpToLength.h
+++ b/alib2algo/src/grammar/generate/GenerateUpToLength.h
@@ -13,6 +13,13 @@
 #include <grammar/Grammar.h>
 #include <string/LinearString.h>
 #include <set>
+#include <deque>
+
+#include <grammar/ContextFree/EpsilonFreeCFG.h>
+#include <grammar/ContextFree/GNF.h>
+#include <grammar/ContextFree/CNF.h>
+#include <grammar/Regular/LeftRG.h>
+#include <grammar/Regular/RightRG.h>
 
 namespace grammar {
 
@@ -21,14 +28,58 @@ namespace generate {
 /**
  * Implements algorithms from Melichar, chapter 3.3
  */
-class GenerateUpToLength : public std::SingleDispatch<GenerateUpToLength, std::set < string::LinearString < > >, const grammar::GrammarBase &, unsigned> {
+class GenerateUpToLength : public std::SingleDispatch < GenerateUpToLength, std::set < string::LinearString < > >, const grammar::GrammarBase &, unsigned > {
 public:
-	static std::set<string::LinearString < >> generate( const grammar::Grammar & grammar, unsigned length );
+	static std::set < string::LinearString < > > generate( const grammar::Grammar & grammar, unsigned length );
 
-	template<class T>
-	static std::set<string::LinearString < >> generate( const T & grammar, unsigned length );
+	template < class T, class SymbolType = typename grammar::SymbolTypeOfGrammar < T > >
+	static std::set < string::LinearString < SymbolType > > generate ( const T & grammar, unsigned length );
 };
 
+template < class T, class SymbolType >
+std::set < string::LinearString < SymbolType > > GenerateUpToLength::generate ( const T & grammar, unsigned length ) {
+	std::set < string::LinearString < SymbolType > > res;
+
+	std::map < SymbolType, std::set < std::vector < SymbolType > > > rules = grammar.getRawRules();
+	if ( grammar.getGeneratesEpsilon ( ) ) {
+		res.insert ( string::LinearString < SymbolType > { } );
+		rules [ grammar.getInitialSymbol ( ) ].erase ( std::vector < SymbolType > { } );
+	}
+
+	std::deque < std::pair < std::vector < SymbolType >, std::vector < SymbolType > > > data;
+	data.push_back ( std::make_pair ( std::vector < SymbolType > { }, std::vector < SymbolType > { grammar.getInitialSymbol ( ) } ) );
+
+	while ( ! data.empty ( ) ) {
+		std::pair < std::vector < SymbolType >, std::vector < SymbolType > > item = std::move ( data.back ( ) );
+		data.pop_back ( );
+
+		SymbolType nonterminal = std::move ( item.second.back ( ) );
+		item.second.pop_back ( );
+		if ( rules.find ( nonterminal ) == rules.end ( ) ) continue;
+
+		for ( const std::vector < SymbolType > & rhs : rules.find ( nonterminal )->second ) {
+			if ( item.first.size ( ) + item.second.size ( ) + rhs.size ( ) > length ) continue;
+
+			std::vector < SymbolType > newStack ( item.second );
+			std::vector < SymbolType > newString ( item.first );
+			newStack.insert ( newStack.end ( ), rhs.rbegin ( ), rhs.rend ( ) );
+
+			while ( ! newStack.empty ( ) && grammar.getTerminalAlphabet ( ).count ( newStack.back ( ) ) ) {
+				newString.push_back ( std::move(newStack.back ( ) ) );
+				newStack.pop_back ( );
+			}
+
+			if ( newStack.empty ( ) ) {
+				res.insert ( string::LinearString < SymbolType > ( newString ) );
+			} else {
+				data.push_back ( std::make_pair ( std::move ( newString ), std::move ( newStack ) ) );
+			}
+		}
+	}
+
+	return res;
+}
+
 } /* namespace generate */
 
 } /* namespace grammar */
diff --git a/alib2algo/src/grammar/simplify/SimpleRulesRemover.cpp b/alib2algo/src/grammar/simplify/SimpleRulesRemover.cpp
index 51e2b43bcfdfe1becdfba4c281d6478d75d63380..dad3a970c9a9914c19977981ac68ee04f9d2698d 100644
--- a/alib2algo/src/grammar/simplify/SimpleRulesRemover.cpp
+++ b/alib2algo/src/grammar/simplify/SimpleRulesRemover.cpp
@@ -7,124 +7,24 @@
 
 #include "SimpleRulesRemover.h"
 
-#include "../properties/NonterminalUnitRuleCycle.h"
-
 namespace grammar {
 
 namespace simplify {
 
-template<class T>
-T removeEpsilonFree( const T & origGrammar ) {
-	T grammar(origGrammar.getInitialSymbol());
-
-	for( const auto & symbol : origGrammar.getNonterminalAlphabet() )
-		grammar.addNonterminalSymbol( symbol );
-
-	for( const auto & symbol : origGrammar.getTerminalAlphabet() )
-		grammar.addTerminalSymbol( symbol );
-
-	auto origRules = origGrammar.getRawRules();
-
-	for( const auto & symbol : origGrammar.getNonterminalAlphabet() ) {
-		std::set<alphabet::Symbol> simpleRulesClosure = grammar::properties::NonterminalUnitRuleCycle::getNonterminalUnitRuleCycle(origGrammar, symbol);
-		for( const auto & closureSymbol : simpleRulesClosure ) {
-			auto rules = origRules.find(closureSymbol);
-			if(rules != origRules.end()) for( const auto& rawRule : rules->second ) {
-				if(rawRule.size() == 0 || (rawRule.size() == 1 && !origGrammar.getNonterminalAlphabet().count(rawRule[0])) || rawRule.size() >= 2)
-					grammar.addRawRule(symbol, rawRule);
-			}
-		}
-	}
-
-	grammar.setGeneratesEpsilon(origGrammar.getGeneratesEpsilon());
-
-	return grammar;
-}
-
-template<class T>
-T removeNonEpsilonFree( const T & origGrammar ) {
-	T grammar(origGrammar.getInitialSymbol());
-
-	for( const auto & symbol : origGrammar.getNonterminalAlphabet() )
-		grammar.addNonterminalSymbol( symbol );
-
-	for( const auto & symbol : origGrammar.getTerminalAlphabet() )
-		grammar.addTerminalSymbol( symbol );
-
-	auto origRules = origGrammar.getRawRules();
-
-	for( const auto & symbol : origGrammar.getNonterminalAlphabet() ) {
-		std::set<alphabet::Symbol> simpleRulesClosure = grammar::properties::NonterminalUnitRuleCycle::getNonterminalUnitRuleCycle(origGrammar, symbol);
-		for( const auto & closureSymbol : simpleRulesClosure ) {
-			auto rules = origRules.find(closureSymbol);
-			if(rules != origRules.end()) for( const auto& rawRule : rules->second ) {
-				if(rawRule.size() == 0 || (rawRule.size() == 1 && !origGrammar.getNonterminalAlphabet().count(rawRule[0])) || rawRule.size() >= 2)
-					grammar.addRawRule(symbol, rawRule);
-			}
-		}
-	}
-
-	return grammar;
-}
-
-grammar::CFG < > SimpleRulesRemover::remove(const grammar::CFG < > & origGrammar) {
-	return removeNonEpsilonFree(origGrammar);
+grammar::Grammar SimpleRulesRemover::remove ( const grammar::Grammar & grammar ) {
+	return dispatch ( grammar.getData ( ) );
 }
 
 auto SimpleRulesRemoverCFG = SimpleRulesRemover::RegistratorWrapper<grammar::CFG < >, grammar::CFG < > >(SimpleRulesRemover::remove);
-
-grammar::EpsilonFreeCFG < > SimpleRulesRemover::remove(const grammar::EpsilonFreeCFG < > & origGrammar) {
-	return removeEpsilonFree(origGrammar);
-}
-
 auto SimpleRulesRemoverEpsilonFreeCFG = SimpleRulesRemover::RegistratorWrapper<grammar::EpsilonFreeCFG < >, grammar::EpsilonFreeCFG < > >(SimpleRulesRemover::remove);
-
-grammar::CNF < > SimpleRulesRemover::remove(const grammar::CNF < > & origGrammar) {
-	return origGrammar;
-}
-
 auto SimpleRulesRemoverCNF = SimpleRulesRemover::RegistratorWrapper<grammar::CNF < >, grammar::CNF < > >(SimpleRulesRemover::remove);
-
-grammar::GNF < > SimpleRulesRemover::remove(const grammar::GNF < > & origGrammar) {
-	return origGrammar;
-}
-
 auto SimpleRulesRemoverGNF = SimpleRulesRemover::RegistratorWrapper<grammar::GNF < >, grammar::GNF < > >(SimpleRulesRemover::remove);
-
-grammar::LG < > SimpleRulesRemover::remove(const grammar::LG < > & origGrammar) {
-	return removeNonEpsilonFree(origGrammar);
-}
-
 auto SimpleRulesRemoverLG = SimpleRulesRemover::RegistratorWrapper<grammar::LG < >, grammar::LG < > >(SimpleRulesRemover::remove);
-
-grammar::LeftLG < > SimpleRulesRemover::remove(const grammar::LeftLG < > & origGrammar) {
-	return removeNonEpsilonFree(origGrammar);
-}
-
 auto SimpleRulesRemoverLeftLG = SimpleRulesRemover::RegistratorWrapper<grammar::LeftLG < >, grammar::LeftLG < > >(SimpleRulesRemover::remove);
-
-grammar::LeftRG < > SimpleRulesRemover::remove(const grammar::LeftRG < > & origGrammar) {
-	return origGrammar;
-}
-
 auto SimpleRulesRemoverLeftRG = SimpleRulesRemover::RegistratorWrapper<grammar::LeftRG < >, grammar::LeftRG < > >(SimpleRulesRemover::remove);
-
-grammar::RightLG < > SimpleRulesRemover::remove(const grammar::RightLG < > & origGrammar) {
-	return removeNonEpsilonFree(origGrammar);
-}
-
 auto SimpleRulesRemoverRightLG = SimpleRulesRemover::RegistratorWrapper<grammar::RightLG < >, grammar::RightLG < > >(SimpleRulesRemover::remove);
-
-grammar::RightRG < > SimpleRulesRemover::remove(const grammar::RightRG < > & origGrammar) {
-	return origGrammar;
-}
-
 auto SimpleRulesRemoverRightRG = SimpleRulesRemover::RegistratorWrapper<grammar::RightRG < >, grammar::RightRG < > >(SimpleRulesRemover::remove);
 
-grammar::Grammar SimpleRulesRemover::remove(const grammar::Grammar& grammar) {
-	return dispatch(grammar.getData());
-}
-
 } /* namespace simplify */
 
 } /* namespace grammar */
diff --git a/alib2algo/src/grammar/simplify/SimpleRulesRemover.h b/alib2algo/src/grammar/simplify/SimpleRulesRemover.h
index 75ee9dd457fb4f93a19a1e5af18b1ef8afa170db..1f5be634ef72d8d949a07c6b2356d077c8fa351e 100644
--- a/alib2algo/src/grammar/simplify/SimpleRulesRemover.h
+++ b/alib2algo/src/grammar/simplify/SimpleRulesRemover.h
@@ -24,25 +24,141 @@
 #include <grammar/Regular/RightLG.h>
 #include <grammar/Regular/RightRG.h>
 
+#include <grammar/properties/NonterminalUnitRuleCycle.h>
+
 namespace grammar {
 
 namespace simplify {
 
 class SimpleRulesRemover : public std::SingleDispatch<SimpleRulesRemover, grammar::Grammar, const grammar::GrammarBase &> {
+	template<class T, class SymbolType = typename grammar::SymbolTypeOfGrammar < T > >
+	static T removeEpsilonFree( const T & origGrammar );
+
+	template<class T, class SymbolType = typename grammar::SymbolTypeOfGrammar < T > >
+	static T removeNonEpsilonFree( const T & origGrammar );
+
 public:
 	static grammar::Grammar remove( const grammar::Grammar & grammar );
 
-	static grammar::CFG < > remove( const grammar::CFG < > & grammar );
-	static grammar::EpsilonFreeCFG < > remove( const grammar::EpsilonFreeCFG < > & grammar );
-	static grammar::GNF < > remove( const grammar::GNF < > & grammar );
-	static grammar::CNF < > remove( const grammar::CNF < > & grammar );
-	static grammar::LG < > remove( const grammar::LG < > & grammar );
-	static grammar::LeftLG < > remove( const grammar::LeftLG < > & grammar );
-	static grammar::LeftRG < > remove( const grammar::LeftRG < > & grammar );
-	static grammar::RightLG < > remove( const grammar::RightLG < > & grammar );
-	static grammar::RightRG < > remove( const grammar::RightRG < > & grammar );
+	template < class SymbolType >
+	static grammar::CFG < SymbolType > remove( const grammar::CFG < SymbolType > & grammar );
+	template < class SymbolType >
+	static grammar::EpsilonFreeCFG < SymbolType > remove( const grammar::EpsilonFreeCFG < SymbolType > & grammar );
+	template < class SymbolType >
+	static grammar::GNF < SymbolType > remove( const grammar::GNF < SymbolType > & grammar );
+	template < class SymbolType >
+	static grammar::CNF < SymbolType > remove( const grammar::CNF < SymbolType > & grammar );
+	template < class SymbolType >
+	static grammar::LG < SymbolType > remove( const grammar::LG < SymbolType > & grammar );
+	template < class SymbolType >
+	static grammar::LeftLG < SymbolType > remove( const grammar::LeftLG < SymbolType > & grammar );
+	template < class SymbolType >
+	static grammar::LeftRG < SymbolType > remove( const grammar::LeftRG < SymbolType > & grammar );
+	template < class SymbolType >
+	static grammar::RightLG < SymbolType > remove( const grammar::RightLG < SymbolType > & grammar );
+	template < class SymbolType >
+	static grammar::RightRG < SymbolType > remove( const grammar::RightRG < SymbolType > & grammar );
 };
 
+template < class T, class SymbolType >
+T SimpleRulesRemover::removeEpsilonFree( const T & origGrammar ) {
+	T grammar(origGrammar.getInitialSymbol());
+
+	for( const auto & symbol : origGrammar.getNonterminalAlphabet() )
+		grammar.addNonterminalSymbol( symbol );
+
+	for( const auto & symbol : origGrammar.getTerminalAlphabet() )
+		grammar.addTerminalSymbol( symbol );
+
+	auto origRules = origGrammar.getRawRules();
+
+	for( const auto & symbol : origGrammar.getNonterminalAlphabet() ) {
+		std::set<SymbolType> simpleRulesClosure = grammar::properties::NonterminalUnitRuleCycle::getNonterminalUnitRuleCycle(origGrammar, symbol);
+		for( const auto & closureSymbol : simpleRulesClosure ) {
+			auto rules = origRules.find(closureSymbol);
+			if(rules != origRules.end()) for( const auto& rawRule : rules->second ) {
+				if(rawRule.size() == 0 || (rawRule.size() == 1 && !origGrammar.getNonterminalAlphabet().count(rawRule[0])) || rawRule.size() >= 2)
+					grammar.addRawRule(symbol, rawRule);
+			}
+		}
+	}
+
+	grammar.setGeneratesEpsilon(origGrammar.getGeneratesEpsilon());
+
+	return grammar;
+}
+
+template < class T, class SymbolType >
+T SimpleRulesRemover::removeNonEpsilonFree( const T & origGrammar ) {
+	T grammar(origGrammar.getInitialSymbol());
+
+	for( const auto & symbol : origGrammar.getNonterminalAlphabet() )
+		grammar.addNonterminalSymbol( symbol );
+
+	for( const auto & symbol : origGrammar.getTerminalAlphabet() )
+		grammar.addTerminalSymbol( symbol );
+
+	auto origRules = origGrammar.getRawRules();
+
+	for( const auto & symbol : origGrammar.getNonterminalAlphabet() ) {
+		std::set<SymbolType> simpleRulesClosure = grammar::properties::NonterminalUnitRuleCycle::getNonterminalUnitRuleCycle(origGrammar, symbol);
+		for( const auto & closureSymbol : simpleRulesClosure ) {
+			auto rules = origRules.find(closureSymbol);
+			if(rules != origRules.end()) for( const auto& rawRule : rules->second ) {
+				if(rawRule.size() == 0 || (rawRule.size() == 1 && !origGrammar.getNonterminalAlphabet().count(rawRule[0])) || rawRule.size() >= 2)
+					grammar.addRawRule(symbol, rawRule);
+			}
+		}
+	}
+
+	return grammar;
+}
+
+template < class SymbolType >
+grammar::CFG < SymbolType > SimpleRulesRemover::remove(const grammar::CFG < SymbolType > & origGrammar) {
+	return removeNonEpsilonFree(origGrammar);
+}
+
+template < class SymbolType >
+grammar::EpsilonFreeCFG < SymbolType > SimpleRulesRemover::remove(const grammar::EpsilonFreeCFG < SymbolType > & origGrammar) {
+	return removeEpsilonFree(origGrammar);
+}
+
+template < class SymbolType >
+grammar::CNF < SymbolType > SimpleRulesRemover::remove(const grammar::CNF < SymbolType > & origGrammar) {
+	return origGrammar;
+}
+
+template < class SymbolType >
+grammar::GNF < SymbolType > SimpleRulesRemover::remove(const grammar::GNF < SymbolType > & origGrammar) {
+	return origGrammar;
+}
+
+template < class SymbolType >
+grammar::LG < SymbolType > SimpleRulesRemover::remove(const grammar::LG < SymbolType > & origGrammar) {
+	return removeNonEpsilonFree(origGrammar);
+}
+
+template < class SymbolType >
+grammar::LeftLG < SymbolType > SimpleRulesRemover::remove(const grammar::LeftLG < SymbolType > & origGrammar) {
+	return removeNonEpsilonFree(origGrammar);
+}
+
+template < class SymbolType >
+grammar::LeftRG < SymbolType > SimpleRulesRemover::remove(const grammar::LeftRG < SymbolType > & origGrammar) {
+	return origGrammar;
+}
+
+template < class SymbolType >
+grammar::RightLG < SymbolType > SimpleRulesRemover::remove(const grammar::RightLG < SymbolType > & origGrammar) {
+	return removeNonEpsilonFree(origGrammar);
+}
+
+template < class SymbolType >
+grammar::RightRG < SymbolType > SimpleRulesRemover::remove(const grammar::RightRG < SymbolType > & origGrammar) {
+	return origGrammar;
+}
+
 } /* namespace simplify */
 
 } /* namespace grammar */
diff --git a/alib2algo/src/grammar/simplify/ToGNF.cpp b/alib2algo/src/grammar/simplify/ToGNF.cpp
index 9455f6f8be2cc856cd0486ec7d2ab20d32db6bb2..504937b475b71093c2ef957b239f3f49c7acb81b 100644
--- a/alib2algo/src/grammar/simplify/ToGNF.cpp
+++ b/alib2algo/src/grammar/simplify/ToGNF.cpp
@@ -7,138 +7,18 @@
 
 #include "ToGNF.h"
 
-#include "EpsilonRemover.h"
-#include "SimpleRulesRemover.h"
-#include "LeftRecursionRemover.h"
-#include "../convert/ToGrammarRightRG.h"
-#include "alphabet/SymbolPairSymbol.h"
-#include <common/createUnique.hpp>
-
 namespace grammar {
 
 namespace simplify {
 
-grammar::EpsilonFreeCFG < > assignNonterminals(const grammar::EpsilonFreeCFG < > & origGrammar) {
-	grammar::EpsilonFreeCFG < > res(origGrammar.getInitialSymbol());
-	res.setNonterminalAlphabet(origGrammar.getNonterminalAlphabet());
-	res.setTerminalAlphabet(origGrammar.getTerminalAlphabet());
-	res.setGeneratesEpsilon(origGrammar.getGeneratesEpsilon());
-
-	for(const std::pair<const alphabet::Symbol, std::set<std::vector<alphabet::Symbol>>>& rule : origGrammar.getRules()) {
-		for(const std::vector<alphabet::Symbol>& singleRHS : rule.second) {
-			if(res.getTerminalAlphabet().count(singleRHS[0])) { //do not substitute terminals
-				res.addRule(rule.first, singleRHS);
-				continue;
-			}
-			const alphabet::Symbol& secondLHS = singleRHS[0];
-			if(origGrammar.getRules().find(secondLHS) == origGrammar.getRules().end()) { //is there any right hand side to substitue with?
-				//if not well this rule does not generate anything anyway
-				continue;
-			}
-
-			for(const std::vector<alphabet::Symbol>& secondSingleRHS : origGrammar.getRules().find(secondLHS)->second) { // do the substitution
-				std::vector<alphabet::Symbol> newRHS(secondSingleRHS);
-				newRHS.insert(newRHS.end(), singleRHS.begin() + 1, singleRHS.end());
-				res.addRule(rule.first, newRHS);
-			}
-		}
-	}
-	return res;
-}
-
-grammar::GNF < > convertInternal( const grammar::EpsilonFreeCFG < > & origGrammar ) {
-	grammar::EpsilonFreeCFG < > step(origGrammar);
-	while(true) {
-		grammar::EpsilonFreeCFG < > nextStep = assignNonterminals(step);
-
-		if(step == nextStep) break;
-		step = std::move(nextStep);
-	}
-
-	grammar::GNF < > res(step.getInitialSymbol());
-	res.setTerminalAlphabet(step.getTerminalAlphabet());
-	res.setNonterminalAlphabet(step.getNonterminalAlphabet());
-	res.setGeneratesEpsilon(step.getGeneratesEpsilon());
-	std::map<alphabet::Symbol, alphabet::Symbol> terminalToPrimed;
-	for(const alphabet::Symbol& terminal : step.getTerminalAlphabet()) {
-		alphabet::Symbol primed = common::createUnique(terminal, res.getTerminalAlphabet(), res.getNonterminalAlphabet());
-		terminalToPrimed.insert(std::make_pair(terminal, primed));
-		res.addNonterminalSymbol(primed);
-		res.addRule(primed, std::make_pair(terminal, std::vector<alphabet::Symbol> {}));
-	}
-	for(const auto& rule : step.getRules()) {
-		for(const auto& rhs : rule.second) {
-			std::vector<alphabet::Symbol> convertedNonterminals;
-			bool first = true;
-			for(const alphabet::Symbol& rhsSymbol : rhs) {
-				if(first) {
-					first = false;
-					continue;
-				}
-
-				if(res.getNonterminalAlphabet().count(rhsSymbol))
-					convertedNonterminals.push_back(rhsSymbol);
-				else
-					convertedNonterminals.push_back(terminalToPrimed.find(rhsSymbol)->second);
-			}
-			res.addRule(rule.first, std::make_pair(rhs[0], std::move(convertedNonterminals)));
-		}
-	}
-	return res;
-}
-
-grammar::GNF < > ToGNF::convert(const grammar::CFG < > & origGrammar) {
-	return convertInternal(grammar::simplify::SimpleRulesRemover::remove(grammar::simplify::LeftRecursionRemover::remove(grammar::simplify::EpsilonRemover::remove(origGrammar))));
-}
-
 auto ToGNFCFG = ToGNF::RegistratorWrapper<grammar::GNF < >, grammar::CFG < > >(ToGNF::convert);
-
-grammar::GNF < > ToGNF::convert(const grammar::EpsilonFreeCFG < > & origGrammar) {
-	return convertInternal(grammar::simplify::SimpleRulesRemover::remove(grammar::simplify::LeftRecursionRemover::remove(origGrammar)));
-}
-
 auto ToGNFEpsilonFreeCFG = ToGNF::RegistratorWrapper<grammar::GNF < >, grammar::EpsilonFreeCFG < > >(ToGNF::convert);
-
-grammar::GNF < > ToGNF::convert(const grammar::CNF < > & origGrammar) {
-	return convertInternal(grammar::simplify::LeftRecursionRemover::remove(origGrammar));
-}
-
 auto ToGNFCNF = ToGNF::RegistratorWrapper<grammar::GNF < >, grammar::CNF < > >(ToGNF::convert);
-
-grammar::GNF < > ToGNF::convert(const grammar::GNF < > & origGrammar) {
-	return origGrammar;
-}
-
 auto ToGNFGNF = ToGNF::RegistratorWrapper<grammar::GNF < >, grammar::GNF < > >(ToGNF::convert);
-
-grammar::GNF < > ToGNF::convert(const grammar::LG < > & origGrammar) {
-	return convertInternal(grammar::simplify::SimpleRulesRemover::remove(grammar::simplify::LeftRecursionRemover::remove(grammar::simplify::EpsilonRemover::remove(origGrammar))));
-}
-
 auto ToGNFLG = ToGNF::RegistratorWrapper<grammar::GNF < >, grammar::LG < > >(ToGNF::convert);
-
-grammar::GNF < > ToGNF::convert(const grammar::LeftLG < > & origGrammar) {
-	return convertInternal(grammar::simplify::SimpleRulesRemover::remove(grammar::simplify::LeftRecursionRemover::remove(grammar::simplify::EpsilonRemover::remove(origGrammar))));
-}
-
 auto ToGNFLeftLG = ToGNF::RegistratorWrapper<grammar::GNF < >, grammar::LeftLG < > >(ToGNF::convert);
-
-grammar::RightRG < > ToGNF::convert(const grammar::LeftRG < > & origGrammar) {
-	return convert::ToGrammarRightRG::convert(origGrammar);
-}
-
 auto ToGNFLeftRG = ToGNF::RegistratorWrapper<grammar::RightRG < >, grammar::LeftRG < > >(ToGNF::convert);
-
-grammar::GNF < > ToGNF::convert(const grammar::RightLG < > & origGrammar) {
-	return convertInternal(grammar::simplify::SimpleRulesRemover::remove(grammar::simplify::LeftRecursionRemover::remove(grammar::simplify::EpsilonRemover::remove(origGrammar))));
-}
-
 auto ToGNFRightLG = ToGNF::RegistratorWrapper<grammar::GNF < >, grammar::RightLG < > >(ToGNF::convert);
-
-grammar::RightRG < > ToGNF::convert(const grammar::RightRG < > & origGrammar) {
-	return origGrammar;
-}
-
 auto ToGNFRightRG = ToGNF::RegistratorWrapper<grammar::RightRG < >, grammar::RightRG < > >(ToGNF::convert);
 
 grammar::Grammar ToGNF::convert(const grammar::Grammar& grammar) {
diff --git a/alib2algo/src/grammar/simplify/ToGNF.h b/alib2algo/src/grammar/simplify/ToGNF.h
index aaa93afa54551faa25d3f3e2927d238b0f7921cb..89433bc78c4c33c8ad717d3395706e88db2e9b12 100644
--- a/alib2algo/src/grammar/simplify/ToGNF.h
+++ b/alib2algo/src/grammar/simplify/ToGNF.h
@@ -24,25 +24,161 @@
 #include <grammar/Regular/RightLG.h>
 #include <grammar/Regular/RightRG.h>
 
+#include "EpsilonRemover.h"
+#include "SimpleRulesRemover.h"
+#include "LeftRecursionRemover.h"
+#include <grammar/convert/ToGrammarRightRG.h>
+#include <common/createUnique.hpp>
+
 namespace grammar {
 
 namespace simplify {
 
 class ToGNF : public std::SingleDispatch<ToGNF, grammar::Grammar, const grammar::GrammarBase &> {
+	template < class SymbolType >
+	static grammar::EpsilonFreeCFG < SymbolType > assignNonterminals(const grammar::EpsilonFreeCFG < SymbolType > & origGrammar);
+	template < class SymbolType >
+	static grammar::GNF < SymbolType > convertInternal( const grammar::EpsilonFreeCFG < SymbolType > & origGrammar );
+
 public:
 	static grammar::Grammar convert( const grammar::Grammar & grammar );
 
-	static grammar::GNF < > convert( const grammar::CFG < > & grammar );
-	static grammar::GNF < > convert( const grammar::EpsilonFreeCFG < > & grammar );
-	static grammar::GNF < > convert( const grammar::CNF < > & grammar );
-	static grammar::GNF < > convert( const grammar::GNF < > & grammar );
-	static grammar::GNF < > convert( const grammar::LG < > & grammar );
-	static grammar::GNF < > convert( const grammar::LeftLG < > & grammar );
-	static grammar::RightRG < > convert( const grammar::LeftRG < > & grammar );
-	static grammar::GNF < > convert( const grammar::RightLG < > & grammar );
-	static grammar::RightRG < > convert( const grammar::RightRG < > & grammar );
+	template < class SymbolType >
+	static grammar::GNF < SymbolType > convert( const grammar::CFG < SymbolType > & grammar );
+	template < class SymbolType >
+	static grammar::GNF < SymbolType > convert( const grammar::EpsilonFreeCFG < SymbolType > & grammar );
+	template < class SymbolType >
+	static grammar::GNF < SymbolType > convert( const grammar::CNF < SymbolType > & grammar );
+	template < class SymbolType >
+	static grammar::GNF < SymbolType > convert( const grammar::GNF < SymbolType > & grammar );
+	template < class SymbolType >
+	static grammar::GNF < SymbolType > convert( const grammar::LG < SymbolType > & grammar );
+	template < class SymbolType >
+	static grammar::GNF < SymbolType > convert( const grammar::LeftLG < SymbolType > & grammar );
+	template < class SymbolType >
+	static grammar::RightRG < SymbolType > convert( const grammar::LeftRG < SymbolType > & grammar );
+	template < class SymbolType >
+	static grammar::GNF < SymbolType > convert( const grammar::RightLG < SymbolType > & grammar );
+	template < class SymbolType >
+	static grammar::RightRG < SymbolType > convert( const grammar::RightRG < SymbolType > & grammar );
 };
 
+template < class SymbolType >
+grammar::EpsilonFreeCFG < SymbolType > ToGNF::assignNonterminals(const grammar::EpsilonFreeCFG < SymbolType > & origGrammar) {
+	grammar::EpsilonFreeCFG < SymbolType > res(origGrammar.getInitialSymbol());
+	res.setNonterminalAlphabet(origGrammar.getNonterminalAlphabet());
+	res.setTerminalAlphabet(origGrammar.getTerminalAlphabet());
+	res.setGeneratesEpsilon(origGrammar.getGeneratesEpsilon());
+
+	for(const std::pair<const alphabet::Symbol, std::set<std::vector<alphabet::Symbol>>>& rule : origGrammar.getRules()) {
+		for(const std::vector<alphabet::Symbol>& singleRHS : rule.second) {
+			if(res.getTerminalAlphabet().count(singleRHS[0])) { //do not substitute terminals
+				res.addRule(rule.first, singleRHS);
+				continue;
+			}
+			const alphabet::Symbol& secondLHS = singleRHS[0];
+			if(origGrammar.getRules().find(secondLHS) == origGrammar.getRules().end()) { //is there any right hand side to substitue with?
+				//if not well this rule does not generate anything anyway
+				continue;
+			}
+
+			for(const std::vector<alphabet::Symbol>& secondSingleRHS : origGrammar.getRules().find(secondLHS)->second) { // do the substitution
+				std::vector<alphabet::Symbol> newRHS(secondSingleRHS);
+				newRHS.insert(newRHS.end(), singleRHS.begin() + 1, singleRHS.end());
+				res.addRule(rule.first, newRHS);
+			}
+		}
+	}
+	return res;
+}
+
+template < class SymbolType >
+grammar::GNF < SymbolType > ToGNF::convertInternal( const grammar::EpsilonFreeCFG < SymbolType > & origGrammar ) {
+	grammar::EpsilonFreeCFG < SymbolType > step(origGrammar);
+	while(true) {
+		grammar::EpsilonFreeCFG < SymbolType > nextStep = assignNonterminals(step);
+
+		if(step == nextStep) break;
+		step = std::move(nextStep);
+	}
+
+	grammar::GNF < SymbolType > res(step.getInitialSymbol());
+	res.setTerminalAlphabet(step.getTerminalAlphabet());
+	res.setNonterminalAlphabet(step.getNonterminalAlphabet());
+	res.setGeneratesEpsilon(step.getGeneratesEpsilon());
+	std::map<alphabet::Symbol, alphabet::Symbol> terminalToPrimed;
+	for(const alphabet::Symbol& terminal : step.getTerminalAlphabet()) {
+		alphabet::Symbol primed = common::createUnique(terminal, res.getTerminalAlphabet(), res.getNonterminalAlphabet());
+		terminalToPrimed.insert(std::make_pair(terminal, primed));
+		res.addNonterminalSymbol(primed);
+		res.addRule(primed, std::make_pair(terminal, std::vector<alphabet::Symbol> {}));
+	}
+	for(const auto& rule : step.getRules()) {
+		for(const auto& rhs : rule.second) {
+			std::vector<alphabet::Symbol> convertedNonterminals;
+			bool first = true;
+			for(const alphabet::Symbol& rhsSymbol : rhs) {
+				if(first) {
+					first = false;
+					continue;
+				}
+
+				if(res.getNonterminalAlphabet().count(rhsSymbol))
+					convertedNonterminals.push_back(rhsSymbol);
+				else
+					convertedNonterminals.push_back(terminalToPrimed.find(rhsSymbol)->second);
+			}
+			res.addRule(rule.first, std::make_pair(rhs[0], std::move(convertedNonterminals)));
+		}
+	}
+	return res;
+}
+
+template < class SymbolType >
+grammar::GNF < SymbolType > ToGNF::convert(const grammar::CFG < SymbolType > & origGrammar) {
+	return convertInternal(grammar::simplify::SimpleRulesRemover::remove(grammar::simplify::LeftRecursionRemover::remove(grammar::simplify::EpsilonRemover::remove(origGrammar))));
+}
+
+template < class SymbolType >
+grammar::GNF < SymbolType > ToGNF::convert(const grammar::EpsilonFreeCFG < SymbolType > & origGrammar) {
+	return convertInternal(grammar::simplify::SimpleRulesRemover::remove(grammar::simplify::LeftRecursionRemover::remove(origGrammar)));
+}
+
+template < class SymbolType >
+grammar::GNF < SymbolType > ToGNF::convert(const grammar::CNF < SymbolType > & origGrammar) {
+	return convertInternal(grammar::simplify::LeftRecursionRemover::remove(origGrammar));
+}
+
+template < class SymbolType >
+grammar::GNF < SymbolType > ToGNF::convert(const grammar::GNF < SymbolType > & origGrammar) {
+	return origGrammar;
+}
+
+template < class SymbolType >
+grammar::GNF < SymbolType > ToGNF::convert(const grammar::LG < SymbolType > & origGrammar) {
+	return convertInternal(grammar::simplify::SimpleRulesRemover::remove(grammar::simplify::LeftRecursionRemover::remove(grammar::simplify::EpsilonRemover::remove(origGrammar))));
+}
+
+template < class SymbolType >
+grammar::GNF < SymbolType > ToGNF::convert(const grammar::LeftLG < SymbolType > & origGrammar) {
+	return convertInternal(grammar::simplify::SimpleRulesRemover::remove(grammar::simplify::LeftRecursionRemover::remove(grammar::simplify::EpsilonRemover::remove(origGrammar))));
+}
+
+template < class SymbolType >
+grammar::RightRG < SymbolType > ToGNF::convert(const grammar::LeftRG < SymbolType > & origGrammar) {
+	return convert::ToGrammarRightRG::convert(origGrammar);
+}
+
+template < class SymbolType >
+grammar::GNF < SymbolType > ToGNF::convert(const grammar::RightLG < SymbolType > & origGrammar) {
+	return convertInternal(grammar::simplify::SimpleRulesRemover::remove(grammar::simplify::LeftRecursionRemover::remove(grammar::simplify::EpsilonRemover::remove(origGrammar))));
+}
+
+template < class SymbolType >
+grammar::RightRG < SymbolType > ToGNF::convert(const grammar::RightRG < SymbolType > & origGrammar) {
+	return origGrammar;
+}
+
 } /* namespace simplify */
 
 } /* namespace grammar */
diff --git a/alib2algo/src/grammar/simplify/Trim.cpp b/alib2algo/src/grammar/simplify/Trim.cpp
index 00e8315afa00c4cee6f4131daf91163927e2d2f5..046d7fae063d6af0695462c051cb775e1723de26 100644
--- a/alib2algo/src/grammar/simplify/Trim.cpp
+++ b/alib2algo/src/grammar/simplify/Trim.cpp
@@ -7,28 +7,10 @@
 
 #include "Trim.h"
 
-#include <grammar/ContextFree/CFG.h>
-#include <grammar/ContextFree/EpsilonFreeCFG.h>
-#include <grammar/ContextFree/GNF.h>
-#include <grammar/ContextFree/CNF.h>
-#include <grammar/ContextFree/LG.h>
-#include <grammar/Regular/LeftLG.h>
-#include <grammar/Regular/LeftRG.h>
-#include <grammar/Regular/RightLG.h>
-#include <grammar/Regular/RightRG.h>
-
-#include "UnreachableSymbolsRemover.h"
-#include "UnproductiveSymbolsRemover.h"
-
 namespace grammar {
 
 namespace simplify {
 
-template<class T>
-T Trim::trim( const T & grammar ) {
-	return grammar::simplify::UnreachableSymbolsRemover::remove( grammar::simplify::UnproductiveSymbolsRemover::remove( grammar ) );
-}
-
 auto TrimCFG = Trim::RegistratorWrapper<grammar::CFG < >, grammar::CFG < > >(Trim::trim);
 auto TrimEpsilonFreeCFG = Trim::RegistratorWrapper<grammar::EpsilonFreeCFG < >, grammar::EpsilonFreeCFG < > >(Trim::trim);
 auto TrimGNF = Trim::RegistratorWrapper<grammar::GNF < >, grammar::GNF < > >(Trim::trim);
diff --git a/alib2algo/src/grammar/simplify/Trim.h b/alib2algo/src/grammar/simplify/Trim.h
index 9c7137720b1e691ee26325f95de5616946329182..1f0f8b0868c7cd2ff2dec594b069b238a87939c8 100644
--- a/alib2algo/src/grammar/simplify/Trim.h
+++ b/alib2algo/src/grammar/simplify/Trim.h
@@ -11,6 +11,19 @@
 #include <core/multipleDispatch.hpp>
 #include <grammar/Grammar.h>
 
+#include <grammar/ContextFree/CFG.h>
+#include <grammar/ContextFree/EpsilonFreeCFG.h>
+#include <grammar/ContextFree/GNF.h>
+#include <grammar/ContextFree/CNF.h>
+#include <grammar/ContextFree/LG.h>
+#include <grammar/Regular/LeftLG.h>
+#include <grammar/Regular/LeftRG.h>
+#include <grammar/Regular/RightLG.h>
+#include <grammar/Regular/RightRG.h>
+
+#include "UnreachableSymbolsRemover.h"
+#include "UnproductiveSymbolsRemover.h"
+
 namespace grammar {
 
 namespace simplify {
@@ -29,6 +42,11 @@ public:
 	static T trim( const T & grammar );
 };
 
+template<class T>
+T Trim::trim( const T & grammar ) {
+	return grammar::simplify::UnreachableSymbolsRemover::remove( grammar::simplify::UnproductiveSymbolsRemover::remove( grammar ) );
+}
+
 } /* namespace simplify */
 
 } /* namespace grammar */
diff --git a/alib2algo/src/grammar/simplify/UnproductiveSymbolsRemover.cpp b/alib2algo/src/grammar/simplify/UnproductiveSymbolsRemover.cpp
index 4e985f226a3075d12285a25cebf315eb2bb82eaf..ba8d91e10fd6f011807e06404ea3a753f29c5fd7 100644
--- a/alib2algo/src/grammar/simplify/UnproductiveSymbolsRemover.cpp
+++ b/alib2algo/src/grammar/simplify/UnproductiveSymbolsRemover.cpp
@@ -7,59 +7,10 @@
 
 #include "UnproductiveSymbolsRemover.h"
 
-#include <grammar/ContextFree/CFG.h>
-#include <grammar/ContextFree/EpsilonFreeCFG.h>
-#include <grammar/ContextFree/GNF.h>
-#include <grammar/ContextFree/CNF.h>
-#include <grammar/ContextFree/LG.h>
-#include <grammar/Regular/LeftLG.h>
-#include <grammar/Regular/LeftRG.h>
-#include <grammar/Regular/RightLG.h>
-#include <grammar/Regular/RightRG.h>
-
-#include <set>
-#include <algorithm>
-
-#include "../properties/ProductiveNonterminals.h"
-#include <exception/CommonException.h>
-
 namespace grammar {
 
 namespace simplify {
 
-template<class T>
-T UnproductiveSymbolsRemover::remove( const T & grammar ) {
-	// 1.
-	std::set<alphabet::Symbol> Nt = grammar::properties::ProductiveNonterminals::getProductiveNonterminals( grammar );
-
-	T ret(grammar.getInitialSymbol( ) );
-
-	for( const auto & symbol : Nt )
-		ret.addNonterminalSymbol( symbol );
-
-	for( const auto & symbol : grammar.getTerminalAlphabet( ) )
-		ret.addTerminalSymbol( symbol );
-
-	const std::set<alphabet::Symbol> & terminals = ret.getTerminalAlphabet( );
-	for( const auto & rule : grammar.getRawRules( ) ) {
-		if( Nt.count( rule.first ) ) {
-			for( const auto & rhs : rule.second ) {
-				if( all_of( rhs.begin( ), rhs.end( ), [ Nt, terminals ]( const alphabet::Symbol & symbol ) {
-						return Nt.count( symbol ) || terminals.count( symbol );
-				} ) )
-					ret.addRawRule( rule.first, rhs );
-			}
-		}
-	}
-
-
-	/* if( ! G1.getNonTerminalSymbols( ) . count( grammar.getInitialSymbol( ) ) )
-		throw CommonException( "Starting symbol of grammar was marked as unproductive and therefore it was removed." ); */
-
-	// 2.
-	return ret;
-}
-
 auto UnproductiveSymbolsRemoverCFG = UnproductiveSymbolsRemover::RegistratorWrapper<grammar::CFG < >, grammar::CFG < > >(UnproductiveSymbolsRemover::remove);
 auto UnproductiveSymbolsRemoverEpsilonFreeCFG = UnproductiveSymbolsRemover::RegistratorWrapper<grammar::EpsilonFreeCFG < >, grammar::EpsilonFreeCFG < > >(UnproductiveSymbolsRemover::remove);
 auto UnproductiveSymbolsRemoverGNF = UnproductiveSymbolsRemover::RegistratorWrapper<grammar::GNF < >, grammar::GNF < > >(UnproductiveSymbolsRemover::remove);
diff --git a/alib2algo/src/grammar/simplify/UnproductiveSymbolsRemover.h b/alib2algo/src/grammar/simplify/UnproductiveSymbolsRemover.h
index 04826f8d910f785198f16cceac0abf3683069f05..d35ce743925cb00153c0bfae3132eb9b3c0e979b 100644
--- a/alib2algo/src/grammar/simplify/UnproductiveSymbolsRemover.h
+++ b/alib2algo/src/grammar/simplify/UnproductiveSymbolsRemover.h
@@ -11,6 +11,22 @@
 #include <core/multipleDispatch.hpp>
 #include <grammar/Grammar.h>
 
+#include <grammar/ContextFree/CFG.h>
+#include <grammar/ContextFree/EpsilonFreeCFG.h>
+#include <grammar/ContextFree/GNF.h>
+#include <grammar/ContextFree/CNF.h>
+#include <grammar/ContextFree/LG.h>
+#include <grammar/Regular/LeftLG.h>
+#include <grammar/Regular/LeftRG.h>
+#include <grammar/Regular/RightLG.h>
+#include <grammar/Regular/RightRG.h>
+
+#include <set>
+#include <algorithm>
+
+#include <grammar/properties/ProductiveNonterminals.h>
+#include <exception/CommonException.h>
+
 namespace grammar {
 
 namespace simplify {
@@ -25,10 +41,43 @@ public:
 	/**
 	 * Removes unproductive (or useless - terminology) symbols - Melichar 3.12
 	 */
-	template<class T>
+	template < class T, class SymbolType = typename grammar::SymbolTypeOfGrammar < T > >
 	static T remove( const T & grammar );
 };
 
+template < class T, class SymbolType >
+T UnproductiveSymbolsRemover::remove( const T & grammar ) {
+	// 1.
+	std::set<SymbolType> Nt = grammar::properties::ProductiveNonterminals::getProductiveNonterminals( grammar );
+
+	T ret(grammar.getInitialSymbol( ) );
+
+	for( const auto & symbol : Nt )
+		ret.addNonterminalSymbol( symbol );
+
+	for( const auto & symbol : grammar.getTerminalAlphabet( ) )
+		ret.addTerminalSymbol( symbol );
+
+	const std::set<SymbolType> & terminals = ret.getTerminalAlphabet( );
+	for( const auto & rule : grammar.getRawRules( ) ) {
+		if( Nt.count( rule.first ) ) {
+			for( const auto & rhs : rule.second ) {
+				if( all_of( rhs.begin( ), rhs.end( ), [ Nt, terminals ]( const SymbolType & symbol ) {
+						return Nt.count( symbol ) || terminals.count( symbol );
+				} ) )
+					ret.addRawRule( rule.first, rhs );
+			}
+		}
+	}
+
+
+	/* if( ! G1.getNonTerminalSymbols( ) . count( grammar.getInitialSymbol( ) ) )
+		throw CommonException( "Starting symbol of grammar was marked as unproductive and therefore it was removed." ); */
+
+	// 2.
+	return ret;
+}
+
 } /* namespace simplify */
 
 } /* namespace grammar */
diff --git a/alib2algo/src/grammar/simplify/UnreachableSymbolsRemover.cpp b/alib2algo/src/grammar/simplify/UnreachableSymbolsRemover.cpp
index e5917b667f2807d0f094348f168088550ef4b418..860b36a43a7a74afa3aa653b81527bf812aab35b 100644
--- a/alib2algo/src/grammar/simplify/UnreachableSymbolsRemover.cpp
+++ b/alib2algo/src/grammar/simplify/UnreachableSymbolsRemover.cpp
@@ -7,58 +7,10 @@
 
 #include "UnreachableSymbolsRemover.h"
 
-#include <grammar/ContextFree/CFG.h>
-#include <grammar/ContextFree/EpsilonFreeCFG.h>
-#include <grammar/ContextFree/GNF.h>
-#include <grammar/ContextFree/CNF.h>
-#include <grammar/ContextFree/LG.h>
-#include <grammar/Regular/LeftLG.h>
-#include <grammar/Regular/LeftRG.h>
-#include <grammar/Regular/RightLG.h>
-#include <grammar/Regular/RightRG.h>
-
-#include <set>
-#include <algorithm>
-
-#include "../properties/UnreachableSymbols.h"
-
 namespace grammar {
 
 namespace simplify {
 
-template<class T>
-T UnreachableSymbolsRemover::remove( const T & grammar) {
-	// 1.
-	std::set<alphabet::Symbol> Vt = grammar::properties::UnreachableSymbols::getUnreachableSymbols( grammar );
-
-	T ret(grammar.getInitialSymbol( ) );
-
-	std::set<alphabet::Symbol> newNonTerminals, newTerminals;
-
-	set_intersection( Vt.begin( ), Vt.end( ), grammar.getNonterminalAlphabet( ).begin( ), grammar.getNonterminalAlphabet( ).end( ), std::inserter( newNonTerminals, newNonTerminals.begin( ) ) );
-	for( const auto & symbol : newNonTerminals )
-		ret.addNonterminalSymbol( symbol );
-
-	set_intersection( Vt.begin( ), Vt.end( ), grammar.getTerminalAlphabet( ).begin( ), grammar.getTerminalAlphabet( ).end( ), std::inserter( newTerminals, newTerminals.begin( ) ) );
-	for( const auto & symbol : newTerminals )
-		ret.addTerminalSymbol( symbol );
-
-	// A->\alpha: if A \in N' and \alpha in V_i*, then A->\alpha in P
-	for( const auto & rule : grammar.getRawRules( ) ) {
-		if( newNonTerminals.count( rule.first ) ) {
-			for( const auto& rhs : rule.second ) {
-				if( all_of( rhs.begin( ), rhs.end( ), [ Vt ]( alphabet::Symbol const& symb ) -> bool {
-					return Vt.count( symb );
-				} ) )
-					ret.addRawRule( rule.first, rhs );
-			}
-		}
-	}
-
-	// 2.
-	return ret;
-}
-
 auto UnreachableSymbolsRemoverCFG = UnreachableSymbolsRemover::RegistratorWrapper<grammar::CFG < >, grammar::CFG < > >(UnreachableSymbolsRemover::remove);
 auto UnreachableSymbolsRemoverEpsilonFreeCFG = UnreachableSymbolsRemover::RegistratorWrapper<grammar::EpsilonFreeCFG < >, grammar::EpsilonFreeCFG < > >(UnreachableSymbolsRemover::remove);
 auto UnreachableSymbolsRemoverGNF = UnreachableSymbolsRemover::RegistratorWrapper<grammar::GNF < >, grammar::GNF < > >(UnreachableSymbolsRemover::remove);
diff --git a/alib2algo/src/grammar/simplify/UnreachableSymbolsRemover.h b/alib2algo/src/grammar/simplify/UnreachableSymbolsRemover.h
index 603abfd9153ccd9b2a2546fbff8f64734279538c..cc94b276522883a7d14f44a2d706ea9c61c6df7b 100644
--- a/alib2algo/src/grammar/simplify/UnreachableSymbolsRemover.h
+++ b/alib2algo/src/grammar/simplify/UnreachableSymbolsRemover.h
@@ -11,6 +11,21 @@
 #include <core/multipleDispatch.hpp>
 #include <grammar/Grammar.h>
 
+#include <grammar/ContextFree/CFG.h>
+#include <grammar/ContextFree/EpsilonFreeCFG.h>
+#include <grammar/ContextFree/GNF.h>
+#include <grammar/ContextFree/CNF.h>
+#include <grammar/ContextFree/LG.h>
+#include <grammar/Regular/LeftLG.h>
+#include <grammar/Regular/LeftRG.h>
+#include <grammar/Regular/RightLG.h>
+#include <grammar/Regular/RightRG.h>
+
+#include <set>
+#include <algorithm>
+
+#include <grammar/properties/UnreachableSymbols.h>
+
 namespace grammar {
 
 namespace simplify {
@@ -25,10 +40,43 @@ public:
 	/*
 	 * Removes unreachable symbols - Melichar 3.9
 	 */
-	template<class T>
+	template < class T, class SymbolType = typename grammar::SymbolTypeOfGrammar < T > >
 	static T remove( const T & grammar );
 };
 
+template < class T, class SymbolType >
+T UnreachableSymbolsRemover::remove( const T & grammar) {
+	// 1.
+	std::set<SymbolType> Vt = grammar::properties::UnreachableSymbols::getUnreachableSymbols( grammar );
+
+	T ret(grammar.getInitialSymbol( ) );
+
+	std::set<SymbolType> newNonTerminals, newTerminals;
+
+	set_intersection( Vt.begin( ), Vt.end( ), grammar.getNonterminalAlphabet( ).begin( ), grammar.getNonterminalAlphabet( ).end( ), std::inserter( newNonTerminals, newNonTerminals.begin( ) ) );
+	for( const auto & symbol : newNonTerminals )
+		ret.addNonterminalSymbol( symbol );
+
+	set_intersection( Vt.begin( ), Vt.end( ), grammar.getTerminalAlphabet( ).begin( ), grammar.getTerminalAlphabet( ).end( ), std::inserter( newTerminals, newTerminals.begin( ) ) );
+	for( const auto & symbol : newTerminals )
+		ret.addTerminalSymbol( symbol );
+
+	// A->\alpha: if A \in N' and \alpha in V_i*, then A->\alpha in P
+	for( const auto & rule : grammar.getRawRules( ) ) {
+		if( newNonTerminals.count( rule.first ) ) {
+			for( const auto& rhs : rule.second ) {
+				if( all_of( rhs.begin( ), rhs.end( ), [ Vt ]( SymbolType const& symb ) -> bool {
+					return Vt.count( symb );
+				} ) )
+					ret.addRawRule( rule.first, rhs );
+			}
+		}
+	}
+
+	// 2.
+	return ret;
+}
+
 } /* namespace simplify */
 
 } /* namespace grammar */