diff --git a/alib2algo/src/grammar/simplify/LeftRecursionRemover.cpp b/alib2algo/src/grammar/simplify/LeftRecursionRemover.cpp
index 996f203d03bfdbc45b5dc9a9814db4a2d4e25975..3837b8ac91e454bb686d76cbade7bd40e1a0dcc8 100644
--- a/alib2algo/src/grammar/simplify/LeftRecursionRemover.cpp
+++ b/alib2algo/src/grammar/simplify/LeftRecursionRemover.cpp
@@ -121,6 +121,24 @@ grammar::EpsilonFreeCFG LeftRecursionRemover::remove(const grammar::EpsilonFreeC
 	return step;
 }
 
+grammar::EpsilonFreeCFG LeftRecursionRemover::remove(const grammar::CNF& origGrammar) {
+	EpsilonFreeCFG tmp(origGrammar.getInitialSymbol());
+	tmp.setTerminalAlphabet(origGrammar.getTerminalAlphabet());
+	tmp.setNonterminalAlphabet(origGrammar.getNonterminalAlphabet());
+	tmp.setGeneratesEpsilon(origGrammar.getGeneratesEpsilon());
+	for(const auto& rule : origGrammar.getRules()) {
+		for(const auto& rhs : rule.second) {
+			if(rhs.is<alphabet::Symbol>()) {
+				tmp.addRule(rule.first, {rhs.get<alphabet::Symbol>()});
+			} else {
+				const auto& rhsPair = rhs.get<std::pair<alphabet::Symbol, alphabet::Symbol>>();
+				tmp.addRule(rule.first, {rhsPair.first, rhsPair.second});
+			}
+		}
+	}
+	return remove(tmp);
+}
+
 grammar::GNF LeftRecursionRemover::remove(const grammar::GNF& origGrammar) {
 	return origGrammar;
 }
@@ -182,8 +200,9 @@ void LeftRecursionRemover::Visit(void* data, const grammar::EpsilonFreeCFG& gram
 	out = new Grammar(std::move(this->remove(grammar)));
 }
 
-void LeftRecursionRemover::Visit(void*, const grammar::CNF&) const {
-	throw exception::AlibException("Unsupported grammar type CNF");
+void LeftRecursionRemover::Visit(void* data, const grammar::CNF& grammar) const {
+	grammar::Grammar* & out = *((grammar::Grammar**) data);
+	out = new Grammar(std::move(this->remove(grammar)));
 }
 
 void LeftRecursionRemover::Visit(void* data, const grammar::GNF& grammar) const {
diff --git a/alib2algo/src/grammar/simplify/LeftRecursionRemover.h b/alib2algo/src/grammar/simplify/LeftRecursionRemover.h
index d6a08689c7b3085e3bb2c7b76ef586b7adcda488..f4877c9bb6a177adab8b9f358fbbce7ffb396ae8 100644
--- a/alib2algo/src/grammar/simplify/LeftRecursionRemover.h
+++ b/alib2algo/src/grammar/simplify/LeftRecursionRemover.h
@@ -33,6 +33,7 @@ public:
 	static grammar::Grammar remove( const grammar::Grammar & grammar );
 
 	static grammar::EpsilonFreeCFG remove( const grammar::EpsilonFreeCFG & grammar );
+	static grammar::EpsilonFreeCFG remove( const grammar::CNF & grammar );
 	static grammar::GNF remove( const grammar::GNF & grammar );
 	static grammar::RightRG remove( const grammar::RightRG & grammar );
 	static grammar::RightLG remove( const grammar::RightLG & grammar );
diff --git a/alib2algo/src/grammar/simplify/ToGNF.cpp b/alib2algo/src/grammar/simplify/ToGNF.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..774d7d8ab6f1c4c11bc3d1ae3302da97849f36b3
--- /dev/null
+++ b/alib2algo/src/grammar/simplify/ToGNF.cpp
@@ -0,0 +1,214 @@
+/*
+ * ToGNF.cpp
+ *
+ *  Created on: 24. 11. 2014
+ *	  Author: Jan Travnicek
+ */
+
+#include "ToGNF.h"
+
+#include "EpsilonRemover.h"
+#include "SimpleRulesRemover.h"
+#include "LeftRecursionRemover.h"
+#include "../convert/ToGrammarRightRG.h"
+#include "alphabet/LabeledSymbol.h"
+#include "alphabet/SymbolPairSymbol.h"
+
+#include <factory/StringDataFactory.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<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?
+				res.addRule(rule.first, singleRHS);
+				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 = alphabet::createUniqueSymbol(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], 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))));
+}
+
+grammar::GNF ToGNF::convert(const grammar::EpsilonFreeCFG& origGrammar)
+{
+	return convertInternal(grammar::simplify::SimpleRulesRemover::remove(grammar::simplify::LeftRecursionRemover::remove(origGrammar)));
+}
+
+grammar::GNF ToGNF::convert(const grammar::CNF& origGrammar)
+{
+	return convertInternal(grammar::simplify::LeftRecursionRemover::remove(origGrammar));
+}
+
+grammar::GNF ToGNF::convert(const grammar::GNF& origGrammar)
+{
+	return origGrammar;
+}
+
+grammar::GNF ToGNF::convert(const grammar::LG& origGrammar)
+{
+	return convertInternal(grammar::simplify::SimpleRulesRemover::remove(grammar::simplify::LeftRecursionRemover::remove(grammar::simplify::EpsilonRemover::remove(origGrammar))));
+}
+
+grammar::GNF ToGNF::convert(const grammar::LeftLG& origGrammar)
+{
+	return convertInternal(grammar::simplify::SimpleRulesRemover::remove(grammar::simplify::LeftRecursionRemover::remove(grammar::simplify::EpsilonRemover::remove(origGrammar))));
+}
+
+grammar::RightRG ToGNF::convert(const grammar::LeftRG& origGrammar)
+{
+	return convert::ToGrammarRightRG::convert(origGrammar);
+}
+
+grammar::GNF ToGNF::convert(const grammar::RightLG& origGrammar)
+{
+	return convertInternal(grammar::simplify::SimpleRulesRemover::remove(grammar::simplify::LeftRecursionRemover::remove(grammar::simplify::EpsilonRemover::remove(origGrammar))));
+}
+
+grammar::RightRG ToGNF::convert(const grammar::RightRG& origGrammar)
+{
+	return origGrammar;
+}
+
+
+
+grammar::Grammar ToGNF::convert(const grammar::Grammar& grammar) {
+	grammar::Grammar* out = NULL;
+	grammar.getData().Accept((void*) &out, ToGNF::TO_GNF);
+	grammar::Grammar res = std::move(*out);
+	delete out;
+	return res;
+}
+
+void ToGNF::Visit(void* data, const grammar::LeftLG& grammar) const {
+	grammar::Grammar* & out = *((grammar::Grammar**) data);
+	out = new Grammar(std::move(this->convert(grammar)));
+}
+
+void ToGNF::Visit(void* data, const grammar::LeftRG& grammar) const {
+	grammar::Grammar* & out = *((grammar::Grammar**) data);
+	out = new Grammar(std::move(this->convert(grammar)));
+}
+
+void ToGNF::Visit(void* data, const grammar::RightLG& grammar) const {
+	grammar::Grammar* & out = *((grammar::Grammar**) data);
+	out = new Grammar(std::move(this->convert(grammar)));
+}
+
+void ToGNF::Visit(void* data, const grammar::RightRG& grammar) const {
+	grammar::Grammar* & out = *((grammar::Grammar**) data);
+	out = new Grammar(std::move(this->convert(grammar)));
+}
+
+void ToGNF::Visit(void* data, const grammar::LG& grammar) const {
+	grammar::Grammar* & out = *((grammar::Grammar**) data);
+	out = new Grammar(std::move(this->convert(grammar)));
+}
+
+void ToGNF::Visit(void* data, const grammar::CFG& grammar) const {
+	grammar::Grammar* & out = *((grammar::Grammar**) data);
+	out = new Grammar(std::move(this->convert(grammar)));
+}
+
+void ToGNF::Visit(void* data, const grammar::EpsilonFreeCFG& grammar) const {
+	grammar::Grammar* & out = *((grammar::Grammar**) data);
+	out = new Grammar(std::move(this->convert(grammar)));
+}
+
+void ToGNF::Visit(void* data, const grammar::CNF& grammar) const {
+	grammar::Grammar* & out = *((grammar::Grammar**) data);
+	out = new Grammar(std::move(this->convert(grammar)));
+}
+
+void ToGNF::Visit(void* data, const grammar::GNF& grammar) const {
+	grammar::Grammar* & out = *((grammar::Grammar**) data);
+	out = new Grammar(std::move(this->convert(grammar)));
+}
+
+void ToGNF::Visit(void*, const grammar::CSG&) const {
+	throw exception::AlibException("Unsupported grammar type CSG");
+}
+
+void ToGNF::Visit(void*, const grammar::NonContractingGrammar&) const {
+	throw exception::AlibException("Unsupported grammar type NonConctractingGrammar");
+}
+
+void ToGNF::Visit(void*, const grammar::ContextPreservingUnrestrictedGrammar&) const {
+	throw exception::AlibException("Unsupported grammar type ContextPreservingUnrestrictedGrammar");
+}
+
+void ToGNF::Visit(void*, const grammar::UnrestrictedGrammar&) const {
+	throw exception::AlibException("Unsupported grammar type UnrestrictedGrammar");
+}
+
+const ToGNF ToGNF::TO_GNF;
+
+} /* namespace simplify */
+
+} /* namespace grammar */
diff --git a/alib2algo/src/grammar/simplify/ToGNF.h b/alib2algo/src/grammar/simplify/ToGNF.h
new file mode 100644
index 0000000000000000000000000000000000000000..87d9f30a2015df7972701e51591c3a01dbd8e2c8
--- /dev/null
+++ b/alib2algo/src/grammar/simplify/ToGNF.h
@@ -0,0 +1,67 @@
+/*
+ * ToGNF.h
+ *
+ *  Created on: 24. 11. 2014
+ *	  Author: Jan Travnicek
+ */
+
+#ifndef TO_GNF_H_
+#define TO_GNF_H_
+
+#include <map>
+#include <algorithm>
+
+#include <grammar/Grammar.h>
+
+#include <grammar/ContextFree/CFG.h>
+#include <grammar/ContextFree/EpsilonFreeCFG.h>
+#include <grammar/ContextFree/GNF.h>
+#include <grammar/ContextFree/GNF.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 <exception/AlibException.h>
+
+namespace grammar {
+
+namespace simplify {
+
+class ToGNF : public grammar::VisitableGrammarBase::const_visitor_type {
+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 );
+
+private:
+	void Visit(void*, const grammar::LeftLG& grammar) const;
+	void Visit(void*, const grammar::LeftRG& grammar) const;
+	void Visit(void*, const grammar::RightLG& grammar) const;
+	void Visit(void*, const grammar::RightRG& grammar) const;
+	void Visit(void*, const grammar::LG& grammar) const;
+	void Visit(void*, const grammar::CFG& grammar) const;
+	void Visit(void*, const grammar::EpsilonFreeCFG& grammar) const;
+	void Visit(void*, const grammar::CNF& grammar) const;
+	void Visit(void*, const grammar::GNF& grammar) const;
+	void Visit(void*, const grammar::CSG& grammar) const;
+	void Visit(void*, const grammar::NonContractingGrammar& grammar) const;
+	void Visit(void*, const grammar::ContextPreservingUnrestrictedGrammar& grammar) const;
+	void Visit(void*, const grammar::UnrestrictedGrammar& grammar) const;
+
+	static const ToGNF TO_GNF;
+};
+
+} /* namespace simplify */
+
+} /* namespace grammar */
+
+#endif /* TO_GNF_H_ */
diff --git a/alib2algo/test-src/grammar/simplify/GrammarToGNFTest.cpp b/alib2algo/test-src/grammar/simplify/GrammarToGNFTest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a7f68578965ebfbe0a3a6c97ce943d10458eb2a6
--- /dev/null
+++ b/alib2algo/test-src/grammar/simplify/GrammarToGNFTest.cpp
@@ -0,0 +1,173 @@
+#include "GrammarToGNFTest.h"
+
+#include "grammar/simplify/ToGNF.h"
+#include "grammar/generate/GenerateUpToLength.h"
+
+#include "grammar/ContextFree/GNF.h"
+#include "grammar/ContextFree/EpsilonFreeCFG.h"
+
+#include <factory/StringDataFactory.hpp>
+
+#define CPPUNIT_IMPLY(x, y) CPPUNIT_ASSERT(!(x) || (y))
+
+CPPUNIT_TEST_SUITE_REGISTRATION( GrammarToGNFTest );
+
+void GrammarToGNFTest::setUp() {
+}
+
+void GrammarToGNFTest::tearDown() {
+}
+
+void GrammarToGNFTest::testRemoveToGNFRules1() {
+	alphabet::Symbol S = alphabet::symbolFrom("S");
+	alphabet::Symbol A = alphabet::symbolFrom("A");
+	alphabet::Symbol B = alphabet::symbolFrom("B");
+	alphabet::Symbol C = alphabet::symbolFrom("C");
+	alphabet::Symbol D = alphabet::symbolFrom("D");
+
+	alphabet::Symbol a = alphabet::symbolFrom("a");
+	alphabet::Symbol b = alphabet::symbolFrom("b");
+
+	grammar::EpsilonFreeCFG grammar1(S);
+	grammar1.setNonterminalAlphabet({S, A, B, C, D});
+	grammar1.setTerminalAlphabet({a, b});
+
+	alphabet::Symbol aprimed = createUniqueSymbol(a, grammar1.getTerminalAlphabet(), grammar1.getNonterminalAlphabet());
+	alphabet::Symbol bprimed = createUniqueSymbol(b, grammar1.getTerminalAlphabet(), grammar1.getNonterminalAlphabet());
+
+	grammar::GNF grammar2 = grammar::simplify::ToGNF::convert(grammar1);
+
+	grammar::GNF grammar3(S);
+	grammar3.setNonterminalAlphabet({S, A, B, C, D, aprimed, bprimed});
+	grammar3.setTerminalAlphabet({a, b});
+	grammar3.addRule(aprimed, std::make_pair(a, std::vector<alphabet::Symbol>{}));
+	grammar3.addRule(bprimed, std::make_pair(b, std::vector<alphabet::Symbol>{}));
+
+	std::cout << alib::StringDataFactory::toString<grammar::Grammar>(grammar::Grammar(grammar2)) << std::endl;
+	std::cout << alib::StringDataFactory::toString<grammar::Grammar>(grammar::Grammar(grammar3)) << std::endl;
+
+	CPPUNIT_ASSERT(grammar2 == grammar3);
+}
+
+void GrammarToGNFTest::testRemoveToGNFRules2() {
+	alphabet::Symbol S = alphabet::symbolFrom("S");
+	alphabet::Symbol A = alphabet::symbolFrom("A");
+	alphabet::Symbol B = alphabet::symbolFrom("B");
+	alphabet::Symbol C = alphabet::symbolFrom("C");
+	alphabet::Symbol D = alphabet::symbolFrom("D");
+
+	alphabet::Symbol a = alphabet::symbolFrom("a");
+	alphabet::Symbol b = alphabet::symbolFrom("b");
+	alphabet::Symbol c = alphabet::symbolFrom("c");
+
+	grammar::EpsilonFreeCFG grammar1(S);
+	grammar1.setNonterminalAlphabet({S, A, B, C, D});
+	grammar1.setTerminalAlphabet({a, b, c});
+	grammar1.addRule(S, {A});
+	grammar1.addRule(A, {A, a});
+	grammar1.addRule(A, {A, b});
+	grammar1.addRule(A, {c});
+
+	alphabet::Symbol Aprimed = createUniqueSymbol(A, grammar1.getTerminalAlphabet(), grammar1.getNonterminalAlphabet());
+	alphabet::Symbol aprimed = createUniqueSymbol(a, grammar1.getTerminalAlphabet(), grammar1.getNonterminalAlphabet());
+	alphabet::Symbol bprimed = createUniqueSymbol(b, grammar1.getTerminalAlphabet(), grammar1.getNonterminalAlphabet());
+	alphabet::Symbol cprimed = createUniqueSymbol(c, grammar1.getTerminalAlphabet(), grammar1.getNonterminalAlphabet());
+
+	std::cout << alib::StringDataFactory::toString<grammar::Grammar>(grammar::Grammar(grammar1)) << std::endl;
+
+	grammar::GNF grammar2 = grammar::simplify::ToGNF::convert(grammar1);
+
+	grammar::GNF grammar3(S);
+	grammar3.setNonterminalAlphabet({S, A, Aprimed, B, C, D, aprimed, bprimed, cprimed});
+	grammar3.setTerminalAlphabet({a, b, c});
+	grammar3.addRule(S, std::make_pair(c, std::vector<alphabet::Symbol>{Aprimed}));
+	grammar3.addRule(S, std::make_pair(c, std::vector<alphabet::Symbol>{}));
+	grammar3.addRule(A, std::make_pair(c, std::vector<alphabet::Symbol>{Aprimed}));
+	grammar3.addRule(A, std::make_pair(c, std::vector<alphabet::Symbol>{}));
+	grammar3.addRule(Aprimed, std::make_pair(a, std::vector<alphabet::Symbol>{Aprimed}));
+	grammar3.addRule(Aprimed, std::make_pair(a, std::vector<alphabet::Symbol>{}));
+	grammar3.addRule(Aprimed, std::make_pair(b, std::vector<alphabet::Symbol>{Aprimed}));
+	grammar3.addRule(Aprimed, std::make_pair(b, std::vector<alphabet::Symbol>{}));
+	grammar3.addRule(aprimed, std::make_pair(a, std::vector<alphabet::Symbol>{}));
+	grammar3.addRule(bprimed, std::make_pair(b, std::vector<alphabet::Symbol>{}));
+	grammar3.addRule(cprimed, std::make_pair(c, std::vector<alphabet::Symbol>{}));
+
+	std::cout << alib::StringDataFactory::toString<grammar::Grammar>(grammar::Grammar(grammar2)) << std::endl;
+	std::cout << alib::StringDataFactory::toString<grammar::Grammar>(grammar::Grammar(grammar3)) << std::endl;
+
+	CPPUNIT_ASSERT(grammar2 == grammar3);
+}
+
+void GrammarToGNFTest::testRemoveToGNFRules3() {
+	alphabet::Symbol S = alphabet::symbolFrom("S");
+	alphabet::Symbol A = alphabet::symbolFrom("A");
+	alphabet::Symbol B = alphabet::symbolFrom("B");
+	alphabet::Symbol C = alphabet::symbolFrom("C");
+
+	alphabet::Symbol a = alphabet::symbolFrom("a");
+	alphabet::Symbol b = alphabet::symbolFrom("b");
+	alphabet::Symbol c = alphabet::symbolFrom("c");
+
+	grammar::EpsilonFreeCFG grammar1(S);
+	grammar1.setNonterminalAlphabet({S, A, B, C});
+	grammar1.setTerminalAlphabet({a, b, c});
+	grammar1.addRule(S, {A});
+	grammar1.addRule(A, {B, a});
+	grammar1.addRule(B, {A, b});
+	grammar1.addRule(A, {c});
+
+	alphabet::Symbol Bprimed = createUniqueSymbol(B, grammar1.getTerminalAlphabet(), grammar1.getNonterminalAlphabet());
+	alphabet::Symbol aprimed = createUniqueSymbol(a, grammar1.getTerminalAlphabet(), grammar1.getNonterminalAlphabet());
+	alphabet::Symbol bprimed = createUniqueSymbol(b, grammar1.getTerminalAlphabet(), grammar1.getNonterminalAlphabet());
+	alphabet::Symbol cprimed = createUniqueSymbol(c, grammar1.getTerminalAlphabet(), grammar1.getNonterminalAlphabet());
+
+	std::cout << alib::StringDataFactory::toString<grammar::Grammar>(grammar::Grammar(grammar1)) << std::endl;
+
+	grammar::GNF grammar2 = grammar::simplify::ToGNF::convert(grammar1);
+
+	grammar::GNF grammar3(S);
+	grammar3.setNonterminalAlphabet({S, A, B, Bprimed, C, aprimed, bprimed, cprimed});
+	grammar3.setTerminalAlphabet({a, b, c});
+	grammar3.addRule(S, std::make_pair(c, std::vector<alphabet::Symbol>{}));
+	grammar3.addRule(S, std::make_pair(c, std::vector<alphabet::Symbol>{bprimed, Bprimed, aprimed}));
+	grammar3.addRule(S, std::make_pair(c, std::vector<alphabet::Symbol>{bprimed, aprimed}));
+	grammar3.addRule(A, std::make_pair(c, std::vector<alphabet::Symbol>{bprimed, aprimed}));
+	grammar3.addRule(A, std::make_pair(c, std::vector<alphabet::Symbol>{bprimed, Bprimed, aprimed}));
+	grammar3.addRule(A, std::make_pair(c, std::vector<alphabet::Symbol>{}));
+	grammar3.addRule(B, std::make_pair(c, std::vector<alphabet::Symbol>{bprimed}));
+	grammar3.addRule(B, std::make_pair(c, std::vector<alphabet::Symbol>{bprimed, Bprimed}));
+	grammar3.addRule(Bprimed, std::make_pair(a, std::vector<alphabet::Symbol>{bprimed, Bprimed}));
+	grammar3.addRule(Bprimed, std::make_pair(a, std::vector<alphabet::Symbol>{bprimed}));
+	grammar3.addRule(aprimed, std::make_pair(a, std::vector<alphabet::Symbol>{}));
+	grammar3.addRule(bprimed, std::make_pair(b, std::vector<alphabet::Symbol>{}));
+	grammar3.addRule(cprimed, std::make_pair(c, std::vector<alphabet::Symbol>{}));
+
+	std::cout << alib::StringDataFactory::toString<grammar::Grammar>(grammar::Grammar(grammar2)) << std::endl;
+	std::cout << alib::StringDataFactory::toString<grammar::Grammar>(grammar::Grammar(grammar3)) << std::endl;
+
+	CPPUNIT_ASSERT(grammar2 == grammar3);
+}
+
+void GrammarToGNFTest::testRemoveToGNFRules4() {
+	alphabet::Symbol A = alphabet::symbolFrom("A");
+	alphabet::Symbol B = alphabet::symbolFrom("B");
+	alphabet::Symbol C = alphabet::symbolFrom("C");
+
+	alphabet::Symbol a = alphabet::symbolFrom("a");
+	alphabet::Symbol b = alphabet::symbolFrom("b");
+
+	grammar::EpsilonFreeCFG grammar1(A);
+	grammar1.setNonterminalAlphabet({A, B, C});
+	grammar1.setTerminalAlphabet({a, b});
+	grammar1.addRule(A, {B, C});
+	grammar1.addRule(A, {a});
+	grammar1.addRule(B, {C, A});
+	grammar1.addRule(B, {A, b});
+	grammar1.addRule(C, {A, B});
+	grammar1.addRule(C, {C, C});
+	grammar1.addRule(C, {a});
+
+	grammar::GNF grammar2 = grammar::simplify::ToGNF::convert(grammar1);
+
+	CPPUNIT_ASSERT(grammar::generate::GenerateUpToLength::generate(grammar1, 7) == grammar::generate::GenerateUpToLength::generate(grammar2, 7));
+}
diff --git a/alib2algo/test-src/grammar/simplify/GrammarToGNFTest.h b/alib2algo/test-src/grammar/simplify/GrammarToGNFTest.h
new file mode 100644
index 0000000000000000000000000000000000000000..d47c6f65374c3c0e0d5c7dadb6c3d7efd3952f14
--- /dev/null
+++ b/alib2algo/test-src/grammar/simplify/GrammarToGNFTest.h
@@ -0,0 +1,25 @@
+#ifndef GRAMMAR_TO_GNF_TEST_H_
+#define GRAMMAR_TO_GNF_TEST_H_
+
+#include <cppunit/extensions/HelperMacros.h>
+
+class GrammarToGNFTest : public CppUnit::TestFixture
+{
+  CPPUNIT_TEST_SUITE( GrammarToGNFTest );
+  CPPUNIT_TEST( testRemoveToGNFRules1 );
+  CPPUNIT_TEST( testRemoveToGNFRules2 );
+  CPPUNIT_TEST( testRemoveToGNFRules3 );
+  CPPUNIT_TEST( testRemoveToGNFRules4 );
+  CPPUNIT_TEST_SUITE_END();
+
+public:
+  void setUp();
+  void tearDown();
+
+  void testRemoveToGNFRules1();
+  void testRemoveToGNFRules2();
+  void testRemoveToGNFRules3();
+  void testRemoveToGNFRules4();
+};
+
+#endif /* GRAMMAR_TO_GNF_TEST_H_ */