/*
 * CockeYoungerKasami.h
 *
 *  Created on: 22. 3. 2014
 *	  Author: Jan Travnicek
 */

#ifndef COCKE_YOUNGER_KASAMI_H_
#define COCKE_YOUNGER_KASAMI_H_

#include <global/GlobalData.h>

#include <grammar/ContextFree/CNF.h>
#include <string/LinearString.h>
#include <grammar/generate/CockeYoungerKasamiVerbose.h>

namespace grammar {

namespace generate {

/**
 * Implements the Cocke Younger Kasami algorithm.
 */
class CockeYoungerKasami {
public:
	/**
	 * Implements the Cocke Younger Kasami algorithm to test whether string is in language generated by a grammar
	 *
	 * \tparam TerminalSymbolType the type of terminal symbol of the grammar
	 * \tparam NonterminalSymbolType the type of nonterminal symbol of the grammar
	 *
	 * \param grammar context free grammar in chomsky's normal form.
	 * \param string the tested string
	 *
	 * \return true if the @p grammar generates a language containing @p string
	 */
	template < class TerminalSymbolType, class NonterminalSymbolType >
	static bool generate ( const grammar::CNF < TerminalSymbolType, NonterminalSymbolType > & grammar, const string::LinearString < TerminalSymbolType > & string );

};

template < class TerminalSymbolType, class NonterminalSymbolType >
bool CockeYoungerKasami::generate ( const grammar::CNF < TerminalSymbolType, NonterminalSymbolType > & grammar, const string::LinearString < TerminalSymbolType > & string ) {
	unsigned stringSize = string.getContent ( ).size ( );

	if ( ( stringSize == 0 ) && grammar.getGeneratesEpsilon ( ) ) return true;

	ext::vector < ext::vector < ext::set < NonterminalSymbolType > > > data = CockeYoungerKasamiVerbose::generate ( grammar, string );

	return data[stringSize - 1][0].count ( grammar.getInitialSymbol ( ) );
}

} /* namespace generate */

} /* namespace grammar */

#endif /* COCKE_YOUNGER_KASAMI_H_ */
