From d1897c248804e4f55f606b7c83dbf5ccadb16ebe Mon Sep 17 00:00:00 2001
From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz>
Date: Tue, 31 Oct 2017 15:48:35 +0100
Subject: [PATCH] use abstraction in automaton/grammar/string diff

---
 acompare2/makefile.conf                |  6 +--
 acompare2/src/acompare.cpp             | 70 +++++++++++++-------------
 alib2aux/src/compare/AutomatonDiff.cpp | 48 ++++++++----------
 alib2aux/src/compare/AutomatonDiff.h   | 23 +++++----
 alib2aux/src/compare/GrammarDiff.cpp   | 36 ++++++-------
 alib2aux/src/compare/GrammarDiff.h     | 25 ++++-----
 alib2aux/src/compare/StringDiff.cpp    |  8 +--
 alib2aux/src/compare/StringDiff.h      | 25 ++++-----
 8 files changed, 117 insertions(+), 124 deletions(-)

diff --git a/acompare2/makefile.conf b/acompare2/makefile.conf
index d992ab93d3..63fdc99aa2 100644
--- a/acompare2/makefile.conf
+++ b/acompare2/makefile.conf
@@ -1,4 +1,4 @@
 EXECUTABLE:=acompare2
-LINK_PATHS= ../alib2aux/ ../alib2str/ ../alib2data/ ../alib2xml/ ../alib2measure/ ../alib2common/  ../alib2std/
-LINK_LIBRARIES=alib2aux alib2str alib2data alib2xml alib2measure alib2common  alib2std xml2
-INCLUDE_PATHS=\$$(SOURCES_BASE_DIR)/../../alib2aux/src/ \$$(SOURCES_BASE_DIR)/../../alib2str/src/ \$$(SOURCES_BASE_DIR)/../../alib2data/src/ \$$(SOURCES_BASE_DIR)/../../alib2xml/src/ \$$(SOURCES_BASE_DIR)/../../alib2measure/src/ \$$(SOURCES_BASE_DIR)/../../alib2common/src/  \$$(SOURCES_BASE_DIR)/../../alib2std/src/ /usr/include/libxml2/
+LINK_PATHS=../alib2cli/ ../alib2aux/ ../alib2str/ ../alib2data/ ../alib2xml/ ../alib2measure/ ../alib2common/ ../alib2std/
+LINK_LIBRARIES=alib2cli alib2aux alib2str alib2data alib2xml alib2measure alib2common  alib2std xml2
+INCLUDE_PATHS=\$$(SOURCES_BASE_DIR)/../../alib2cli/src/ \$$(SOURCES_BASE_DIR)/../../alib2xml/src/ \$$(SOURCES_BASE_DIR)/../../alib2measure/src/ \$$(SOURCES_BASE_DIR)/../../alib2common/src/  \$$(SOURCES_BASE_DIR)/../../alib2std/src/ /usr/include/libxml2/
diff --git a/acompare2/src/acompare.cpp b/acompare2/src/acompare.cpp
index a2a6a1b8ed..1a91dbed33 100644
--- a/acompare2/src/acompare.cpp
+++ b/acompare2/src/acompare.cpp
@@ -5,17 +5,16 @@
  *      Author: Jan Travnicek
  */
 
+#include <tclap/CmdLine.h>
 #include <global/GlobalData.h>
 #include <measure>
-#include <sax/FromXMLParserHelper.h>
-#include <tclap/CmdLine.h>
 
-#include "exception/CommonException.h"
-#include "factory/XmlDataFactory.hpp"
+#include <exception/CommonException.h>
+#include <lexer/Lexer.h>
+#include <parser/Parser.h>
 
-#include <compare/AutomatonDiff.h>
-#include <compare/GrammarDiff.h>
-#include <compare/StringDiff.h>
+#include <factory/XmlDataFactory.hpp>
+#include <abstraction/ValueProvider.hpp>
 
 int main ( int argc, char * * argv ) {
 	try {
@@ -44,46 +43,49 @@ int main ( int argc, char * * argv ) {
 		if ( measure.isSet ( ) )
 			common::GlobalData::measure = true;
 
+		cli::Environment environment;
+		environment.setBinding ( "stdin1", input1.getValue ( ) );
+		environment.setBinding ( "stdin2", input2.getValue ( ) );
+		environment.setBinding ( "stdout", "-" );
+
 		measurements::start ( "Overal", measurements::Type::OVERALL );
 		measurements::start ( "Input read", measurements::Type::AUXILIARY );
 
-		ext::deque < sax::Token > tokens1 = sax::FromXMLParserHelper::parseInput ( input1 );
-		ext::deque < sax::Token > tokens2 = sax::FromXMLParserHelper::parseInput ( input2 );
-
-		int res;
-
-		if ( alib::XmlDataFactory::first < automaton::Automaton > ( tokens1 ) && alib::XmlDataFactory::first < automaton::Automaton > ( tokens2 ) ) {
-			automaton::Automaton automaton1 = alib::XmlDataFactory::fromTokens ( std::move ( tokens1 ) );
-			automaton::Automaton automaton2 = alib::XmlDataFactory::fromTokens ( std::move ( tokens2 ) );
-
-			measurements::end ( );
-			measurements::start ( "Compare", measurements::Type::MAIN );
+		cli::Parser parser ( cli::Lexer ( "execute <#stdin1 > $input1" ) );
+		parser.parse ( )->run ( environment );
 
-			res = compare::AutomatonDiff::diff ( automaton1, automaton2, std::cout );
-		} else if ( alib::XmlDataFactory::first < grammar::Grammar > ( tokens1 ) && alib::XmlDataFactory::first < grammar::Grammar > ( tokens2 ) ) {
-			grammar::Grammar grammar1 = alib::XmlDataFactory::fromTokens ( std::move ( tokens1 ) );
-			grammar::Grammar grammar2 = alib::XmlDataFactory::fromTokens ( std::move ( tokens2 ) );
+		parser = cli::Parser ( cli::Lexer ( "execute <#stdin2 > $input2" ) );
+		parser.parse ( )->run ( environment );
 
-			measurements::end ( );
-			measurements::start ( "Compare", measurements::Type::MAIN );
+		std::string input1Type = environment.getVariable ( "input1" )->getReturnType ( );
+		std::string input2Type = environment.getVariable ( "input2" )->getReturnType ( );
+		bool isAutomaton = input1Type.find ( "automaton::" ) == 0 && input2Type.find ( "automaton::" ) == 0;
+		bool isGrammar = input1Type.find ( "grammar::" ) == 0 && input2Type.find ( "grammar::" ) == 0;
+		bool isString = input1Type.find ( "string::" ) == 0 && input2Type.find ( "string::" ) == 0;
 
-			res = compare::GrammarDiff::diff ( grammar1, grammar2, std::cout );
-		} else if ( alib::XmlDataFactory::first < string::String > ( tokens1 ) && alib::XmlDataFactory::first < string::String > ( tokens2 ) ) {
-			string::String string1 = alib::XmlDataFactory::fromTokens ( std::move ( tokens1 ) );
-			string::String string2 = alib::XmlDataFactory::fromTokens ( std::move ( tokens2 ) );
-
-			measurements::end ( );
-			measurements::start ( "Compare", measurements::Type::MAIN );
-
-			res = compare::StringDiff::diff ( string1, string2, std::cout );
+		measurements::end ( );
+		measurements::start ( "Compare", measurements::Type::MAIN );
+
+		if ( isAutomaton ) {
+			parser = cli::Parser ( cli::Lexer ( "execute compare::AutomatonDiff $input1 $input2 > $output" ) );
+		} else if ( isGrammar ) {
+			parser = cli::Parser ( cli::Lexer ( "execute compare::GrammarDiff $input1 $input2 > $output" ) );
+		} else if ( isString ) {
+			parser = cli::Parser ( cli::Lexer ( "execute comapre::StringDiff $input1 $input2 > $output" ) );
 		} else {
 			throw exception::CommonException ( "Only automata, grammars and strings can be compared." );
 		}
+		parser.parse ( )->run ( environment );
+
+		std::string result = std::dynamic_pointer_cast < abstraction::ValueProvider < std::string > > ( environment.getVariable ( "output" ) )->getValue ( true );
+
+		if ( result != "" )
+			std::cout << result << std::endl;
 
 		measurements::end ( );
 		measurements::end ( );
 
-		return res;
+		return result != "";
 	} catch ( const exception::CommonException & exception ) {
 		alib::XmlDataFactory::toStdout ( exception );
 		return 1;
diff --git a/alib2aux/src/compare/AutomatonDiff.cpp b/alib2aux/src/compare/AutomatonDiff.cpp
index 3dcd3b2395..a39388c13c 100644
--- a/alib2aux/src/compare/AutomatonDiff.cpp
+++ b/alib2aux/src/compare/AutomatonDiff.cpp
@@ -10,31 +10,27 @@
 
 namespace compare {
 
-auto AutomatonDiffDFA = registration::OverloadRegister < AutomatonDiff, int, automaton::DFA < >, automaton::DFA < > > ( AutomatonDiff::diff );
-auto AutomatonDiffNFA = registration::OverloadRegister < AutomatonDiff, int, automaton::NFA < > , automaton::NFA < > > ( AutomatonDiff::diff );
-auto AutomatonDiffMultiInitialStateNFA = registration::OverloadRegister < AutomatonDiff, int, automaton::MultiInitialStateNFA < >, automaton::MultiInitialStateNFA < > > ( AutomatonDiff::diff );
-auto AutomatonDiffEpsilonNFA = registration::OverloadRegister < AutomatonDiff, int, automaton::EpsilonNFA < >, automaton::EpsilonNFA < > > ( AutomatonDiff::diff );
-auto AutomatonDiffExtendedNFA = registration::OverloadRegister < AutomatonDiff, int, automaton::ExtendedNFA < >, automaton::ExtendedNFA < > > ( AutomatonDiff::diff );
-auto AutomatonDiffCompactNFA = registration::OverloadRegister < AutomatonDiff, int, automaton::CompactNFA < >, automaton::CompactNFA < > > ( AutomatonDiff::diff );
-
-auto AutomatonDiffDFTA = registration::OverloadRegister < AutomatonDiff, int, automaton::DFTA < >, automaton::DFTA < > > ( AutomatonDiff::diff );
-auto AutomatonDiffNFTA = registration::OverloadRegister < AutomatonDiff, int, automaton::NFTA < >, automaton::NFTA < > > ( AutomatonDiff::diff );
-
-auto AutomatonDiffDPDA = registration::OverloadRegister < AutomatonDiff, int, automaton::DPDA < >, automaton::DPDA < > > ( AutomatonDiff::diff );
-auto AutomatonDiffNPDA = registration::OverloadRegister < AutomatonDiff, int, automaton::NPDA < >, automaton::NPDA < > > ( AutomatonDiff::diff );
-auto AutomatonDiffInputDrivenDPDA = registration::OverloadRegister < AutomatonDiff, int, automaton::InputDrivenDPDA < >, automaton::InputDrivenDPDA < > > ( AutomatonDiff::diff );
-auto AutomatonDiffInputDrivenNPDA = registration::OverloadRegister < AutomatonDiff, int, automaton::InputDrivenNPDA < >, automaton::InputDrivenNPDA < > > ( AutomatonDiff::diff );
-auto AutomatonDiffVisiblyPushdownDPDA = registration::OverloadRegister < AutomatonDiff, int, automaton::VisiblyPushdownDPDA < >, automaton::VisiblyPushdownDPDA < > > ( AutomatonDiff::diff );
-auto AutomatonDiffVisiblyPushdownNPDA = registration::OverloadRegister < AutomatonDiff, int, automaton::VisiblyPushdownNPDA < >, automaton::VisiblyPushdownNPDA < > > ( AutomatonDiff::diff );
-auto AutomatonDiffRealTimeHeightDeterministicDPDA = registration::OverloadRegister < AutomatonDiff, int, automaton::RealTimeHeightDeterministicDPDA < >, automaton::RealTimeHeightDeterministicDPDA < > > ( AutomatonDiff::diff );
-auto AutomatonDiffRealTimeHeightDeterministicNPDA = registration::OverloadRegister < AutomatonDiff, int, automaton::RealTimeHeightDeterministicNPDA < >, automaton::RealTimeHeightDeterministicNPDA < > > ( AutomatonDiff::diff );
-auto AutomatonDiffSinglePopDPDA = registration::OverloadRegister < AutomatonDiff, int, automaton::SinglePopDPDA < >, automaton::SinglePopDPDA < > > ( AutomatonDiff::diff );
-auto AutomatonDiffSinglePopNPDA = registration::OverloadRegister < AutomatonDiff, int, automaton::SinglePopNPDA < >, automaton::SinglePopNPDA < > > ( AutomatonDiff::diff );
-
-auto AutomatonDiffOneTapeDTM = registration::OverloadRegister < AutomatonDiff, int, automaton::OneTapeDTM < >, automaton::OneTapeDTM < > > ( AutomatonDiff::diff );
-
-int AutomatonDiff::diff(const automaton::Automaton& a, const automaton::Automaton& b, std::ostream & out ) {
-	return dispatch(a.getData(), b.getData(), out);
-}
+auto AutomatonDiffDFA = registration::AbstractRegister < AutomatonDiff, std::string, const automaton::DFA < > &, const automaton::DFA < > & > ( AutomatonDiff::diff );
+auto AutomatonDiffNFA = registration::AbstractRegister < AutomatonDiff, std::string, const automaton::NFA < > & , const automaton::NFA < > & > ( AutomatonDiff::diff );
+auto AutomatonDiffMultiInitialStateNFA = registration::AbstractRegister < AutomatonDiff, std::string, const automaton::MultiInitialStateNFA < > &, const automaton::MultiInitialStateNFA < > & > ( AutomatonDiff::diff );
+auto AutomatonDiffEpsilonNFA = registration::AbstractRegister < AutomatonDiff, std::string, const automaton::EpsilonNFA < > &, const automaton::EpsilonNFA < > & > ( AutomatonDiff::diff );
+auto AutomatonDiffExtendedNFA = registration::AbstractRegister < AutomatonDiff, std::string, const automaton::ExtendedNFA < > &, const automaton::ExtendedNFA < > & > ( AutomatonDiff::diff );
+auto AutomatonDiffCompactNFA = registration::AbstractRegister < AutomatonDiff, std::string, const automaton::CompactNFA < > &, const automaton::CompactNFA < > & > ( AutomatonDiff::diff );
+
+auto AutomatonDiffDFTA = registration::AbstractRegister < AutomatonDiff, std::string, const automaton::DFTA < > &, const automaton::DFTA < > & > ( AutomatonDiff::diff );
+auto AutomatonDiffNFTA = registration::AbstractRegister < AutomatonDiff, std::string, const automaton::NFTA < > &, const automaton::NFTA < > & > ( AutomatonDiff::diff );
+
+auto AutomatonDiffDPDA = registration::AbstractRegister < AutomatonDiff, std::string, const automaton::DPDA < > &, const automaton::DPDA < > & > ( AutomatonDiff::diff );
+auto AutomatonDiffNPDA = registration::AbstractRegister < AutomatonDiff, std::string, const automaton::NPDA < > &, const automaton::NPDA < > & > ( AutomatonDiff::diff );
+auto AutomatonDiffInputDrivenDPDA = registration::AbstractRegister < AutomatonDiff, std::string, const automaton::InputDrivenDPDA < > &, const automaton::InputDrivenDPDA < > & > ( AutomatonDiff::diff );
+auto AutomatonDiffInputDrivenNPDA = registration::AbstractRegister < AutomatonDiff, std::string, const automaton::InputDrivenNPDA < > &, const automaton::InputDrivenNPDA < > & > ( AutomatonDiff::diff );
+auto AutomatonDiffVisiblyPushdownDPDA = registration::AbstractRegister < AutomatonDiff, std::string, const automaton::VisiblyPushdownDPDA < > &, const automaton::VisiblyPushdownDPDA < > & > ( AutomatonDiff::diff );
+auto AutomatonDiffVisiblyPushdownNPDA = registration::AbstractRegister < AutomatonDiff, std::string, const automaton::VisiblyPushdownNPDA < > &, const automaton::VisiblyPushdownNPDA < > & > ( AutomatonDiff::diff );
+auto AutomatonDiffRealTimeHeightDeterministicDPDA = registration::AbstractRegister < AutomatonDiff, std::string, const automaton::RealTimeHeightDeterministicDPDA < > &, const automaton::RealTimeHeightDeterministicDPDA < > & > ( AutomatonDiff::diff );
+auto AutomatonDiffRealTimeHeightDeterministicNPDA = registration::AbstractRegister < AutomatonDiff, std::string, const automaton::RealTimeHeightDeterministicNPDA < > &, const automaton::RealTimeHeightDeterministicNPDA < > & > ( AutomatonDiff::diff );
+auto AutomatonDiffSinglePopDPDA = registration::AbstractRegister < AutomatonDiff, std::string, const automaton::SinglePopDPDA < > &, const automaton::SinglePopDPDA < > & > ( AutomatonDiff::diff );
+auto AutomatonDiffSinglePopNPDA = registration::AbstractRegister < AutomatonDiff, std::string, const automaton::SinglePopNPDA < > &, const automaton::SinglePopNPDA < > & > ( AutomatonDiff::diff );
+
+auto AutomatonDiffOneTapeDTM = registration::AbstractRegister < AutomatonDiff, std::string, const automaton::OneTapeDTM < > &, const automaton::OneTapeDTM < > & > ( AutomatonDiff::diff );
 
 } /* namespace compare */
diff --git a/alib2aux/src/compare/AutomatonDiff.h b/alib2aux/src/compare/AutomatonDiff.h
index 0268c3414b..88ce063c6d 100644
--- a/alib2aux/src/compare/AutomatonDiff.h
+++ b/alib2aux/src/compare/AutomatonDiff.h
@@ -8,13 +8,9 @@
 #ifndef AUTOMATON_DIFF_H_
 #define AUTOMATON_DIFF_H_
 
-#include <core/multipleDispatch.hpp>
-
 #include <compare/DiffAux.h>
 #include <compare/AutomatonCompare.h>
 
-#include <automaton/Automaton.h>
-#include <automaton/AutomatonFeatures.h>
 #include <set>
 #include <list>
 #include <map>
@@ -45,7 +41,7 @@
 
 namespace compare {
 
-class AutomatonDiff : public alib::MultipleDispatch < AutomatonDiff, int, ext::tuple < >, ext::tuple < const automaton::AutomatonBase &, const automaton::AutomatonBase & >, ext::tuple < std::ostream & > > {
+class AutomatonDiff {
 private:
 	template<class SymbolType, class StateType>
 	static void printDiff(const automaton::DFA < SymbolType, StateType > & a, const automaton::DFA < SymbolType, StateType > & b, std::ostream & out );
@@ -105,9 +101,10 @@ private:
 	static void printDiff(const automaton::OneTapeDTM < SymbolType, StateType > & a, const automaton::OneTapeDTM < SymbolType, StateType > & b, std::ostream & out );
 public:
 	template<class T>
-	static int diff(const T & a, const T & b, std::ostream & out );
+	static void diff(const T & a, const T & b, std::ostream & out );
 
-	static int diff(const automaton::Automaton& a, const automaton::Automaton& b, std::ostream & out );
+	template < class T >
+	static std::string diff ( const T & a, const T & b );
 };
 
 template<class SymbolType, class StateType>
@@ -1030,15 +1027,19 @@ void AutomatonDiff::printDiff(const automaton::OneTapeDTM < SymbolType, StateTyp
 }
 
 template < class T>
-int AutomatonDiff::diff(const T & a, const T & b, std::ostream & out) {
+void AutomatonDiff::diff(const T & a, const T & b, std::ostream & out) {
 	if(!AutomatonCompare::compare(a, b)) {
 		AutomatonDiff::printDiff(a, b, out);
-		return 1;
-	} else {
-		return 0;
 	}
 }
 
+template < class T >
+std::string AutomatonDiff::diff ( const T & a, const T & b ) {
+	std::stringstream ss;
+	diff ( a, b, ss );
+	return ss.str ( );
+}
+
 } /* namespace compare */
 
 #endif /* AUTOMATON_DIFF_H_ */
diff --git a/alib2aux/src/compare/GrammarDiff.cpp b/alib2aux/src/compare/GrammarDiff.cpp
index da6b6736e2..b9a237ee46 100644
--- a/alib2aux/src/compare/GrammarDiff.cpp
+++ b/alib2aux/src/compare/GrammarDiff.cpp
@@ -10,25 +10,21 @@
 
 namespace compare {
 
-auto GrammarDiffLeftLG = registration::OverloadRegister < GrammarDiff, int, grammar::LeftLG < >, grammar::LeftLG < > > ( GrammarDiff::diff );
-auto GrammarDiffLeftRG = registration::OverloadRegister < GrammarDiff, int, grammar::LeftRG < >, grammar::LeftRG < > > ( GrammarDiff::diff );
-auto GrammarDiffRightLG = registration::OverloadRegister < GrammarDiff, int, grammar::RightLG < >, grammar::RightLG < > > ( GrammarDiff::diff );
-auto GrammarDiffRightRG = registration::OverloadRegister < GrammarDiff, int, grammar::RightRG < >, grammar::RightRG < > > ( GrammarDiff::diff );
-
-auto GrammarDiffLG = registration::OverloadRegister < GrammarDiff, int, grammar::LG < >, grammar::LG < > > ( GrammarDiff::diff );
-auto GrammarDiffCFG = registration::OverloadRegister < GrammarDiff, int, grammar::CFG < >, grammar::CFG < > > ( GrammarDiff::diff );
-auto GrammarDiffEpsilonFreeCFG = registration::OverloadRegister < GrammarDiff, int, grammar::EpsilonFreeCFG < >, grammar::EpsilonFreeCFG < > > ( GrammarDiff::diff );
-auto GrammarDiffCNF = registration::OverloadRegister < GrammarDiff, int, grammar::CNF < >, grammar::CNF < > > ( GrammarDiff::diff );
-auto GrammarDiffGNF = registration::OverloadRegister < GrammarDiff, int, grammar::GNF < >, grammar::GNF < > > ( GrammarDiff::diff );
-auto GrammarDiffCSG = registration::OverloadRegister < GrammarDiff, int, grammar::CSG < >, grammar::CSG < > > ( GrammarDiff::diff );
-
-auto GrammarDiffNonContractingGrammar = registration::OverloadRegister < GrammarDiff, int, grammar::NonContractingGrammar < >, grammar::NonContractingGrammar < > > ( GrammarDiff::diff );
-auto GrammarDiffContextPreservingUnrestrictedGrammar = registration::OverloadRegister < GrammarDiff, int, grammar::ContextPreservingUnrestrictedGrammar < >, grammar::ContextPreservingUnrestrictedGrammar < > > ( GrammarDiff::diff );
-
-auto GrammarDiffUnrestrictedGrammar = registration::OverloadRegister < GrammarDiff, int, grammar::UnrestrictedGrammar < >, grammar::UnrestrictedGrammar < > > ( GrammarDiff::diff );
-
-int GrammarDiff::diff(const grammar::Grammar& a, const grammar::Grammar& b, std::ostream & out ) {
-	return dispatch(a.getData(), b.getData(), out);
-}
+auto GrammarDiffLeftLG = registration::AbstractRegister < GrammarDiff, std::string, const grammar::LeftLG < > &, const grammar::LeftLG < > & > ( GrammarDiff::diff );
+auto GrammarDiffLeftRG = registration::AbstractRegister < GrammarDiff, std::string, const grammar::LeftRG < > &, const grammar::LeftRG < > & > ( GrammarDiff::diff );
+auto GrammarDiffRightLG = registration::AbstractRegister < GrammarDiff, std::string, const grammar::RightLG < > &, const grammar::RightLG < > & > ( GrammarDiff::diff );
+auto GrammarDiffRightRG = registration::AbstractRegister < GrammarDiff, std::string, const grammar::RightRG < > &, const grammar::RightRG < > & > ( GrammarDiff::diff );
+
+auto GrammarDiffLG = registration::AbstractRegister < GrammarDiff, std::string, const grammar::LG < > &, const grammar::LG < > & > ( GrammarDiff::diff );
+auto GrammarDiffCFG = registration::AbstractRegister < GrammarDiff, std::string, const grammar::CFG < > &, const grammar::CFG < > & > ( GrammarDiff::diff );
+auto GrammarDiffEpsilonFreeCFG = registration::AbstractRegister < GrammarDiff, std::string, const grammar::EpsilonFreeCFG < > &, const grammar::EpsilonFreeCFG < > & > ( GrammarDiff::diff );
+auto GrammarDiffCNF = registration::AbstractRegister < GrammarDiff, std::string, const grammar::CNF < > &, const grammar::CNF < > & > ( GrammarDiff::diff );
+auto GrammarDiffGNF = registration::AbstractRegister < GrammarDiff, std::string, const grammar::GNF < > &, const grammar::GNF < > & > ( GrammarDiff::diff );
+auto GrammarDiffCSG = registration::AbstractRegister < GrammarDiff, std::string, const grammar::CSG < > &, const grammar::CSG < > & > ( GrammarDiff::diff );
+
+auto GrammarDiffNonContractingGrammar = registration::AbstractRegister < GrammarDiff, std::string, const grammar::NonContractingGrammar < > &, const grammar::NonContractingGrammar < > & > ( GrammarDiff::diff );
+auto GrammarDiffContextPreservingUnrestrictedGrammar = registration::AbstractRegister < GrammarDiff, std::string, const grammar::ContextPreservingUnrestrictedGrammar < > &, const grammar::ContextPreservingUnrestrictedGrammar < > & > ( GrammarDiff::diff );
+
+auto GrammarDiffUnrestrictedGrammar = registration::AbstractRegister < GrammarDiff, std::string, const grammar::UnrestrictedGrammar < > &, const grammar::UnrestrictedGrammar < > & > ( GrammarDiff::diff );
 
 } /* namespace compare */
diff --git a/alib2aux/src/compare/GrammarDiff.h b/alib2aux/src/compare/GrammarDiff.h
index be0709ae6a..fc437cae66 100644
--- a/alib2aux/src/compare/GrammarDiff.h
+++ b/alib2aux/src/compare/GrammarDiff.h
@@ -8,13 +8,9 @@
 #ifndef GRAMMAR_DIFF_H_
 #define GRAMMAR_DIFF_H_
 
-#include <core/multipleDispatch.hpp>
-
 #include <compare/DiffAux.h>
 #include <compare/GrammarCompare.h>
 
-#include <grammar/Grammar.h>
-#include <grammar/GrammarFeatures.h>
 #include <set>
 #include <map>
 #include <list>
@@ -41,7 +37,7 @@
 
 namespace compare {
 
-class GrammarDiff : public alib::MultipleDispatch < GrammarDiff, int, ext::tuple < >, ext::tuple < const grammar::GrammarBase &, const grammar::GrammarBase & >, ext::tuple < std::ostream & > > {
+class GrammarDiff {
 private:
 	template < class SymbolType >
 	static void printDiff(const grammar::LeftLG < SymbolType > & a, const grammar::LeftLG < SymbolType > & b, std::ostream & out );
@@ -82,10 +78,11 @@ private:
 	template < class SymbolType >
 	static void printDiff(const grammar::UnrestrictedGrammar < SymbolType > & a, const grammar::UnrestrictedGrammar < SymbolType > & b, std::ostream & out );
 public:
-	template < class T >
-	static int diff(const T & a, const T & b, std::ostream & out );
+	template<class T>
+	static void diff(const T & a, const T & b, std::ostream & out );
 
-	static int diff(const grammar::Grammar& a, const grammar::Grammar& b, std::ostream & out );
+	template < class T >
+	static std::string diff ( const T & a, const T & b );
 };
 
 template < class SymbolType >
@@ -492,15 +489,19 @@ void GrammarDiff::printDiff(const grammar::UnrestrictedGrammar < SymbolType > &
 }
 
 template < class T >
-int GrammarDiff::diff(const T & a, const T & b, std::ostream & out ) {
+void GrammarDiff::diff(const T & a, const T & b, std::ostream & out ) {
 	if(!GrammarCompare::compare(a, b)) {
 	  GrammarDiff::printDiff ( a, b, out );
-	  return 1;
-	} else {
-	  return 0;
 	}
 }
 
+template < class T >
+std::string GrammarDiff::diff ( const T & a, const T & b ) {
+	std::stringstream ss;
+	diff ( a, b, ss );
+	return ss.str ( );
+}
+
 } /* namespace compare */
 
 #endif /* GRAMMAR_DIFF_H_ */
diff --git a/alib2aux/src/compare/StringDiff.cpp b/alib2aux/src/compare/StringDiff.cpp
index f4e0464583..80ec7d659e 100644
--- a/alib2aux/src/compare/StringDiff.cpp
+++ b/alib2aux/src/compare/StringDiff.cpp
@@ -10,11 +10,7 @@
 
 namespace compare {
 
-auto StringDiffLinear = registration::OverloadRegister < StringDiff, int, string::LinearString < >, string::LinearString < > > ( StringDiff::diff );
-auto StringDiffCyclic = registration::OverloadRegister < StringDiff, int, string::CyclicString < >, string::CyclicString < > > ( StringDiff::diff );
-
-int StringDiff::diff ( const string::String & a, const string::String & b, std::ostream & out ) {
-	return dispatch ( a.getData ( ), b.getData ( ), out );
-}
+auto StringDiffLinear = registration::AbstractRegister < StringDiff, std::string, const string::LinearString < > &, const string::LinearString < > & > ( StringDiff::diff );
+auto StringDiffCyclic = registration::AbstractRegister < StringDiff, std::string, const string::CyclicString < > &, const string::CyclicString < > & > ( StringDiff::diff );
 
 } /* namespace compare */
diff --git a/alib2aux/src/compare/StringDiff.h b/alib2aux/src/compare/StringDiff.h
index 30ea38acf5..91390d53b4 100644
--- a/alib2aux/src/compare/StringDiff.h
+++ b/alib2aux/src/compare/StringDiff.h
@@ -8,13 +8,9 @@
 #ifndef STRING_DIFF_H_
 #define STRING_DIFF_H_
 
-#include <core/multipleDispatch.hpp>
-
 #include <compare/DiffAux.h>
 #include <compare/StringCompare.h>
 
-#include <string/String.h>
-#include <string/StringFeatures.h>
 #include <utility>
 #include <vector>
 #include <ostream>
@@ -24,7 +20,7 @@
 
 namespace compare {
 
-class StringDiff : public alib::MultipleDispatch < StringDiff, int, ext::tuple < >, ext::tuple < const string::StringBase &, const string::StringBase & >, ext::tuple < std::ostream & > > {
+class StringDiff {
 private:
 	template < class SymbolType >
 	static void printDiff ( const string::LinearString < SymbolType > & a, const string::LinearString < SymbolType > & b, std::ostream & out );
@@ -33,10 +29,11 @@ private:
 	static void printDiff ( const string::CyclicString < SymbolType > & a, const string::CyclicString < SymbolType > & b, std::ostream & out );
 
 public:
-	template < class T >
-	static int diff ( const T & a, const T & b, std::ostream & out );
+	template<class T>
+	static void diff(const T & a, const T & b, std::ostream & out );
 
-	static int diff ( const string::String & a, const string::String & b, std::ostream & out );
+	template < class T >
+	static std::string diff ( const T & a, const T & b );
 };
 
 template < class SymbolType >
@@ -62,15 +59,19 @@ void StringDiff::printDiff ( const string::LinearString < SymbolType > & a, cons
 }
 
 template < class T >
-int StringDiff::diff ( const T & a, const T & b, std::ostream & out ) {
+void StringDiff::diff ( const T & a, const T & b, std::ostream & out ) {
 	if ( !StringCompare::compare ( a, b ) ) {
 		StringDiff::printDiff ( a, b, out );
-		return 1;
-	} else {
-		return 0;
 	}
 }
 
+template < class T >
+std::string StringDiff::diff ( const T & a, const T & b ) {
+	std::stringstream ss;
+	diff ( a, b, ss );
+	return ss.str ( );
+}
+
 } /* namespace compare */
 
 #endif /* STRING_DIFF_H_ */
-- 
GitLab