From 14dfa8524519c54c945b0c1aa29810c49160e0b8 Mon Sep 17 00:00:00 2001
From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz>
Date: Tue, 11 Sep 2018 22:04:39 +0200
Subject: [PATCH] partial template to CNF algorithm

---
 alib2algo/src/grammar/simplify/ToCNF.cpp | 13 ----
 alib2algo/src/grammar/simplify/ToCNF.h   | 82 +++++++++++++++++++++++-
 2 files changed, 79 insertions(+), 16 deletions(-)

diff --git a/alib2algo/src/grammar/simplify/ToCNF.cpp b/alib2algo/src/grammar/simplify/ToCNF.cpp
index 3b5fc083ac..4c658b89f0 100644
--- a/alib2algo/src/grammar/simplify/ToCNF.cpp
+++ b/alib2algo/src/grammar/simplify/ToCNF.cpp
@@ -11,7 +11,6 @@
 #include "SimpleRulesRemover.h"
 #include <common/DefaultSymbolsPairType.h>
 #include <exception/CommonException.h>
-#include <common/createUnique.hpp>
 #include <registration/AlgoRegistration.hpp>
 
 #include <grammar/RawRules.h>
@@ -128,10 +127,6 @@ grammar::CNF < > ToCNF::convert(const grammar::EpsilonFreeCFG < > & origGrammar)
 	return convertInternal(grammar::simplify::SimpleRulesRemover::remove(origGrammar));
 }
 
-grammar::CNF < > ToCNF::convert(const grammar::CNF < > & origGrammar) {
-	return origGrammar;
-}
-
 grammar::CNF < > ToCNF::convert(const grammar::GNF < > & origGrammar) {
 	return convertInternal(origGrammar);
 }
@@ -144,18 +139,10 @@ grammar::CNF < > ToCNF::convert(const grammar::LeftLG< > & origGrammar) {
 	return convertInternal(grammar::simplify::SimpleRulesRemover::remove(grammar::simplify::EpsilonRemover::remove(origGrammar)));
 }
 
-grammar::CNF < > ToCNF::convert(const grammar::LeftRG < > & origGrammar) {
-	return convertInternal(origGrammar);
-}
-
 grammar::CNF < > ToCNF::convert(const grammar::RightLG < > & origGrammar) {
 	return convertInternal(grammar::simplify::SimpleRulesRemover::remove(grammar::simplify::EpsilonRemover::remove(origGrammar)));
 }
 
-grammar::CNF < > ToCNF::convert(const grammar::RightRG < > & origGrammar) {
-	return convertInternal(origGrammar);
-}
-
 auto ToCNFCFG = registration::AbstractRegister < ToCNF, grammar::CNF < >, const grammar::CFG < > & > ( ToCNF::convert );
 auto ToCNFEpsilonFreeCFG = registration::AbstractRegister < ToCNF, grammar::CNF < >, const grammar::EpsilonFreeCFG < > & > ( ToCNF::convert );
 auto ToCNFCNF = registration::AbstractRegister < ToCNF, grammar::CNF < >, const grammar::CNF < > & > ( ToCNF::convert );
diff --git a/alib2algo/src/grammar/simplify/ToCNF.h b/alib2algo/src/grammar/simplify/ToCNF.h
index d1d96976f3..88165da160 100644
--- a/alib2algo/src/grammar/simplify/ToCNF.h
+++ b/alib2algo/src/grammar/simplify/ToCNF.h
@@ -18,6 +18,8 @@
 #include <grammar/Regular/RightLG.h>
 #include <grammar/Regular/RightRG.h>
 
+#include <common/createUnique.hpp>
+
 namespace grammar {
 
 namespace simplify {
@@ -25,16 +27,90 @@ namespace simplify {
 class ToCNF {
 public:
 	static grammar::CNF < > convert( const grammar::CFG < > & grammar );
+
 	static grammar::CNF < > convert( const grammar::EpsilonFreeCFG < > & grammar );
+
 	static grammar::CNF < > convert( const grammar::GNF < > & grammar );
-	static grammar::CNF < > convert( const grammar::CNF < > & grammar );
+
+	template < class SymbolType >
+	static grammar::CNF < SymbolType > convert( const grammar::CNF < SymbolType > & grammar );
+
 	static grammar::CNF < > convert( const grammar::LG < > & grammar );
+
 	static grammar::CNF < > convert( const grammar::LeftLG < > & grammar );
-	static grammar::CNF < > convert( const grammar::LeftRG < > & grammar );
+
+	template < class SymbolType >
+	static grammar::CNF < SymbolType > convert( const grammar::LeftRG < SymbolType > & grammar );
+
 	static grammar::CNF < > convert( const grammar::RightLG < > & grammar );
-	static grammar::CNF < > convert( const grammar::RightRG < > & grammar );
+
+	template < class SymbolType >
+	static grammar::CNF < SymbolType > convert( const grammar::RightRG < SymbolType > & grammar );
 };
 
+template < class SymbolType >
+grammar::CNF < SymbolType > ToCNF::convert(const grammar::CNF < SymbolType > & origGrammar) {
+	return origGrammar;
+}
+
+template < class SymbolType >
+grammar::CNF < SymbolType > ToCNF::convert ( const grammar::LeftRG < SymbolType > & origGrammar ) {
+	grammar::CNF < SymbolType > result ( origGrammar.getInitialSymbol ( ) );
+
+	result.setNonterminalAlphabet ( origGrammar.getNonterminalAlphabet ( ) );
+	result.setTerminalAlphabet ( origGrammar.getTerminalAlphabet ( ) );
+
+	ext::map < SymbolType, SymbolType > terminalToShadowNonterminal;
+	for ( const SymbolType & symbol : origGrammar.getTerminalAlphabet ( ) ) {
+		SymbolType shadowSymbol = common::createUnique ( symbol, result.getTerminalAlphabet ( ), result.getNonterminalAlphabet ( ) );
+		terminalToShadowNonterminal.insert ( std::make_pair ( symbol, shadowSymbol ) );
+		result.addNonterminalSymbol ( shadowSymbol );
+		result.addRule ( std::move ( shadowSymbol ), symbol );
+	}
+
+	for ( const std::pair < SymbolType, ext::set < ext::variant < SymbolType, ext::pair < SymbolType, SymbolType > > > > & rules : origGrammar.getRules ( ) ) {
+		for ( const ext::variant < SymbolType, ext::pair < SymbolType, SymbolType > > & rhs : rules.second ) {
+			if ( rhs.template is < SymbolType > ( ) ) {
+				result.addRule ( rules.first, rhs );
+			} else {
+				const ext::pair < SymbolType, SymbolType > & rhsPair = rhs.template get < ext::pair < SymbolType, SymbolType > > ( );
+				result.addRule ( rules.first, ext::make_pair ( rhsPair.first, terminalToShadowNonterminal.at ( rhsPair.second ) ) );
+			}
+		}
+	}
+
+	return result;
+}
+
+template < class SymbolType >
+grammar::CNF < SymbolType > ToCNF::convert ( const grammar::RightRG < SymbolType > & origGrammar ) {
+	grammar::CNF < SymbolType > result ( origGrammar.getInitialSymbol ( ) );
+
+	result.setNonterminalAlphabet ( origGrammar.getNonterminalAlphabet ( ) );
+	result.setTerminalAlphabet ( origGrammar.getTerminalAlphabet ( ) );
+
+	ext::map < SymbolType, SymbolType > terminalToShadowNonterminal;
+	for ( const SymbolType & symbol : origGrammar.getTerminalAlphabet ( ) ) {
+		SymbolType shadowSymbol = common::createUnique ( symbol, result.getTerminalAlphabet ( ), result.getNonterminalAlphabet ( ) );
+		terminalToShadowNonterminal.insert ( std::make_pair ( symbol, shadowSymbol ) );
+		result.addNonterminalSymbol ( shadowSymbol );
+		result.addRule ( std::move ( shadowSymbol ), symbol );
+	}
+
+	for ( const std::pair < SymbolType, ext::set < ext::variant < SymbolType, ext::pair < SymbolType, SymbolType > > > > & rules : origGrammar.getRules ( ) ) {
+		for ( const ext::variant < SymbolType, ext::pair < SymbolType, SymbolType > > & rhs : rules.second ) {
+			if ( rhs.template is < SymbolType > ( ) ) {
+				result.addRule ( rules.first, rhs );
+			} else {
+				const ext::pair < SymbolType, SymbolType > & rhsPair = rhs.template get < ext::pair < SymbolType, SymbolType > > ( );
+				result.addRule ( rules.first, ext::make_pair ( terminalToShadowNonterminal.at ( rhsPair.first ), rhsPair.second ) );
+			}
+		}
+	}
+
+	return result;
+}
+
 } /* namespace simplify */
 
 } /* namespace grammar */
-- 
GitLab