diff --git a/agenerate2/src/agenerate.cpp b/agenerate2/src/agenerate.cpp
index b2ed27a49deaf3dd06be06e9be96e78aef1e6782..ce3c41283176d293656ebdd7b4fe4b5980bc6c2e 100644
--- a/agenerate2/src/agenerate.cpp
+++ b/agenerate2/src/agenerate.cpp
@@ -14,22 +14,35 @@
 #include <string/LinearString.h>
 #include <grammar/Grammar.h>
 #include <grammar/generate/GenerateUpToLength.h>
+#include <grammar/generate/CockeYoungerKasami.h>
 #include <container/ObjectsSet.h>
+#include <primitive/Bool.h>
 
 int main(int argc, char* argv[]) {
 	try {
 		TCLAP::CmdLine cmd("String generate from grammar", ' ', "0.01");
 
-		TCLAP::ValueArg<unsigned> upto(	"",	"upto",		"Generate all strings up to length",		false,	5, "unsigned");
+		std::vector<std::string> allowed;
+		allowed.push_back("upTo");
+		allowed.push_back("CYK");
+		TCLAP::ValuesConstraint<std::string> allowedVals( allowed );
+
+		TCLAP::ValueArg<std::string> type(	"t",	"type",		"Run type",		false,	"accept",	&allowedVals);
+		cmd.add( type );
+
+		TCLAP::ValueArg<unsigned> upto(		"",	"upto",		"Generate all strings up to length",	false,	5, "unsigned");
 		cmd.add( upto );
 
+		TCLAP::ValueArg<std::string> string(	"s",	"string",	"String from file",	false,	"-",		"file");
+		cmd.add( string );
+
 		TCLAP::ValueArg<std::string> grammar(	"g",	"grammar",	"Grammar to use",	false,	"-",		"file");
 		cmd.add( grammar );
 
-		TCLAP::SwitchArg measure(		"m",	"measure",	"Measure times",		false);
+		TCLAP::SwitchArg measure(		"m",	"measure",	"Measure times",	false);
 		cmd.add( measure );
 
-		TCLAP::SwitchArg verbose(		"v",	"verbose",	"Be verbose",			false);
+		TCLAP::SwitchArg verbose(		"v",	"verbose",	"Be verbose",		false);
 		cmd.add( verbose );
 
 		cmd.parse(argc, argv);
@@ -42,6 +55,15 @@ int main(int argc, char* argv[]) {
 		std::chrono::measurements::start("Overal", std::chrono::measurements::Type::OVERALL);
 		std::chrono::measurements::start("Input read", std::chrono::measurements::Type::AUXILARY);
 
+		std::deque<sax::Token> stringTokens;
+		if(string.isSet()) {
+			if(string.getValue() == "-") {
+				sax::SaxParseInterface::parseStdin(stringTokens);
+			} else {
+				sax::SaxParseInterface::parseFile(string.getValue(), stringTokens);
+			}
+		}
+
 		std::deque<sax::Token> grammarTokens;
 		if(grammar.isSet()) {
 			if(grammar.getValue() == "-") {
@@ -53,7 +75,7 @@ int main(int argc, char* argv[]) {
 			sax::SaxParseInterface::parseStdin(grammarTokens);
 		}
 
-		if( upto.isSet() ) {
+		if( type.getValue() == "upTo" && upto.isSet() ) {
 			grammar::Grammar grammar = alib::XmlDataFactory::fromTokens<grammar::Grammar>(grammarTokens);
 
 			std::chrono::measurements::end();
@@ -64,6 +86,19 @@ int main(int argc, char* argv[]) {
 			std::chrono::measurements::end();
 			std::chrono::measurements::start("Output write", std::chrono::measurements::Type::AUXILARY);
 
+			alib::XmlDataFactory::toStdout( res );
+		} else if ( type.getValue() == "CYK" ) {
+			grammar::Grammar grammar = alib::XmlDataFactory::fromTokens<grammar::Grammar>(grammarTokens);
+			string::LinearString string = alib::XmlDataFactory::fromTokens<string::LinearString>(stringTokens);
+
+			std::chrono::measurements::end();
+			std::chrono::measurements::start("Algorithm", std::chrono::measurements::Type::MAIN);
+
+			bool res = grammar::generate::CockeYoungerKasami::generate(grammar, string);
+
+			std::chrono::measurements::end();
+			std::chrono::measurements::start("Output write", std::chrono::measurements::Type::AUXILARY);
+
 			alib::XmlDataFactory::toStdout( res );
 		} else {
 			throw exception::AlibException( "Invalid run type" );
diff --git a/alib2algo/src/grammar/generate/CockeYoungerKasami.cpp b/alib2algo/src/grammar/generate/CockeYoungerKasami.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f08df75f1b6af8f39b97eb1d884bdc20f5137583
--- /dev/null
+++ b/alib2algo/src/grammar/generate/CockeYoungerKasami.cpp
@@ -0,0 +1,92 @@
+/*
+ * CockeYoungerKasami.cpp
+ *
+ *  Created on: 22. 3. 2014
+ *	  Author: Jan Travnicek
+ */
+
+#include "CockeYoungerKasami.h"
+#include <common/GlobalData.h>
+
+namespace grammar {
+
+namespace generate {
+
+bool CockeYoungerKasami::generate( const grammar::CNF & grammar, const string::LinearString & string ) {
+	unsigned stringSize = string.getContent().size();
+
+	if(stringSize == 0 && grammar.getGeneratesEpsilon()) return true;
+
+	std::vector<std::vector<std::set<alphabet::Symbol>>> data;
+	data.resize(stringSize);
+	for(unsigned i = 0; i < stringSize; i++) {
+		data[i].resize(stringSize - i);
+	}
+
+	for(unsigned i = 0; i < stringSize; i++) {
+		for( const std::pair < alphabet::Symbol, std::set < std::variant < alphabet::Symbol, std::pair < alphabet::Symbol, alphabet::Symbol > > > > rule : grammar.getRules ( ) ) {
+			const alphabet::Symbol & lhs = rule.first;
+
+			for( const std::variant < alphabet::Symbol, std::pair < alphabet::Symbol, alphabet::Symbol > > rhs : rule.second ) {
+				if( rhs.is< alphabet::Symbol >() && rhs.get< alphabet::Symbol >() == string.getContent()[i]) {
+					data[0][i].insert(lhs);
+				}
+			}
+		}
+	}
+
+	for(unsigned i = 1; i < stringSize; i++) {
+		for(unsigned j = 0; j < stringSize - i; j++) {
+			std::set<alphabet::Symbol> & targetCell = data[i][j]; //Element to compute
+
+			for(unsigned k = 0; k < i; k++) {
+				const std::set<alphabet::Symbol> & vertical = data[k][j];
+				const std::set<alphabet::Symbol> & diagonal = data[i - 1 - k][j + 1 + k]; // Sources of data
+
+				for(const alphabet::Symbol & verticalElement : vertical) {
+					for(const alphabet::Symbol & diagonalElement : diagonal) {
+
+						for( const std::pair < alphabet::Symbol, std::set < std::variant < alphabet::Symbol, std::pair < alphabet::Symbol, alphabet::Symbol > > > > rule : grammar.getRules ( ) ) {
+							const alphabet::Symbol & lhs = rule.first;
+
+							for( const std::variant < alphabet::Symbol, std::pair < alphabet::Symbol, alphabet::Symbol > > rhs : rule.second ) {
+								if( rhs.is< std::pair<alphabet::Symbol, alphabet::Symbol > >() ) {
+									const std::pair<alphabet::Symbol, alphabet::Symbol > rhsp = rhs.get< std::pair<alphabet::Symbol, alphabet::Symbol > >();
+
+									if(rhsp.first == verticalElement && rhsp.second == diagonalElement ) {
+										targetCell.insert(lhs);
+									}
+								}
+							}
+
+						}
+
+					}
+				}
+
+			}
+
+		}
+	}
+
+	if ( common::GlobalData::verbose )
+		for(const std::vector<std::set<alphabet::Symbol>> & row : data) {
+			for( const std::set<alphabet::Symbol>& element : row) {
+				std::clog << element << " ";
+			}
+			std::clog << std::endl;
+		}
+
+	return data[stringSize - 1][0].count(grammar.getInitialSymbol());
+}
+
+auto CockeYoungerKasamiCNF = CockeYoungerKasami::RegistratorWrapper<bool, grammar::CNF>(CockeYoungerKasami::getInstance(), CockeYoungerKasami::generate);
+
+bool CockeYoungerKasami::generate(const grammar::Grammar& grammar, const string::LinearString & string) {
+	return getInstance().dispatch(grammar.getData(), string);
+}
+
+} /* namespace generate */
+
+} /* namespace grammar */
+
diff --git a/alib2algo/src/grammar/generate/CockeYoungerKasami.h b/alib2algo/src/grammar/generate/CockeYoungerKasami.h
new file mode 100644
index 0000000000000000000000000000000000000000..8f49af3a648ddce9b57de457923f008d91e69535
--- /dev/null
+++ b/alib2algo/src/grammar/generate/CockeYoungerKasami.h
@@ -0,0 +1,40 @@
+/*
+ * CockeYoungerKasami.h
+ *
+ *  Created on: 22. 3. 2014
+ *	  Author: Jan Travnicek
+ */
+
+#ifndef COCKE_YOUNGER_KASAMI_H_
+#define COCKE_YOUNGER_KASAMI_H_
+
+#include <common/multipleDispatch.hpp>
+
+#include <grammar/Grammar.h>
+#include <grammar/ContextFree/CNF.h>
+#include <string/LinearString.h>
+
+namespace grammar {
+
+namespace generate {
+
+/**
+ * Implements algorithms from Melichar, chapter 3.3
+ */
+class CockeYoungerKasami : public std::SingleDispatchLastStaticParam<bool, grammar::GrammarBase, const string::LinearString &> {
+public:
+	static bool generate( const grammar::Grammar & grammar, const string::LinearString & string );
+
+	static bool generate( const grammar::CNF & grammar, const string::LinearString & string );
+
+	static CockeYoungerKasami& getInstance() {
+		static CockeYoungerKasami res;
+		return res;
+	}
+};
+
+} /* namespace generate */
+
+} /* namespace grammar */
+
+#endif /* COCKE_YOUNGER_KASAMI_H_ */
diff --git a/examples2/grammar/contextFree1-4.txt b/examples2/grammar/contextFree1-4.txt
new file mode 100644
index 0000000000000000000000000000000000000000..937ed0bfee9d59568ca51dc1278a86aa55581706
--- /dev/null
+++ b/examples2/grammar/contextFree1-4.txt
@@ -0,0 +1,10 @@
+CFG (
+{'A', 'B', 'C', 'D', 'E'},
+{'a', 'b'},
+{'A' -> 'b' | 'A' 'B' | 'a',
+'B' -> 'A' 'C',
+'C' -> 'a' 'E' 'D',
+'D' -> 'a' | 'B' 'E',
+'E' -> 'B' 'A' | 'b' |
+},
+'E')
diff --git a/tests.anormalize.sh b/tests.anormalize.sh
index 52f990d9e6b7f0f93b3677fe88b422acc2134d00..4a8617fafa0ee2e85a924a2928f8dcc8db52ac52 100755
--- a/tests.anormalize.sh
+++ b/tests.anormalize.sh
@@ -57,7 +57,7 @@ function generateCFG {
 # $1 = command for conversion. Output of such command must be a grammar !!
 # $2 = original grammar
 function runTest2 {
-	GENERATED_STRINGS="./agenerate2 --upto $STRING_LENGHTS"
+	GENERATED_STRINGS="./agenerate2 -t upTo --upto $STRING_LENGHTS"
 
 	OUT=`timeout $TESTCASE_TIMEOUT bash -c "diff <(cat $2 | $1 | $GENERATED_STRINGS ) <(cat $2 | $GENERATED_STRINGS)"`
 	RET=$?