diff --git a/alib2algo/src/grammar/parsing/First.cpp b/alib2algo/src/grammar/parsing/First.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..fc00d75ead0c6d8251a4931b5b2bf1079f139e5f
--- /dev/null
+++ b/alib2algo/src/grammar/parsing/First.cpp
@@ -0,0 +1,195 @@
+/*
+ * First.cpp
+ *
+ *  Created on: 9. 6. 2015
+ *	  Author: Tomas Pecka
+ */
+
+#include "First.h"
+#include <algorithm>
+#include <string/Epsilon.h>
+#include <iterator>
+
+#include "setunion.h"
+
+namespace grammar {
+
+namespace parsing {
+
+template<class T>
+std::set<std::variant<alphabet::Symbol, string::Epsilon>> First::firstSeq(const T& grammar, const std::vector<alphabet::Symbol>& rhs, std::map<alphabet::Symbol, std::set<std::variant<alphabet::Symbol, string::Epsilon>>> firstNt)
+{
+	// 1. FIRST(\varepsilon) = { \varepsilon }
+	if(rhs.empty()) return {string::Epsilon::EPSILON};
+
+	// 2. FIRST(a) = { a } forall a \in T
+	else if(grammar.getTerminalAlphabet().find(rhs[0]) != grammar.getTerminalAlphabet().end())
+		return {rhs[0]};
+
+	// 3. FIRST(A) = first(A) forall A \in N
+	else if(rhs.size() == 1 && grammar.getNonterminalAlphabet().find(rhs[0]) != grammar.getNonterminalAlphabet().end())
+		return firstNt[rhs[0]];
+
+	// 4. FIRST(A \alpha) = first(A) if A \in N and \varepsilon \notin first(A)
+	else if(grammar.getNonterminalAlphabet().find(rhs[0]) != grammar.getNonterminalAlphabet().end() && firstNt[rhs[0]].find(string::Epsilon::EPSILON) == firstNt[rhs[0]].end())
+		return firstNt[rhs[0]];
+
+	// 5. FIRST(A \alpha) = (first(A) - \varepsilon) \cup FIRST(\alpha) if A \in N and \varepsilon \in first(A)
+	else if(grammar.getNonterminalAlphabet().find(rhs[0]) != grammar.getNonterminalAlphabet().end() && firstNt[rhs[0]].find(string::Epsilon::EPSILON) != firstNt[rhs[0]].end())
+	{
+		std::set<std::variant<alphabet::Symbol, string::Epsilon>> fiA = firstNt[rhs[0]];
+
+		auto it = fiA.find(string::Epsilon::EPSILON);
+		if(it != fiA.end()) fiA.erase(it);
+
+		std::vector<alphabet::Symbol> alpha = rhs;
+		alpha.erase(alpha.begin());
+		std::set<std::variant<alphabet::Symbol, string::Epsilon>> FIA = firstSeq(grammar, alpha, firstNt);
+
+		return setunion(fiA, FIA);
+	}
+	throw exception::AlibException("Unhandled case in First.cpp");
+}
+
+template<class T>
+std::set<std::variant<alphabet::Symbol, string::Epsilon>> First::first(const T& grammar, const std::vector<alphabet::Symbol>& rhs)
+{
+	/*
+	 *
+	 * 1. foreach A \in N: first(A) = \emptyset
+	 * 2. foreach A \rightarrow \alpha:
+	 *	first(A) = first(A) \cup FIRST(\alpha)
+	 * 3. repeat step 2 if at least one set first(A) has changed
+	 *
+	 */
+
+	// (N u T)* -> T*
+	// rhs -> first(rhs)
+	std::map<alphabet::Symbol, std::set<std::variant<alphabet::Symbol, string::Epsilon>>> firstNt;
+	for(const alphabet::Symbol& nt : grammar.getNonterminalAlphabet())
+		firstNt.insert(std::make_pair(nt, std::set<std::variant<alphabet::Symbol, string::Epsilon>>{}));
+
+	bool changed;
+	do
+	{
+		changed = false;
+
+		for(const std::pair<alphabet::Symbol, std::set<std::vector<alphabet::Symbol>>>& rule : grammar.getRawRules())
+		{
+			const alphabet::Symbol& lhs = rule.first;
+			for(const std::vector<alphabet::Symbol>& rhs : rule.second)
+			{
+				std::set<std::variant<alphabet::Symbol, string::Epsilon>> oldFirst;
+
+				oldFirst = firstNt[lhs];
+				firstNt[lhs] = setunion(firstNt[lhs], firstSeq(grammar, rhs, firstNt));
+				if(firstNt[lhs] != oldFirst)
+					changed = true;
+			}
+		}
+	}
+	while(changed);
+
+	/*
+	std::map<std::vector<alphabet::Symbol>, std::set<std::variant<alphabet::Symbol, string::Epsilon>>> res;
+	for(const std::pair<alphabet::Symbol, std::set<std::vector<alphabet::Symbol>>>& rule : grammar.getRawRules())
+		for(const std::vector<alphabet::Symbol>& rhs : rule.second)
+			res[rhs] = firstSeq(grammar, rhs, firstNt);
+	return res;
+	*/
+
+	return firstSeq(grammar, rhs, firstNt);
+}
+
+template<>
+std::set<std::variant<alphabet::Symbol, string::Epsilon>> First::first(const grammar::Grammar& grammar, const std::vector<alphabet::Symbol>& rhs) {
+	std::pair<std::vector<alphabet::Symbol>, std::set<std::variant<alphabet::Symbol, string::Epsilon>>> data;
+	data.first = rhs;
+	grammar.getData().Accept((void*) &data, First::FIRST);
+	return data.second;
+}
+
+void First::Visit(void* data, const grammar::LeftLG& grammar) const {
+	std::pair<std::vector<alphabet::Symbol>, std::set<std::variant<alphabet::Symbol, string::Epsilon>>>& out =
+		*((std::pair<std::vector<alphabet::Symbol>, std::set<std::variant<alphabet::Symbol, string::Epsilon>>>*) data);
+
+	out.second = this->first(grammar, out.first);
+}
+
+void First::Visit(void* data, const grammar::LeftRG& grammar) const {
+	std::pair<std::vector<alphabet::Symbol>, std::set<std::variant<alphabet::Symbol, string::Epsilon>>>& out =
+		*((std::pair<std::vector<alphabet::Symbol>, std::set<std::variant<alphabet::Symbol, string::Epsilon>>>*) data);
+
+	out.second = this->first(grammar, out.first);
+}
+
+void First::Visit(void* data, const grammar::RightLG& grammar) const {
+	std::pair<std::vector<alphabet::Symbol>, std::set<std::variant<alphabet::Symbol, string::Epsilon>>>& out =
+		*((std::pair<std::vector<alphabet::Symbol>, std::set<std::variant<alphabet::Symbol, string::Epsilon>>>*) data);
+
+	out.second = this->first(grammar, out.first);
+}
+
+void First::Visit(void* data, const grammar::RightRG& grammar) const {
+	std::pair<std::vector<alphabet::Symbol>, std::set<std::variant<alphabet::Symbol, string::Epsilon>>>& out =
+		*((std::pair<std::vector<alphabet::Symbol>, std::set<std::variant<alphabet::Symbol, string::Epsilon>>>*) data);
+
+	out.second = this->first(grammar, out.first);
+}
+
+void First::Visit(void* data, const grammar::LG& grammar) const {
+	std::pair<std::vector<alphabet::Symbol>, std::set<std::variant<alphabet::Symbol, string::Epsilon>>>& out =
+		*((std::pair<std::vector<alphabet::Symbol>, std::set<std::variant<alphabet::Symbol, string::Epsilon>>>*) data);
+
+	out.second = this->first(grammar, out.first);
+}
+
+void First::Visit(void* data, const grammar::CFG& grammar) const {
+	std::pair<std::vector<alphabet::Symbol>, std::set<std::variant<alphabet::Symbol, string::Epsilon>>>& out =
+		*((std::pair<std::vector<alphabet::Symbol>, std::set<std::variant<alphabet::Symbol, string::Epsilon>>>*) data);
+
+	out.second = this->first(grammar, out.first);
+}
+
+void First::Visit(void* data, const grammar::EpsilonFreeCFG& grammar) const {
+	std::pair<std::vector<alphabet::Symbol>, std::set<std::variant<alphabet::Symbol, string::Epsilon>>>& out =
+		*((std::pair<std::vector<alphabet::Symbol>, std::set<std::variant<alphabet::Symbol, string::Epsilon>>>*) data);
+
+	out.second = this->first(grammar, out.first);
+}
+
+void First::Visit(void* data, const grammar::CNF& grammar) const {
+	std::pair<std::vector<alphabet::Symbol>, std::set<std::variant<alphabet::Symbol, string::Epsilon>>>& out =
+		*((std::pair<std::vector<alphabet::Symbol>, std::set<std::variant<alphabet::Symbol, string::Epsilon>>>*) data);
+
+	out.second = this->first(grammar, out.first);
+}
+
+void First::Visit(void* data, const grammar::GNF& grammar) const {
+	std::pair<std::vector<alphabet::Symbol>, std::set<std::variant<alphabet::Symbol, string::Epsilon>>>& out =
+		*((std::pair<std::vector<alphabet::Symbol>, std::set<std::variant<alphabet::Symbol, string::Epsilon>>>*) data);
+
+	out.second = this->first(grammar, out.first);
+}
+
+void First::Visit(void*, const grammar::CSG&) const {
+	throw exception::AlibException("Unsupported grammar type CSG");
+}
+
+void First::Visit(void*, const grammar::NonContractingGrammar&) const {
+	throw exception::AlibException("Unsupported grammar type NonConctractingGrammar");
+}
+
+void First::Visit(void*, const grammar::ContextPreservingUnrestrictedGrammar&) const {
+	throw exception::AlibException("Unsupported grammar type ContextPreservingUnrestrictedGrammar");
+}
+
+void First::Visit(void*, const grammar::UnrestrictedGrammar&) const {
+	throw exception::AlibException("Unsupported grammar type UnrestrictedGrammar");
+}
+
+const First First::FIRST;
+
+} /* namespace parsing */
+
+} /* namespace grammar */
diff --git a/alib2algo/src/grammar/parsing/First.h b/alib2algo/src/grammar/parsing/First.h
new file mode 100644
index 0000000000000000000000000000000000000000..958a0a99a41d2f863f68547d03b5ab9c61fd3904
--- /dev/null
+++ b/alib2algo/src/grammar/parsing/First.h
@@ -0,0 +1,61 @@
+/*
+ * First.h
+ *
+ *  Created on: 9. 6. 2015
+ *	  Author: Tomas Pecka
+ */
+
+#ifndef FIRST_H_
+#define FIRST_H_
+
+#include <grammar/Grammar.h>
+
+#include <grammar/ContextFree/CFG.h>
+#include <grammar/ContextFree/EpsilonFreeCFG.h>
+#include <grammar/ContextFree/CNF.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 parsing {
+
+class First : public grammar::VisitableGrammarBase::const_visitor_type {
+
+public:
+	First() {}
+
+	template<class T>
+	static std::set<std::variant<alphabet::Symbol, string::Epsilon>> first(const T& grammar, const std::vector<alphabet::Symbol>& rhs);
+
+private:
+	template<class T>
+	static std::set<std::variant<alphabet::Symbol, string::Epsilon>> firstSeq(const T& grammar, const std::vector<alphabet::Symbol>& rhs, std::map<alphabet::Symbol, std::set<std::variant<alphabet::Symbol, string::Epsilon>>> firstNt);
+
+	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 First FIRST;
+};
+
+} /* namespace parsing */
+
+} /* namespace grammar */
+
+#endif /* FIRST_H_ */
diff --git a/alib2algo/src/grammar/parsing/Follow.cpp b/alib2algo/src/grammar/parsing/Follow.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..afd058b5f75ce537697ad97c7dec4bf9dd5550ff
--- /dev/null
+++ b/alib2algo/src/grammar/parsing/Follow.cpp
@@ -0,0 +1,177 @@
+/*
+ * Follow.cpp
+ *
+ *  Created on: 9. 6. 2015
+ *	  Author: Tomas Pecka
+ */
+
+#include "Follow.h"
+#include "First.h"
+#include <algorithm>
+#include <string/Epsilon.h>
+#include <iterator>
+
+#include "setunion.h"
+
+namespace grammar {
+
+namespace parsing {
+
+template<class T>
+std::set<std::variant<alphabet::Symbol, string::Epsilon>> Follow::follow(const T& grammar, const alphabet::Symbol& nt)
+{
+	if(grammar.getNonterminalAlphabet().find(nt) == grammar.getNonterminalAlphabet().end())
+		throw exception::AlibException("Follow: Given symbol is not nonterminal.");
+
+	/*
+	 * 1. Follow(S) = { \varepsilon }
+	 *    Follow(A) = {} forall A \in N, A \neq S
+	 * 2. Forall p \in P:
+	 *      if p == X -> \alpha Y \beta
+	 *		Follow(Y) = Follow(Y) \cup (First(\beta) \setminus { \varepsilon})
+	 *	if p == X -> \alpha Y \beta \wedge \varepsilon \in First(\beta)
+	 *		Follow(Y) = Follow(Y) \cup Follow(X)
+	 * 3. goto 2 if any follow set was changed in prev step.
+	 */
+
+	std::map<alphabet::Symbol, std::set<std::variant<alphabet::Symbol, string::Epsilon>>> followSet;
+
+	for(const alphabet::Symbol& symb : grammar.getNonterminalAlphabet())
+		followSet[symb] = {};
+
+	followSet[grammar.getInitialSymbol()] = {string::Epsilon::EPSILON};
+
+	bool changed;
+	do
+	{
+		changed = false;
+
+		for(const std::pair<alphabet::Symbol, std::set<std::vector<alphabet::Symbol>>>& rule : grammar.getRawRules())
+		{
+			const alphabet::Symbol& X = rule.first;
+			for(const std::vector<alphabet::Symbol>& rhs : rule.second)
+			{
+				// every nt in rhs is Y
+				for(std::vector<alphabet::Symbol>::const_iterator it = rhs.begin(); it != rhs.end(); it++)
+				{
+					const alphabet::Symbol& Y = *it;
+
+					if(grammar.getNonterminalAlphabet().find(Y) == grammar.getNonterminalAlphabet().end())
+						continue;
+
+					std::vector<alphabet::Symbol> beta(std::next(it), rhs.end());
+					std::set<std::variant<alphabet::Symbol, string::Epsilon>> oldFollow, firstBeta = First::first(grammar, beta);
+
+					auto epsIt = firstBeta.find(string::Epsilon::EPSILON);
+					if(epsIt != firstBeta.end())
+					{
+						firstBeta.erase(epsIt);
+
+						oldFollow = followSet[Y];
+						followSet[Y] = setunion(followSet[Y], followSet[X]);
+						if(oldFollow != followSet[Y]) changed = true;
+					}
+
+					oldFollow = followSet[Y];
+					followSet[Y] = setunion(followSet[Y], firstBeta);
+					if(oldFollow != followSet[Y]) changed = true;
+				}
+			}
+		}
+	}
+	while(changed);
+
+	return followSet[nt];
+}
+
+template<>
+std::set<std::variant<alphabet::Symbol, string::Epsilon>> Follow::follow(const grammar::Grammar& grammar, const alphabet::Symbol& nt) {
+	std::pair<alphabet::Symbol, std::set<std::variant<alphabet::Symbol, string::Epsilon>>> data(nt, {});
+	grammar.getData().Accept((void*) &data, Follow::FOLLOW);
+	return data.second;
+}
+
+void Follow::Visit(void* data, const grammar::LeftLG& grammar) const {
+	std::pair<alphabet::Symbol, std::set<std::variant<alphabet::Symbol, string::Epsilon>>>& out =
+		*((std::pair<alphabet::Symbol, std::set<std::variant<alphabet::Symbol, string::Epsilon>>>*) data);
+
+	out.second = this->follow(grammar, out.first);
+}
+
+void Follow::Visit(void* data, const grammar::LeftRG& grammar) const {
+	std::pair<alphabet::Symbol, std::set<std::variant<alphabet::Symbol, string::Epsilon>>>& out =
+		*((std::pair<alphabet::Symbol, std::set<std::variant<alphabet::Symbol, string::Epsilon>>>*) data);
+
+	out.second = this->follow(grammar, out.first);
+}
+
+void Follow::Visit(void* data, const grammar::RightLG& grammar) const {
+	std::pair<alphabet::Symbol, std::set<std::variant<alphabet::Symbol, string::Epsilon>>>& out =
+		*((std::pair<alphabet::Symbol, std::set<std::variant<alphabet::Symbol, string::Epsilon>>>*) data);
+
+	out.second = this->follow(grammar, out.first);
+}
+
+void Follow::Visit(void* data, const grammar::RightRG& grammar) const {
+	std::pair<alphabet::Symbol, std::set<std::variant<alphabet::Symbol, string::Epsilon>>>& out =
+		*((std::pair<alphabet::Symbol, std::set<std::variant<alphabet::Symbol, string::Epsilon>>>*) data);
+
+	out.second = this->follow(grammar, out.first);
+}
+
+void Follow::Visit(void* data, const grammar::LG& grammar) const {
+	std::pair<alphabet::Symbol, std::set<std::variant<alphabet::Symbol, string::Epsilon>>>& out =
+		*((std::pair<alphabet::Symbol, std::set<std::variant<alphabet::Symbol, string::Epsilon>>>*) data);
+
+	out.second = this->follow(grammar, out.first);
+}
+
+void Follow::Visit(void* data, const grammar::CFG& grammar) const {
+	std::pair<alphabet::Symbol, std::set<std::variant<alphabet::Symbol, string::Epsilon>>>& out =
+		*((std::pair<alphabet::Symbol, std::set<std::variant<alphabet::Symbol, string::Epsilon>>>*) data);
+
+	out.second = this->follow(grammar, out.first);
+}
+
+void Follow::Visit(void* data, const grammar::EpsilonFreeCFG& grammar) const {
+	std::pair<alphabet::Symbol, std::set<std::variant<alphabet::Symbol, string::Epsilon>>>& out =
+		*((std::pair<alphabet::Symbol, std::set<std::variant<alphabet::Symbol, string::Epsilon>>>*) data);
+
+	out.second = this->follow(grammar, out.first);
+}
+
+void Follow::Visit(void* data, const grammar::CNF& grammar) const {
+	std::pair<alphabet::Symbol, std::set<std::variant<alphabet::Symbol, string::Epsilon>>>& out =
+		*((std::pair<alphabet::Symbol, std::set<std::variant<alphabet::Symbol, string::Epsilon>>>*) data);
+
+	out.second = this->follow(grammar, out.first);
+}
+
+void Follow::Visit(void* data, const grammar::GNF& grammar) const {
+	std::pair<alphabet::Symbol, std::set<std::variant<alphabet::Symbol, string::Epsilon>>>& out =
+		*((std::pair<alphabet::Symbol, std::set<std::variant<alphabet::Symbol, string::Epsilon>>>*) data);
+
+	out.second = this->follow(grammar, out.first);
+}
+
+void Follow::Visit(void*, const grammar::CSG&) const {
+	throw exception::AlibException("Unsupported grammar type CSG");
+}
+
+void Follow::Visit(void*, const grammar::NonContractingGrammar&) const {
+	throw exception::AlibException("Unsupported grammar type NonConctractingGrammar");
+}
+
+void Follow::Visit(void*, const grammar::ContextPreservingUnrestrictedGrammar&) const {
+	throw exception::AlibException("Unsupported grammar type ContextPreservingUnrestrictedGrammar");
+}
+
+void Follow::Visit(void*, const grammar::UnrestrictedGrammar&) const {
+	throw exception::AlibException("Unsupported grammar type UnrestrictedGrammar");
+}
+
+const Follow Follow::FOLLOW;
+
+} /* namespace parsing */
+
+} /* namespace grammar */
diff --git a/alib2algo/src/grammar/parsing/Follow.h b/alib2algo/src/grammar/parsing/Follow.h
new file mode 100644
index 0000000000000000000000000000000000000000..3d1e4b40bbbe91ba19c0a20e495cc23f616286e3
--- /dev/null
+++ b/alib2algo/src/grammar/parsing/Follow.h
@@ -0,0 +1,58 @@
+/*
+ * Follow.h
+ *
+ *  Created on: 9. 6. 2015
+ *	  Author: Tomas Pecka
+ */
+
+#ifndef FOLLOW_H_
+#define FOLLOW_H_
+
+#include <grammar/Grammar.h>
+
+#include <grammar/ContextFree/CFG.h>
+#include <grammar/ContextFree/EpsilonFreeCFG.h>
+#include <grammar/ContextFree/CNF.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 parsing {
+
+class Follow : public grammar::VisitableGrammarBase::const_visitor_type {
+
+public:
+	Follow() {}
+
+	template<class T>
+	static std::set<std::variant<alphabet::Symbol, string::Epsilon>> follow(const T& grammar, const alphabet::Symbol& nt);
+
+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 Follow FOLLOW;
+};
+
+} /* namespace parsing */
+
+} /* namespace grammar */
+
+#endif /* FOLLOW_H_ */
diff --git a/alib2algo/src/grammar/parsing/setunion.h b/alib2algo/src/grammar/parsing/setunion.h
new file mode 100644
index 0000000000000000000000000000000000000000..c69b35061aec537a9cd2a9bbc2362162c826ca27
--- /dev/null
+++ b/alib2algo/src/grammar/parsing/setunion.h
@@ -0,0 +1,20 @@
+#ifndef __SETUNION_H__
+#define __SETUNION_H__
+
+namespace grammar {
+
+namespace parsing {
+
+template<class T>
+std::set<T> setunion(const std::set<T>& a, const std::set<T>& b)
+{
+	std::set<T> res;
+	std::set_union(a.begin(), a.end(), b.begin(), b.end(), std::inserter(res, res.begin()));
+	return res;
+}
+
+} /* namespace parsing */
+
+} /* namespace grammar */
+
+#endif /* __SETUNION_H__ */
diff --git a/alib2algo/test-src/grammar/parsing/FirstTest.cpp b/alib2algo/test-src/grammar/parsing/FirstTest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ad3f5fbf29cf79c6acdb6c9b3384735ebc47dd8b
--- /dev/null
+++ b/alib2algo/test-src/grammar/parsing/FirstTest.cpp
@@ -0,0 +1,144 @@
+#include "FirstTest.h"
+
+#include "grammar/parsing/First.h"
+#include "string/Epsilon.h"
+
+CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( FirstTest, "grammar" );
+CPPUNIT_TEST_SUITE_REGISTRATION( FirstTest );
+
+void FirstTest::setUp() {
+}
+
+void FirstTest::tearDown() {
+}
+
+void FirstTest::testFirst() {
+	{
+		alphabet::Symbol nE = alphabet::symbolFrom('E');
+		alphabet::Symbol nT = alphabet::symbolFrom('T');
+		alphabet::Symbol nF = alphabet::symbolFrom('F');
+
+		alphabet::Symbol tP = alphabet::symbolFrom('+');
+		alphabet::Symbol tS = alphabet::symbolFrom('*');
+		alphabet::Symbol tL = alphabet::symbolFrom('(');
+		alphabet::Symbol tR = alphabet::symbolFrom(')');
+		alphabet::Symbol tA = alphabet::symbolFrom('a');
+
+		grammar::CFG grammar(nE);
+		grammar.setTerminalAlphabet(std::set<alphabet::Symbol>{tP, tS, tL, tR, tA});
+		grammar.setNonterminalAlphabet(std::set<alphabet::Symbol>{nE, nT, nF});
+
+		std::vector<alphabet::Symbol> rhsE1({nE, tP, nT});
+		std::vector<alphabet::Symbol> rhsE2({nT});
+		std::vector<alphabet::Symbol> rhsT1({nT, tS, nF});
+		std::vector<alphabet::Symbol> rhsT2({nF});
+		std::vector<alphabet::Symbol> rhsF1({tA});
+		std::vector<alphabet::Symbol> rhsF2({tL, nE, tR});
+
+		grammar.addRule(nE, rhsE1);
+		grammar.addRule(nE, rhsE2);
+		grammar.addRule(nT, rhsT1);
+		grammar.addRule(nT, rhsT2);
+		grammar.addRule(nF, rhsF1);
+		grammar.addRule(nF, rhsF2);
+
+		// --------------------------------------------------
+		std::map<std::vector<alphabet::Symbol>, std::set<std::variant<alphabet::Symbol, string::Epsilon>>> first;
+
+		first[rhsE1] = std::set<std::variant<alphabet::Symbol, string::Epsilon>>{tA, tL};
+		first[rhsE2] = std::set<std::variant<alphabet::Symbol, string::Epsilon>>{tA, tL};
+		first[rhsT1] = std::set<std::variant<alphabet::Symbol, string::Epsilon>>{tA, tL};
+		first[rhsT2] = std::set<std::variant<alphabet::Symbol, string::Epsilon>>{tA, tL};
+		first[rhsF1] = std::set<std::variant<alphabet::Symbol, string::Epsilon>>{tA};
+		first[rhsF2] = std::set<std::variant<alphabet::Symbol, string::Epsilon>>{tL};
+
+		// --------------------------------------------------
+
+		std::map<std::vector<alphabet::Symbol>, std::set<std::variant<alphabet::Symbol, string::Epsilon>>> firstAlgo;
+
+		for(const auto& rule : grammar.getRawRules())
+			for(const auto& rhs : rule.second)
+				firstAlgo[rhs] = grammar::parsing::First::first(grammar, rhs);
+
+		CPPUNIT_ASSERT(first == firstAlgo);
+	}
+
+	{
+		alphabet::Symbol nS = alphabet::symbolFrom('S');
+		alphabet::Symbol nA = alphabet::symbolFrom('A');
+		alphabet::Symbol nB = alphabet::symbolFrom('B');
+		alphabet::Symbol nC = alphabet::symbolFrom('C');
+		alphabet::Symbol nD = alphabet::symbolFrom('D');
+		alphabet::Symbol nE = alphabet::symbolFrom('E');
+		alphabet::Symbol nF = alphabet::symbolFrom('F');
+
+		alphabet::Symbol tA = alphabet::symbolFrom('a');
+		alphabet::Symbol tB = alphabet::symbolFrom('b');
+		alphabet::Symbol tC = alphabet::symbolFrom('c');
+		alphabet::Symbol tD = alphabet::symbolFrom('d');
+		alphabet::Symbol tE = alphabet::symbolFrom('e');
+
+		grammar::CFG grammar(nS);
+		grammar.setTerminalAlphabet(std::set<alphabet::Symbol>{tA, tB, tC, tD, tE});
+		grammar.setNonterminalAlphabet(std::set<alphabet::Symbol>{nS, nA, nB, nC, nD, nE, nF});
+
+		std::vector<alphabet::Symbol> rhsS1({nB, tD, nS});
+		std::vector<alphabet::Symbol> rhsS2({tD, tD, nC});
+		std::vector<alphabet::Symbol> rhsS3({tC, nA});
+		std::vector<alphabet::Symbol> rhsA1({tA, tE, nE});
+		std::vector<alphabet::Symbol> rhsA2({tB, tB, nE});
+		std::vector<alphabet::Symbol> rhsB1({tA, nF});
+		std::vector<alphabet::Symbol> rhsB2({tB, tB, nD});
+		std::vector<alphabet::Symbol> rhsC1({tA, nB, tD});
+		std::vector<alphabet::Symbol> rhsC2({tE, nA});
+		std::vector<alphabet::Symbol> rhsD1({tC, tA, nF});
+		std::vector<alphabet::Symbol> rhsE1({tC, tA, tE, nE});
+		std::vector<alphabet::Symbol> rhsE2({});
+		std::vector<alphabet::Symbol> rhsF1({tE, nD});
+		std::vector<alphabet::Symbol> rhsF2({});
+
+		grammar.addRule(nS, rhsS1);
+		grammar.addRule(nS, rhsS2);
+		grammar.addRule(nS, rhsS3);
+		grammar.addRule(nA, rhsA1);
+		grammar.addRule(nA, rhsA2);
+		grammar.addRule(nB, rhsB1);
+		grammar.addRule(nB, rhsB2);
+		grammar.addRule(nC, rhsC1);
+		grammar.addRule(nC, rhsC2);
+		grammar.addRule(nD, rhsD1);
+		grammar.addRule(nE, rhsE1);
+		grammar.addRule(nE, rhsE2);
+		grammar.addRule(nF, rhsF1);
+		grammar.addRule(nF, rhsF2);
+
+		// --------------------------------------------------
+		std::map<std::vector<alphabet::Symbol>, std::set<std::variant<alphabet::Symbol, string::Epsilon>>> first;
+
+		first[rhsS1] = std::set<std::variant<alphabet::Symbol, string::Epsilon>>{tA, tB};
+		first[rhsS2] = std::set<std::variant<alphabet::Symbol, string::Epsilon>>{tD};
+		first[rhsS3] = std::set<std::variant<alphabet::Symbol, string::Epsilon>>{tC};
+		first[rhsA1] = std::set<std::variant<alphabet::Symbol, string::Epsilon>>{tA};
+		first[rhsA2] = std::set<std::variant<alphabet::Symbol, string::Epsilon>>{tB};
+		first[rhsB1] = std::set<std::variant<alphabet::Symbol, string::Epsilon>>{tA};
+		first[rhsB2] = std::set<std::variant<alphabet::Symbol, string::Epsilon>>{tB};
+		first[rhsC1] = std::set<std::variant<alphabet::Symbol, string::Epsilon>>{tA};
+		first[rhsC2] = std::set<std::variant<alphabet::Symbol, string::Epsilon>>{tE};
+		first[rhsD1] = std::set<std::variant<alphabet::Symbol, string::Epsilon>>{tC};
+		first[rhsE1] = std::set<std::variant<alphabet::Symbol, string::Epsilon>>{tC};
+		first[rhsE2] = std::set<std::variant<alphabet::Symbol, string::Epsilon>>{string::Epsilon::EPSILON};
+		first[rhsF1] = std::set<std::variant<alphabet::Symbol, string::Epsilon>>{tE};
+		first[rhsF2] = std::set<std::variant<alphabet::Symbol, string::Epsilon>>{string::Epsilon::EPSILON};
+
+		// --------------------------------------------------
+
+		std::map<std::vector<alphabet::Symbol>, std::set<std::variant<alphabet::Symbol, string::Epsilon>>> firstAlgo;
+
+		for(const auto& rule : grammar.getRawRules())
+			for(const auto& rhs : rule.second)
+				firstAlgo[rhs] = grammar::parsing::First::first(grammar, rhs);
+
+		CPPUNIT_ASSERT(first == firstAlgo);
+	}
+}
+
diff --git a/alib2algo/test-src/grammar/parsing/FirstTest.h b/alib2algo/test-src/grammar/parsing/FirstTest.h
new file mode 100644
index 0000000000000000000000000000000000000000..5bb36cef0f8b7bf193d35c799568ab92e6961eba
--- /dev/null
+++ b/alib2algo/test-src/grammar/parsing/FirstTest.h
@@ -0,0 +1,19 @@
+#ifndef FIRST_TEST_H_
+#define FIRST_TEST_H_
+
+#include <cppunit/extensions/HelperMacros.h>
+
+class FirstTest : public CppUnit::TestFixture
+{
+  CPPUNIT_TEST_SUITE( FirstTest );
+  CPPUNIT_TEST( testFirst );
+  CPPUNIT_TEST_SUITE_END();
+
+public:
+  void setUp();
+  void tearDown();
+
+  void testFirst();
+};
+
+#endif /* FIRST_TEST_H_ */
diff --git a/alib2algo/test-src/grammar/parsing/FollowTest.cpp b/alib2algo/test-src/grammar/parsing/FollowTest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..fb2c2eb95045f99581a042ab4fa70ef458fc6214
--- /dev/null
+++ b/alib2algo/test-src/grammar/parsing/FollowTest.cpp
@@ -0,0 +1,137 @@
+#include "FollowTest.h"
+
+#include "grammar/parsing/Follow.h"
+#include "string/Epsilon.h"
+
+CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( FollowTest, "grammar" );
+CPPUNIT_TEST_SUITE_REGISTRATION( FollowTest );
+
+void FollowTest::setUp() {
+}
+
+void FollowTest::tearDown() {
+}
+
+void FollowTest::testFollow() {
+	{
+		alphabet::Symbol nE = alphabet::symbolFrom('E');
+		alphabet::Symbol nT = alphabet::symbolFrom('T');
+		alphabet::Symbol nF = alphabet::symbolFrom('F');
+
+		alphabet::Symbol tP = alphabet::symbolFrom('+');
+		alphabet::Symbol tS = alphabet::symbolFrom('*');
+		alphabet::Symbol tL = alphabet::symbolFrom('(');
+		alphabet::Symbol tR = alphabet::symbolFrom(')');
+		alphabet::Symbol tA = alphabet::symbolFrom('a');
+
+		grammar::CFG grammar(nE);
+		grammar.setTerminalAlphabet(std::set<alphabet::Symbol>{tP, tS, tL, tR, tA});
+		grammar.setNonterminalAlphabet(std::set<alphabet::Symbol>{nE, nT, nF});
+
+		std::vector<alphabet::Symbol> rhsE1({nE, tP, nT});
+		std::vector<alphabet::Symbol> rhsE2({nT});
+		std::vector<alphabet::Symbol> rhsT1({nT, tS, nF});
+		std::vector<alphabet::Symbol> rhsT2({nF});
+		std::vector<alphabet::Symbol> rhsF1({tA});
+		std::vector<alphabet::Symbol> rhsF2({tL, nE, tR});
+
+		grammar.addRule(nE, rhsE1);
+		grammar.addRule(nE, rhsE2);
+		grammar.addRule(nT, rhsT1);
+		grammar.addRule(nT, rhsT2);
+		grammar.addRule(nF, rhsF1);
+		grammar.addRule(nF, rhsF2);
+
+		// --------------------------------------------------
+		std::map<alphabet::Symbol, std::set<std::variant<alphabet::Symbol, string::Epsilon>>> follow;
+
+		follow[nE] = std::set<std::variant<alphabet::Symbol, string::Epsilon>>{string::Epsilon::EPSILON, tP, tR};
+		follow[nT] = std::set<std::variant<alphabet::Symbol, string::Epsilon>>{string::Epsilon::EPSILON, tP, tR, tS};
+		follow[nF] = std::set<std::variant<alphabet::Symbol, string::Epsilon>>{string::Epsilon::EPSILON, tP, tR, tS};
+
+		// --------------------------------------------------
+
+		std::map<alphabet::Symbol, std::set<std::variant<alphabet::Symbol, string::Epsilon>>> followAlgo;
+
+		for(const auto& nt : grammar.getNonterminalAlphabet())
+			followAlgo[nt] = grammar::parsing::Follow::follow(grammar, nt);
+
+		// std::cout << follow << std::endl;
+		// std::cout << followAlgo << std::endl;
+		CPPUNIT_ASSERT(follow == followAlgo);
+	}
+
+	{
+		alphabet::Symbol nS = alphabet::symbolFrom('S');
+		alphabet::Symbol nA = alphabet::symbolFrom('A');
+		alphabet::Symbol nB = alphabet::symbolFrom('B');
+		alphabet::Symbol nC = alphabet::symbolFrom('C');
+		alphabet::Symbol nD = alphabet::symbolFrom('D');
+		alphabet::Symbol nE = alphabet::symbolFrom('E');
+		alphabet::Symbol nF = alphabet::symbolFrom('F');
+
+		alphabet::Symbol tA = alphabet::symbolFrom('a');
+		alphabet::Symbol tB = alphabet::symbolFrom('b');
+		alphabet::Symbol tC = alphabet::symbolFrom('c');
+		alphabet::Symbol tD = alphabet::symbolFrom('d');
+		alphabet::Symbol tE = alphabet::symbolFrom('e');
+
+		grammar::CFG grammar(nS);
+		grammar.setTerminalAlphabet(std::set<alphabet::Symbol>{tA, tB, tC, tD, tE});
+		grammar.setNonterminalAlphabet(std::set<alphabet::Symbol>{nS, nA, nB, nC, nD, nE, nF});
+
+		std::vector<alphabet::Symbol> rhsS1({nB, tD, nS});
+		std::vector<alphabet::Symbol> rhsS2({tD, tD, nC});
+		std::vector<alphabet::Symbol> rhsS3({tC, nA});
+		std::vector<alphabet::Symbol> rhsA1({tA, tE, nE});
+		std::vector<alphabet::Symbol> rhsA2({tB, tB, nE});
+		std::vector<alphabet::Symbol> rhsB1({tA, nF});
+		std::vector<alphabet::Symbol> rhsB2({tB, tB, nD});
+		std::vector<alphabet::Symbol> rhsC1({tA, nB, tD});
+		std::vector<alphabet::Symbol> rhsC2({tE, nA});
+		std::vector<alphabet::Symbol> rhsD1({tC, tA, nF});
+		std::vector<alphabet::Symbol> rhsE1({tC, tA, tE, nE});
+		std::vector<alphabet::Symbol> rhsE2({});
+		std::vector<alphabet::Symbol> rhsF1({tE, nD});
+		std::vector<alphabet::Symbol> rhsF2({});
+
+		grammar.addRule(nS, rhsS1);
+		grammar.addRule(nS, rhsS2);
+		grammar.addRule(nS, rhsS3);
+		grammar.addRule(nA, rhsA1);
+		grammar.addRule(nA, rhsA2);
+		grammar.addRule(nB, rhsB1);
+		grammar.addRule(nB, rhsB2);
+		grammar.addRule(nC, rhsC1);
+		grammar.addRule(nC, rhsC2);
+		grammar.addRule(nD, rhsD1);
+		grammar.addRule(nE, rhsE1);
+		grammar.addRule(nE, rhsE2);
+		grammar.addRule(nF, rhsF1);
+		grammar.addRule(nF, rhsF2);
+
+		// --------------------------------------------------
+		std::map<alphabet::Symbol, std::set<std::variant<alphabet::Symbol, string::Epsilon>>> follow;
+
+		follow[nS] = std::set<std::variant<alphabet::Symbol, string::Epsilon>>{string::Epsilon::EPSILON};
+		follow[nA] = std::set<std::variant<alphabet::Symbol, string::Epsilon>>{string::Epsilon::EPSILON};
+		follow[nB] = std::set<std::variant<alphabet::Symbol, string::Epsilon>>{tD};
+		follow[nC] = std::set<std::variant<alphabet::Symbol, string::Epsilon>>{string::Epsilon::EPSILON};
+		follow[nD] = std::set<std::variant<alphabet::Symbol, string::Epsilon>>{tD};
+		follow[nE] = std::set<std::variant<alphabet::Symbol, string::Epsilon>>{string::Epsilon::EPSILON};
+		follow[nF] = std::set<std::variant<alphabet::Symbol, string::Epsilon>>{tD};
+
+		// --------------------------------------------------
+
+		std::map<alphabet::Symbol, std::set<std::variant<alphabet::Symbol, string::Epsilon>>> followAlgo;
+
+		for(const auto& nt : grammar.getNonterminalAlphabet())
+			followAlgo[nt] = grammar::parsing::Follow::follow(grammar, nt);
+
+		// std::cout << follow << std::endl;
+		// std::cout << followAlgo << std::endl;
+		CPPUNIT_ASSERT(follow == followAlgo);
+
+	}
+}
+
diff --git a/alib2algo/test-src/grammar/parsing/FollowTest.h b/alib2algo/test-src/grammar/parsing/FollowTest.h
new file mode 100644
index 0000000000000000000000000000000000000000..aa992d4afae4a9a7a75ab0c5f367373887830804
--- /dev/null
+++ b/alib2algo/test-src/grammar/parsing/FollowTest.h
@@ -0,0 +1,19 @@
+#ifndef FOLLOW_TEST_H_
+#define FOLLOW_TEST_H_
+
+#include <cppunit/extensions/HelperMacros.h>
+
+class FollowTest : public CppUnit::TestFixture
+{
+  CPPUNIT_TEST_SUITE( FollowTest );
+  CPPUNIT_TEST( testFollow );
+  CPPUNIT_TEST_SUITE_END();
+
+public:
+  void setUp();
+  void tearDown();
+
+  void testFollow();
+};
+
+#endif /* FOLLOW_TEST_H_ */