From 505418dad62f10bff10c4348ab67d0df3a4eed0c Mon Sep 17 00:00:00 2001
From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz>
Date: Fri, 16 Oct 2015 11:43:41 +0200
Subject: [PATCH] add follow of all symbols

---
 alib2algo/src/grammar/parsing/Follow.cpp | 49 ++++++++++++++++--------
 alib2algo/src/grammar/parsing/Follow.h   | 31 ++++++++++++---
 2 files changed, 59 insertions(+), 21 deletions(-)

diff --git a/alib2algo/src/grammar/parsing/Follow.cpp b/alib2algo/src/grammar/parsing/Follow.cpp
index cd4a99e343..c85a0a3f0d 100644
--- a/alib2algo/src/grammar/parsing/Follow.cpp
+++ b/alib2algo/src/grammar/parsing/Follow.cpp
@@ -52,10 +52,7 @@ void Follow::follow ( const T & grammar, std::map < alphabet::Symbol, std::set <
 }
 
 template < class T >
-std::set < std::variant < alphabet::Symbol, string::Epsilon > > Follow::follow ( const T & grammar, const alphabet::Symbol & nt ) {
-	if ( !grammar.getNonterminalAlphabet ( ).count ( nt ) )
-		throw exception::AlibException ( "Follow: Given symbol is not nonterminal." );
-
+std::map< alphabet::Symbol, std::set < std::variant < alphabet::Symbol, string::Epsilon > > > Follow::follow ( const T & grammar ) {
 	/*
 	 * 1. Follow(S) = { \varepsilon }
 	 *    Follow(A) = {} forall A \in N, A \neq S
@@ -84,21 +81,43 @@ std::set < std::variant < alphabet::Symbol, string::Epsilon > > Follow::follow (
 		followSet1 = followSet2;
 	} while ( true );
 
-	return followSet1[nt];
+	return followSet1;
+}
+
+template < class T >
+std::set < std::variant < alphabet::Symbol, string::Epsilon > > Follow::follow ( const T & grammar, const alphabet::Symbol & nt ) {
+	if ( !grammar.getNonterminalAlphabet ( ).count ( nt ) )
+		throw exception::AlibException ( "Follow: Given symbol is not nonterminal." );
+
+	return follow(grammar)[nt];
+}
+
+auto FollowCFG = FollowBase1::RegistratorWrapper < FollowResult1, grammar::CFG > ( Follow::getInstance1 ( ), Follow::follow );
+auto FollowEpsilonFreeCFG = FollowBase1::RegistratorWrapper < FollowResult1, grammar::EpsilonFreeCFG > ( Follow::getInstance1 ( ), Follow::follow );
+auto FollowGNF = FollowBase1::RegistratorWrapper < FollowResult1, grammar::GNF > ( Follow::getInstance1 ( ), Follow::follow );
+auto FollowCNF = FollowBase1::RegistratorWrapper < FollowResult1, grammar::CNF > ( Follow::getInstance1 ( ), Follow::follow );
+auto FollowLG = FollowBase1::RegistratorWrapper < FollowResult1, grammar::LG > ( Follow::getInstance1 ( ), Follow::follow );
+auto FollowLeftLG = FollowBase1::RegistratorWrapper < FollowResult1, grammar::LeftLG > ( Follow::getInstance1 ( ), Follow::follow );
+auto FollowLeftRG = FollowBase1::RegistratorWrapper < FollowResult1, grammar::LeftRG > ( Follow::getInstance1 ( ), Follow::follow );
+auto FollowRightLG = FollowBase1::RegistratorWrapper < FollowResult1, grammar::RightLG > ( Follow::getInstance1 ( ), Follow::follow );
+auto FollowRightRG = FollowBase1::RegistratorWrapper < FollowResult1, grammar::RightRG > ( Follow::getInstance1 ( ), Follow::follow );
+
+std::map< alphabet::Symbol, std::set < std::variant < alphabet::Symbol, string::Epsilon > > > Follow::follow ( const grammar::Grammar & grammar ) {
+	return getInstance1 ( ).dispatch ( grammar.getData ( ) );
 }
 
-auto FollowCFG = Follow::RegistratorWrapper < std::set < std::variant < alphabet::Symbol, string::Epsilon > >, grammar::CFG > ( Follow::getInstance ( ), Follow::follow );
-auto FollowEpsilonFreeCFG = Follow::RegistratorWrapper < std::set < std::variant < alphabet::Symbol, string::Epsilon > >, grammar::EpsilonFreeCFG > ( Follow::getInstance ( ), Follow::follow );
-auto FollowGNF = Follow::RegistratorWrapper < std::set < std::variant < alphabet::Symbol, string::Epsilon > >, grammar::GNF > ( Follow::getInstance ( ), Follow::follow );
-auto FollowCNF = Follow::RegistratorWrapper < std::set < std::variant < alphabet::Symbol, string::Epsilon > >, grammar::CNF > ( Follow::getInstance ( ), Follow::follow );
-auto FollowLG  = Follow::RegistratorWrapper < std::set < std::variant < alphabet::Symbol, string::Epsilon > >, grammar::LG > ( Follow::getInstance ( ), Follow::follow );
-auto FollowLeftLG  = Follow::RegistratorWrapper < std::set < std::variant < alphabet::Symbol, string::Epsilon > >, grammar::LeftLG > ( Follow::getInstance ( ), Follow::follow );
-auto FollowLeftRG  = Follow::RegistratorWrapper < std::set < std::variant < alphabet::Symbol, string::Epsilon > >, grammar::LeftRG > ( Follow::getInstance ( ), Follow::follow );
-auto FollowRightLG = Follow::RegistratorWrapper < std::set < std::variant < alphabet::Symbol, string::Epsilon > >, grammar::RightLG > ( Follow::getInstance ( ), Follow::follow );
-auto FollowRightRG = Follow::RegistratorWrapper < std::set < std::variant < alphabet::Symbol, string::Epsilon > >, grammar::RightRG > ( Follow::getInstance ( ), Follow::follow );
+auto FollowCFG2 = FollowBase2::RegistratorWrapper < FollowResult2, grammar::CFG > ( Follow::getInstance2 ( ), Follow::follow );
+auto FollowEpsilonFreeCFG2 = FollowBase2::RegistratorWrapper < FollowResult2, grammar::EpsilonFreeCFG > ( Follow::getInstance2 ( ), Follow::follow );
+auto FollowGNF2 = FollowBase2::RegistratorWrapper < FollowResult2, grammar::GNF > ( Follow::getInstance2 ( ), Follow::follow );
+auto FollowCNF2 = FollowBase2::RegistratorWrapper < FollowResult2, grammar::CNF > ( Follow::getInstance2 ( ), Follow::follow );
+auto FollowLG2 = FollowBase2::RegistratorWrapper < FollowResult2, grammar::LG > ( Follow::getInstance2 ( ), Follow::follow );
+auto FollowLeftLG2 = FollowBase2::RegistratorWrapper < FollowResult2, grammar::LeftLG > ( Follow::getInstance2 ( ), Follow::follow );
+auto FollowLeftRG2 = FollowBase2::RegistratorWrapper < FollowResult2, grammar::LeftRG > ( Follow::getInstance2 ( ), Follow::follow );
+auto FollowRightLG2 = FollowBase2::RegistratorWrapper < FollowResult2, grammar::RightLG > ( Follow::getInstance2 ( ), Follow::follow );
+auto FollowRightRG2 = FollowBase2::RegistratorWrapper < FollowResult2, grammar::RightRG > ( Follow::getInstance2 ( ), Follow::follow );
 
 std::set < std::variant < alphabet::Symbol, string::Epsilon > > Follow::follow ( const grammar::Grammar & grammar, const alphabet::Symbol & nt ) {
-	return getInstance ( ).dispatch ( grammar.getData ( ), nt );
+	return getInstance2 ( ).dispatch ( grammar.getData ( ), nt );
 }
 
 } /* namespace parsing */
diff --git a/alib2algo/src/grammar/parsing/Follow.h b/alib2algo/src/grammar/parsing/Follow.h
index 9e965dabb6..9f4d57505c 100644
--- a/alib2algo/src/grammar/parsing/Follow.h
+++ b/alib2algo/src/grammar/parsing/Follow.h
@@ -20,15 +20,15 @@ namespace grammar {
 
 namespace parsing {
 
-class Follow : public std::SingleDispatchLastStaticParam < std::set < std::variant < alphabet::Symbol, string::Epsilon > >, grammar::GrammarBase, const alphabet::Symbol & > {
-	template < class T >
-	static void follow ( const T & grammar, std::map < alphabet::Symbol, std::set < std::variant < alphabet::Symbol, string::Epsilon > > > & followSet );
+typedef std::map< alphabet::Symbol, std::set < std::variant < alphabet::Symbol, string::Epsilon > > > FollowResult1;
+typedef std::SingleDispatch < FollowResult1, grammar::GrammarBase > FollowBase1;
 
-public:
-	static std::set < std::variant < alphabet::Symbol, string::Epsilon > > follow ( const grammar::Grammar & grammar, const alphabet::Symbol & nt );
+typedef std::set < std::variant < alphabet::Symbol, string::Epsilon > > FollowResult2;
+typedef std::SingleDispatchLastStaticParam < FollowResult2, grammar::GrammarBase, const alphabet::Symbol & > FollowBase2;
 
+class Follow : public FollowBase1, public FollowBase2 {
 	template < class T >
-	static std::set < std::variant < alphabet::Symbol, string::Epsilon > > follow ( const T & grammar, const alphabet::Symbol & nt );
+	static void follow ( const T & grammar, std::map < alphabet::Symbol, std::set < std::variant < alphabet::Symbol, string::Epsilon > > > & followSet );
 
 	static Follow & getInstance ( ) {
 		static Follow res;
@@ -36,6 +36,25 @@ public:
 		return res;
 	}
 
+public:
+	static FollowResult1 follow ( const grammar::Grammar & grammar );
+
+	static FollowResult2 follow ( const grammar::Grammar & grammar, const alphabet::Symbol & nt );
+
+	template < class T >
+	static FollowResult1 follow ( const T & grammar );
+
+	template < class T >
+	static FollowResult2 follow ( const T & grammar, const alphabet::Symbol & nt );
+
+	static FollowBase1 & getInstance1 ( ) {
+		return getInstance ( );
+	}
+
+	static FollowBase2 & getInstance2 ( ) {
+		return getInstance ( );
+	}
+
 };
 
 } /* namespace parsing */
-- 
GitLab