From 037d21e24199cdee5816919e959561e9968e080a Mon Sep 17 00:00:00 2001
From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz>
Date: Fri, 2 Dec 2016 15:56:45 +0100
Subject: [PATCH] template EpsilonRemover algorithm

---
 .../src/grammar/simplify/EpsilonRemover.cpp   |  85 -------------
 .../src/grammar/simplify/EpsilonRemover.h     | 119 ++++++++++++++++--
 2 files changed, 110 insertions(+), 94 deletions(-)

diff --git a/alib2algo/src/grammar/simplify/EpsilonRemover.cpp b/alib2algo/src/grammar/simplify/EpsilonRemover.cpp
index 6da9995533..76abf3b1ba 100644
--- a/alib2algo/src/grammar/simplify/EpsilonRemover.cpp
+++ b/alib2algo/src/grammar/simplify/EpsilonRemover.cpp
@@ -7,103 +7,18 @@
 
 #include "EpsilonRemover.h"
 
-#include "../properties/NullableNonterminals.h"
-
 namespace grammar {
 
 namespace simplify {
 
-void removeNullableNonterminals(grammar::EpsilonFreeCFG < > & grammar, const std::set<alphabet::Symbol>& nullableNonterminals, const alphabet::Symbol& lhs, const std::vector<alphabet::Symbol>& rhs, unsigned i, std::vector<alphabet::Symbol> clear) {
-	if(rhs.size() == i) {
-		if(clear.size() == 0) return;
-		grammar.addRule(lhs, clear);
-	} else if(nullableNonterminals.find(rhs[i]) != nullableNonterminals.end()) {
-		removeNullableNonterminals(grammar, nullableNonterminals, lhs, rhs, i+1, clear);
-		clear.push_back(rhs[i]);
-		removeNullableNonterminals(grammar, nullableNonterminals, lhs, rhs, i+1, clear);
-	} else {
-		clear.push_back(rhs[i]);
-		removeNullableNonterminals(grammar, nullableNonterminals, lhs, rhs, i+1, clear);
-	}
-}
-
-template<class T>
-grammar::EpsilonFreeCFG < > removeInternal( const T & origGrammar ) {
-	grammar::EpsilonFreeCFG < > grammar(origGrammar.getInitialSymbol());
-
-	for( const auto & symbol : origGrammar.getNonterminalAlphabet() )
-		grammar.addNonterminalSymbol( symbol );
-
-	for( const auto & symbol : origGrammar.getTerminalAlphabet() )
-		grammar.addTerminalSymbol( symbol );
-
-	std::set<alphabet::Symbol> nullableNonterminals = grammar::properties::NullableNonterminals::getNullableNonterminals(origGrammar);
-
-	for( const auto & rule : origGrammar.getRawRules( ) )
-		for(const auto & rhs : rule.second) {
-			if(rhs.size() == 0) continue;
-
-			removeNullableNonterminals(grammar, nullableNonterminals, rule.first, rhs, 0, {});
-		}
-
-	if(nullableNonterminals.find(origGrammar.getInitialSymbol()) != nullableNonterminals.end())
-		grammar.setGeneratesEpsilon(true);
-
-	return grammar;
-}
-
-grammar::EpsilonFreeCFG < > EpsilonRemover::remove(const grammar::CFG < > & origGrammar) {
-	return removeInternal(origGrammar);
-}
-
 auto EpsilonRemoverCFG = EpsilonRemover::RegistratorWrapper<grammar::EpsilonFreeCFG < >, grammar::CFG < > >(EpsilonRemover::remove);
-
-grammar::EpsilonFreeCFG < > EpsilonRemover::remove(const grammar::EpsilonFreeCFG < > & origGrammar) {
-	return origGrammar;
-}
-
 auto EpsilonRemoverEpsilonFreeCFG = EpsilonRemover::RegistratorWrapper<grammar::EpsilonFreeCFG < >, grammar::EpsilonFreeCFG < > >(EpsilonRemover::remove);
-
-grammar::CNF < > EpsilonRemover::remove(const grammar::CNF < > & origGrammar) {
-	return origGrammar;
-}
-
 auto EpsilonRemoverCNF = EpsilonRemover::RegistratorWrapper<grammar::CNF < >, grammar::CNF < > >(EpsilonRemover::remove);
-
-grammar::GNF < > EpsilonRemover::remove(const grammar::GNF < > & origGrammar) {
-	return origGrammar;
-}
-
 auto EpsilonRemoverGNF = EpsilonRemover::RegistratorWrapper<grammar::GNF < >, grammar::GNF < > >(EpsilonRemover::remove);
-
-grammar::EpsilonFreeCFG < > EpsilonRemover::remove(const grammar::LG < > & origGrammar) {
-	return removeInternal(origGrammar);
-}
-
 auto EpsilonRemoverLG = EpsilonRemover::RegistratorWrapper<grammar::EpsilonFreeCFG < >, grammar::LG < > >(EpsilonRemover::remove);
-
-grammar::EpsilonFreeCFG < > EpsilonRemover::remove(const grammar::LeftLG < > & origGrammar) {
-	return removeInternal(origGrammar);
-}
-
 auto EpsilonRemoverLeftLG = EpsilonRemover::RegistratorWrapper<grammar::EpsilonFreeCFG < >, grammar::LeftLG < > >(EpsilonRemover::remove);
-
-grammar::LeftRG < > EpsilonRemover::remove(const grammar::LeftRG < > & origGrammar) {
-	return origGrammar;
-}
-
 auto EpsilonRemoverLeftRG = EpsilonRemover::RegistratorWrapper<grammar::LeftRG < >, grammar::LeftRG < > >(EpsilonRemover::remove);
-
-grammar::EpsilonFreeCFG < > EpsilonRemover::remove(const grammar::RightLG < > & origGrammar) {
-	return removeInternal(origGrammar);
-}
-
 auto EpsilonRemoverRightLG = EpsilonRemover::RegistratorWrapper<grammar::EpsilonFreeCFG < >, grammar::RightLG < > >(EpsilonRemover::remove);
-
-grammar::RightRG < > EpsilonRemover::remove(const grammar::RightRG < > & origGrammar) {
-	return origGrammar;
-}
-
 auto EpsilonRemoverRightRG = EpsilonRemover::RegistratorWrapper<grammar::RightRG < >, grammar::RightRG < > >(EpsilonRemover::remove);
 
 grammar::Grammar EpsilonRemover::remove(const grammar::Grammar& grammar) {
diff --git a/alib2algo/src/grammar/simplify/EpsilonRemover.h b/alib2algo/src/grammar/simplify/EpsilonRemover.h
index 0dd6dfe6a4..0bdb818dcf 100644
--- a/alib2algo/src/grammar/simplify/EpsilonRemover.h
+++ b/alib2algo/src/grammar/simplify/EpsilonRemover.h
@@ -24,25 +24,126 @@
 #include <grammar/Regular/RightLG.h>
 #include <grammar/Regular/RightRG.h>
 
+#include "../properties/NullableNonterminals.h"
+
 namespace grammar {
 
 namespace simplify {
 
 class EpsilonRemover : public std::SingleDispatch<EpsilonRemover, grammar::Grammar, const grammar::GrammarBase &> {
+	template < class SymbolType >
+	static void removeNullableNonterminals(grammar::EpsilonFreeCFG < SymbolType > & grammar, const std::set<SymbolType>& nullableNonterminals, const SymbolType& lhs, const std::vector<SymbolType>& rhs, unsigned i, std::vector<SymbolType> clear);
+
+	template<class T, class SymbolType = typename grammar::SymbolTypeOfGrammar < T > >
+	static grammar::EpsilonFreeCFG < SymbolType > removeInternal( const T & origGrammar );
 public:
 	static grammar::Grammar remove( const grammar::Grammar & grammar );
 
-	static grammar::EpsilonFreeCFG < > 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::EpsilonFreeCFG < > remove( const grammar::LG < > & grammar );
-	static grammar::EpsilonFreeCFG < > remove( const grammar::LeftLG < > & grammar );
-	static grammar::LeftRG < > remove( const grammar::LeftRG < > & grammar );
-	static grammar::EpsilonFreeCFG < > remove( const grammar::RightLG < > & grammar );
-	static grammar::RightRG < > remove( const grammar::RightRG < > & grammar );
+	template < class SymbolType >
+	static grammar::EpsilonFreeCFG < 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::EpsilonFreeCFG < SymbolType > remove( const grammar::LG < SymbolType > & grammar );
+	template < class SymbolType >
+	static grammar::EpsilonFreeCFG < 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::EpsilonFreeCFG < SymbolType > remove( const grammar::RightLG < SymbolType > & grammar );
+	template < class SymbolType >
+	static grammar::RightRG < SymbolType > remove( const grammar::RightRG < SymbolType > & grammar );
 };
 
+template < class SymbolType >
+void EpsilonRemover::removeNullableNonterminals(grammar::EpsilonFreeCFG < SymbolType > & grammar, const std::set<SymbolType>& nullableNonterminals, const SymbolType& lhs, const std::vector<SymbolType>& rhs, unsigned i, std::vector<SymbolType> clear) {
+	if(rhs.size() == i) {
+		if(clear.size() == 0) return;
+		grammar.addRule(lhs, clear);
+	} else if(nullableNonterminals.find(rhs[i]) != nullableNonterminals.end()) {
+		removeNullableNonterminals(grammar, nullableNonterminals, lhs, rhs, i+1, clear);
+		clear.push_back(rhs[i]);
+		removeNullableNonterminals(grammar, nullableNonterminals, lhs, rhs, i+1, clear);
+	} else {
+		clear.push_back(rhs[i]);
+		removeNullableNonterminals(grammar, nullableNonterminals, lhs, rhs, i+1, clear);
+	}
+}
+
+template<class T, class SymbolType >
+grammar::EpsilonFreeCFG < SymbolType > EpsilonRemover::removeInternal( const T & origGrammar ) {
+	grammar::EpsilonFreeCFG < SymbolType > grammar(origGrammar.getInitialSymbol());
+
+	for( const auto & symbol : origGrammar.getNonterminalAlphabet() )
+		grammar.addNonterminalSymbol( symbol );
+
+	for( const auto & symbol : origGrammar.getTerminalAlphabet() )
+		grammar.addTerminalSymbol( symbol );
+
+	std::set<SymbolType> nullableNonterminals = grammar::properties::NullableNonterminals::getNullableNonterminals(origGrammar);
+
+	for( const auto & rule : origGrammar.getRawRules( ) )
+		for(const auto & rhs : rule.second) {
+			if(rhs.size() == 0) continue;
+
+			EpsilonRemover::removeNullableNonterminals(grammar, nullableNonterminals, rule.first, rhs, 0, {});
+		}
+
+	if(nullableNonterminals.find(origGrammar.getInitialSymbol()) != nullableNonterminals.end())
+		grammar.setGeneratesEpsilon(true);
+
+	return grammar;
+}
+
+template < class SymbolType >
+grammar::EpsilonFreeCFG < SymbolType > EpsilonRemover::remove(const grammar::CFG < SymbolType > & origGrammar) {
+	return EpsilonRemover::removeInternal(origGrammar);
+}
+
+template < class SymbolType >
+grammar::EpsilonFreeCFG < SymbolType > EpsilonRemover::remove(const grammar::EpsilonFreeCFG < SymbolType > & origGrammar) {
+	return origGrammar;
+}
+
+template < class SymbolType >
+grammar::CNF < SymbolType > EpsilonRemover::remove(const grammar::CNF < SymbolType > & origGrammar) {
+	return origGrammar;
+}
+
+template < class SymbolType >
+grammar::GNF < SymbolType > EpsilonRemover::remove(const grammar::GNF < SymbolType > & origGrammar) {
+	return origGrammar;
+}
+
+template < class SymbolType >
+grammar::EpsilonFreeCFG < SymbolType > EpsilonRemover::remove(const grammar::LG < SymbolType > & origGrammar) {
+	return EpsilonRemover::removeInternal(origGrammar);
+}
+
+template < class SymbolType >
+grammar::EpsilonFreeCFG < SymbolType > EpsilonRemover::remove(const grammar::LeftLG < SymbolType > & origGrammar) {
+	return EpsilonRemover::removeInternal(origGrammar);
+}
+
+template < class SymbolType >
+grammar::LeftRG < SymbolType > EpsilonRemover::remove(const grammar::LeftRG < SymbolType > & origGrammar) {
+	return origGrammar;
+}
+
+template < class SymbolType >
+grammar::EpsilonFreeCFG < SymbolType > EpsilonRemover::remove(const grammar::RightLG < SymbolType > & origGrammar) {
+	return EpsilonRemover::removeInternal(origGrammar);
+}
+
+template < class SymbolType >
+grammar::RightRG < SymbolType > EpsilonRemover::remove(const grammar::RightRG < SymbolType > & origGrammar) {
+	return origGrammar;
+}
+
 } /* namespace simplify */
 
 } /* namespace grammar */
-- 
GitLab