diff --git a/alib2algo/src/grammar/generate/CockeYoungerKasami.cpp b/alib2algo/src/grammar/generate/CockeYoungerKasami.cpp index d3b4a0383991973c9d5c9b07d132d3c746fba001..44bf5ef80ee14645ade454c807d6abed64b35f00 100644 --- a/alib2algo/src/grammar/generate/CockeYoungerKasami.cpp +++ b/alib2algo/src/grammar/generate/CockeYoungerKasami.cpp @@ -12,7 +12,12 @@ namespace grammar { namespace generate { -auto CockeYoungerKasamiCNF = registration::AbstractRegister < CockeYoungerKasami, bool, const grammar::CNF < > &, const string::LinearString < > & > ( CockeYoungerKasami::generate ); +auto CockeYoungerKasamiCNF = registration::AbstractRegister < CockeYoungerKasami, bool, const grammar::CNF < > &, const string::LinearString < > & > ( CockeYoungerKasami::generate, "grammar", "string" ).setDocumentation ( +"Implements the Cocke Younger Kasami algorithm to test whether string is in language generated by a grammar\n\ +\n\ +@param grammar context free grammar in chomsky's normal form.\n\ +@param string the tested string\n\ +@return true if the @p grammar generates a language containing @p string" ); } /* namespace generate */ diff --git a/alib2algo/src/grammar/generate/CockeYoungerKasami.h b/alib2algo/src/grammar/generate/CockeYoungerKasami.h index 16ac57768d8041cc77673b44c2a8eb444c95753f..7b75c4973d6783097872d1d51dc1dc8bbda89c77 100644 --- a/alib2algo/src/grammar/generate/CockeYoungerKasami.h +++ b/alib2algo/src/grammar/generate/CockeYoungerKasami.h @@ -12,16 +12,28 @@ #include <grammar/ContextFree/CNF.h> #include <string/LinearString.h> +#include <grammar/generate/CockeYoungerKasamiVerbose.h> namespace grammar { namespace generate { /** - * Implements algorithms from Melichar, chapter 3.3 + * 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 ); @@ -33,59 +45,7 @@ bool CockeYoungerKasami::generate ( const grammar::CNF < TerminalSymbolType, Non if ( ( stringSize == 0 ) && grammar.getGeneratesEpsilon ( ) ) return true; - ext::vector < ext::vector < ext::set < NonterminalSymbolType > > > 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 < const NonterminalSymbolType, ext::set < ext::variant < TerminalSymbolType, ext::pair < NonterminalSymbolType, NonterminalSymbolType > > > > rule : grammar.getRules ( ) ) { - const NonterminalSymbolType & lhs = rule.first; - - for ( const ext::variant < TerminalSymbolType, ext::pair < NonterminalSymbolType, NonterminalSymbolType > > rhs : rule.second ) - if ( rhs.template is < TerminalSymbolType > ( ) && ( rhs.template get < TerminalSymbolType > ( ) == string.getContent ( )[i] ) ) - data[0][i].insert ( lhs ); - - } - - for ( unsigned i = 1; i < stringSize; i++ ) - for ( unsigned j = 0; j < stringSize - i; j++ ) { - ext::set < NonterminalSymbolType > & targetCell = data[i][j]; // Element to compute - - for ( unsigned k = 0; k < i; k++ ) { - const ext::set < NonterminalSymbolType > & vertical = data[k][j]; - const ext::set < NonterminalSymbolType > & diagonal = data[i - 1 - k][j + 1 + k]; // Sources of data - - for ( const NonterminalSymbolType & verticalElement : vertical ) { - for ( const NonterminalSymbolType & diagonalElement : diagonal ) - - for ( const std::pair < const NonterminalSymbolType, ext::set < ext::variant < TerminalSymbolType, ext::pair < NonterminalSymbolType, NonterminalSymbolType > > > > rule : grammar.getRules ( ) ) { - const NonterminalSymbolType & lhs = rule.first; - - for ( const ext::variant < TerminalSymbolType, ext::pair < NonterminalSymbolType, NonterminalSymbolType > > rhs : rule.second ) - if ( rhs.template is < ext::pair < NonterminalSymbolType, NonterminalSymbolType > > ( ) ) { - const ext::pair < NonterminalSymbolType, NonterminalSymbolType > rhsp = rhs.template get < ext::pair < NonterminalSymbolType, NonterminalSymbolType > > ( ); - - if ( ( rhsp.first == verticalElement ) && ( rhsp.second == diagonalElement ) ) - targetCell.insert ( lhs ); - } - - } - - } - } - } - - - - if ( common::GlobalData::verbose ) - for ( const ext::vector < ext::set < NonterminalSymbolType > > & row : data ) { - for ( const ext::set < NonterminalSymbolType > & element : row ) - common::Streams::log << element << " "; - - common::Streams::log << std::endl; - } + ext::vector < ext::vector < ext::set < NonterminalSymbolType > > > data = CockeYoungerKasamiVerbose::generate ( grammar, string ); return data[stringSize - 1][0].count ( grammar.getInitialSymbol ( ) ); } diff --git a/alib2algo/src/grammar/generate/CockeYoungerKasamiVerbose.cpp b/alib2algo/src/grammar/generate/CockeYoungerKasamiVerbose.cpp index 7a9dc7ec32a19d9135ed32796850f792825aee9d..9fd8d3e440000b3c9b10c00fb3d790030eb4cb2d 100644 --- a/alib2algo/src/grammar/generate/CockeYoungerKasamiVerbose.cpp +++ b/alib2algo/src/grammar/generate/CockeYoungerKasamiVerbose.cpp @@ -12,7 +12,12 @@ namespace grammar { namespace generate { -auto CockeYoungerKasamiVerboseCNF = registration::AbstractRegister < CockeYoungerKasamiVerbose, ext::vector < ext::vector < ext::set < DefaultSymbolType > > >, const grammar::CNF < > &, const string::LinearString < > & > ( CockeYoungerKasamiVerbose::generate ); +auto CockeYoungerKasamiVerboseCNF = registration::AbstractRegister < CockeYoungerKasamiVerbose, ext::vector < ext::vector < ext::set < DefaultSymbolType > > >, const grammar::CNF < > &, const string::LinearString < > & > ( CockeYoungerKasamiVerbose::generate, "grammar", "string" ).setDocumentation ( +"Implements the Cocke Younger Kasami algorithm to test whether string is in language generated by a grammar.\n\ +\n\ +@param grammar context free grammar in chomsky's normal form\n\ +@param string the tested string\n\ +@return the internal table constructed by the Cock Younger Kasami algorithm" ); } /* namespace generate */ diff --git a/alib2algo/src/grammar/generate/CockeYoungerKasamiVerbose.h b/alib2algo/src/grammar/generate/CockeYoungerKasamiVerbose.h index a70aa96c05300ec8536b4c74fb59248de676cd69..721a17c4c1fcf9558e58f997ad8750c0c1a60fc4 100644 --- a/alib2algo/src/grammar/generate/CockeYoungerKasamiVerbose.h +++ b/alib2algo/src/grammar/generate/CockeYoungerKasamiVerbose.h @@ -18,10 +18,21 @@ namespace grammar { namespace generate { /** - * Implements algorithms from Melichar, chapter 3.3 + * Implements the Cocke Younger Kasami algorithm. */ class CockeYoungerKasamiVerbose { public: + /** + * Implements the Cocke Younger Kasami algorithm to test whether string is in language generated by a grammar. This version returns the internal data structures. + * + * \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 the internal table constructed by the Cock Younger Kasami algorithm + */ template < class TerminalSymbolType, class NonterminalSymbolType > static ext::vector < ext::vector < ext::set < NonterminalSymbolType > > > generate ( const grammar::CNF < TerminalSymbolType, NonterminalSymbolType > & grammar, const string::LinearString < TerminalSymbolType > & string );