Skip to content
Snippets Groups Projects
Commit 10444ab6 authored by Jan Trávníček's avatar Jan Trávníček
Browse files

template properties retrieving algorithms

parent 625f3923
No related branches found
No related tags found
No related merge requests found
Showing
with 289 additions and 268 deletions
...@@ -7,25 +7,12 @@ ...@@ -7,25 +7,12 @@
   
#include "IsLanguageEmpty.h" #include "IsLanguageEmpty.h"
   
#include <grammar/ContextFree/CFG.h>
#include <grammar/ContextFree/EpsilonFreeCFG.h>
#include <grammar/ContextFree/GNF.h>
#include <grammar/ContextFree/CNF.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 "../properties/ProductiveNonterminals.h"
namespace grammar { namespace grammar {
   
namespace properties { namespace properties {
   
template<class T> bool IsLanguageEmpty::isLanguageEmpty(const grammar::Grammar& grammar) {
bool IsLanguageEmpty::isLanguageEmpty( const T & grammar ) { return dispatch(grammar.getData());
return grammar::properties::ProductiveNonterminals::getProductiveNonterminals( grammar ).count( grammar.getInitialSymbol( ) );
} }
   
auto IsLanguageEmptyCFG = IsLanguageEmpty::RegistratorWrapper<bool, grammar::CFG < > >(IsLanguageEmpty::isLanguageEmpty); auto IsLanguageEmptyCFG = IsLanguageEmpty::RegistratorWrapper<bool, grammar::CFG < > >(IsLanguageEmpty::isLanguageEmpty);
......
...@@ -12,6 +12,18 @@ ...@@ -12,6 +12,18 @@
   
#include <grammar/Grammar.h> #include <grammar/Grammar.h>
   
#include <grammar/ContextFree/CFG.h>
#include <grammar/ContextFree/EpsilonFreeCFG.h>
#include <grammar/ContextFree/GNF.h>
#include <grammar/ContextFree/CNF.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 <grammar/properties/ProductiveNonterminals.h>
namespace grammar { namespace grammar {
   
namespace properties { namespace properties {
...@@ -33,6 +45,11 @@ public: ...@@ -33,6 +45,11 @@ public:
static bool isLanguageEmpty( const T & grammar ); static bool isLanguageEmpty( const T & grammar );
}; };
   
template<class T>
bool IsLanguageEmpty::isLanguageEmpty( const T & grammar ) {
return grammar::properties::ProductiveNonterminals::getProductiveNonterminals( grammar ).count( grammar.getInitialSymbol( ) );
}
} /* namespace properties */ } /* namespace properties */
   
} /* namespace grammar */ } /* namespace grammar */
......
...@@ -7,25 +7,12 @@ ...@@ -7,25 +7,12 @@
   
#include "IsLanguageGeneratingEpsilon.h" #include "IsLanguageGeneratingEpsilon.h"
   
#include <grammar/ContextFree/CFG.h>
#include <grammar/ContextFree/EpsilonFreeCFG.h>
#include <grammar/ContextFree/GNF.h>
#include <grammar/ContextFree/CNF.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 "../properties/NullableNonterminals.h"
namespace grammar { namespace grammar {
   
namespace properties { namespace properties {
   
template<class T> bool IsLanguageGeneratingEpsilon::isLanguageGeneratingEpsilon(const grammar::Grammar& grammar) {
bool IsLanguageGeneratingEpsilon::isLanguageGeneratingEpsilon( const T & grammar ) { return dispatch(grammar.getData());
return grammar::properties::NullableNonterminals::getNullableNonterminals( grammar ).count( grammar.getInitialSymbol( ) );
} }
   
auto IsLanguageGeneratingEpsilonCFG = IsLanguageGeneratingEpsilon::RegistratorWrapper<bool, grammar::CFG < > >(IsLanguageGeneratingEpsilon::isLanguageGeneratingEpsilon); auto IsLanguageGeneratingEpsilonCFG = IsLanguageGeneratingEpsilon::RegistratorWrapper<bool, grammar::CFG < > >(IsLanguageGeneratingEpsilon::isLanguageGeneratingEpsilon);
......
...@@ -12,6 +12,18 @@ ...@@ -12,6 +12,18 @@
   
#include <grammar/Grammar.h> #include <grammar/Grammar.h>
   
#include <grammar/ContextFree/CFG.h>
#include <grammar/ContextFree/EpsilonFreeCFG.h>
#include <grammar/ContextFree/GNF.h>
#include <grammar/ContextFree/CNF.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 <grammar/properties/NullableNonterminals.h>
namespace grammar { namespace grammar {
   
namespace properties { namespace properties {
...@@ -33,6 +45,11 @@ public: ...@@ -33,6 +45,11 @@ public:
static bool isLanguageGeneratingEpsilon( const T & grammar ); static bool isLanguageGeneratingEpsilon( const T & grammar );
}; };
   
template<class T>
bool IsLanguageGeneratingEpsilon::isLanguageGeneratingEpsilon( const T & grammar ) {
return grammar::properties::NullableNonterminals::getNullableNonterminals( grammar ).count( grammar.getInitialSymbol( ) );
}
} /* namespace properties */ } /* namespace properties */
   
} /* namespace grammar */ } /* namespace grammar */
......
...@@ -7,56 +7,10 @@ ...@@ -7,56 +7,10 @@
   
#include "NonterminalUnitRuleCycle.h" #include "NonterminalUnitRuleCycle.h"
   
#include <grammar/ContextFree/CFG.h>
#include <grammar/ContextFree/EpsilonFreeCFG.h>
#include <grammar/ContextFree/GNF.h>
#include <grammar/ContextFree/CNF.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 <set>
#include <deque>
#include <exception/CommonException.h>
namespace grammar { namespace grammar {
   
namespace properties { namespace properties {
   
template<class T>
std::set<alphabet::Symbol> NonterminalUnitRuleCycle::getNonterminalUnitRuleCycle(const T& grammar, const alphabet::Symbol& nonterminal) {
if(grammar.getNonterminalAlphabet().count(nonterminal) == 0) {
throw exception::CommonException("Nonterminal symbol \"" + (std::string) nonterminal + "\" is not present in grammar.");
}
std::deque<std::set<alphabet::Symbol>> Ni;
Ni.push_back(std::set<alphabet::Symbol>{nonterminal});
int i = 1;
while(true) {
Ni.push_back(Ni.at(i-1));
for(const auto&rule : grammar.getRawRules()) {
const alphabet::Symbol& lhs = rule.first;
for(const auto& rhs : rule.second) {
if(Ni.at(i-1).count(lhs) && rhs.size() == 1 && grammar.getNonterminalAlphabet().count(rhs.front())) {
Ni.at(i).insert(rhs.front());
}
}
}
if(Ni.at(i) == Ni.at(i-1))
break;
i += 1;
}
return Ni.at(i);
}
auto NonterminalUnitRuleCycleCFG = NonterminalUnitRuleCycle::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::CFG < > >(NonterminalUnitRuleCycle::getNonterminalUnitRuleCycle); auto NonterminalUnitRuleCycleCFG = NonterminalUnitRuleCycle::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::CFG < > >(NonterminalUnitRuleCycle::getNonterminalUnitRuleCycle);
auto NonterminalUnitRuleCycleEpsilonFreeCFG = NonterminalUnitRuleCycle::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::EpsilonFreeCFG < > >(NonterminalUnitRuleCycle::getNonterminalUnitRuleCycle); auto NonterminalUnitRuleCycleEpsilonFreeCFG = NonterminalUnitRuleCycle::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::EpsilonFreeCFG < > >(NonterminalUnitRuleCycle::getNonterminalUnitRuleCycle);
auto NonterminalUnitRuleCycleGNF = NonterminalUnitRuleCycle::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::GNF < > >(NonterminalUnitRuleCycle::getNonterminalUnitRuleCycle); auto NonterminalUnitRuleCycleGNF = NonterminalUnitRuleCycle::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::GNF < > >(NonterminalUnitRuleCycle::getNonterminalUnitRuleCycle);
......
...@@ -13,6 +13,21 @@ ...@@ -13,6 +13,21 @@
#include <grammar/Grammar.h> #include <grammar/Grammar.h>
#include <alphabet/Symbol.h> #include <alphabet/Symbol.h>
   
#include <grammar/ContextFree/CFG.h>
#include <grammar/ContextFree/EpsilonFreeCFG.h>
#include <grammar/ContextFree/GNF.h>
#include <grammar/ContextFree/CNF.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 <set>
#include <deque>
#include <exception/CommonException.h>
namespace grammar { namespace grammar {
   
namespace properties { namespace properties {
...@@ -33,10 +48,41 @@ public: ...@@ -33,10 +48,41 @@ public:
* @param nonterminal nonterminal * @param nonterminal nonterminal
* @return set of nonterminals for which we can be derived from giveUnitRuleCyclen nonterminals in finite number of steps * @return set of nonterminals for which we can be derived from giveUnitRuleCyclen nonterminals in finite number of steps
*/ */
template<class T> template<class T, class SymbolType>
static std::set<alphabet::Symbol> getNonterminalUnitRuleCycle(const T& grammar, const alphabet::Symbol& nonterminal); static std::set<SymbolType> getNonterminalUnitRuleCycle(const T& grammar, const SymbolType& nonterminal);
}; };
   
template<class T, class SymbolType >
std::set<SymbolType> NonterminalUnitRuleCycle::getNonterminalUnitRuleCycle(const T& grammar, const SymbolType& nonterminal) {
if(grammar.getNonterminalAlphabet().count(nonterminal) == 0) {
throw exception::CommonException("Nonterminal symbol \"" + std::to_string ( nonterminal ) + "\" is not present in grammar.");
}
std::deque<std::set<SymbolType>> Ni;
Ni.push_back(std::set<SymbolType>{nonterminal});
int i = 1;
while(true) {
Ni.push_back(Ni.at(i-1));
for(const auto &rule : grammar.getRawRules()) {
const SymbolType& lhs = rule.first;
for(const auto& rhs : rule.second) {
if(Ni.at(i-1).count(lhs) && rhs.size() == 1 && grammar.getNonterminalAlphabet().count(rhs.front())) {
Ni.at(i).insert(rhs.front());
}
}
}
if(Ni.at(i) == Ni.at(i-1))
break;
i += 1;
}
return Ni.at(i);
}
} /* namespace properties */ } /* namespace properties */
   
} /* namespace grammar */ } /* namespace grammar */
......
...@@ -7,50 +7,10 @@ ...@@ -7,50 +7,10 @@
   
#include "NullableNonterminals.h" #include "NullableNonterminals.h"
   
#include <grammar/ContextFree/CFG.h>
#include <grammar/ContextFree/EpsilonFreeCFG.h>
#include <grammar/ContextFree/GNF.h>
#include <grammar/ContextFree/CNF.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 <set>
#include <deque>
#include <algorithm>
namespace grammar { namespace grammar {
   
namespace properties { namespace properties {
   
template<class T>
std::set<alphabet::Symbol> NullableNonterminals::getNullableNonterminals(const T& grammar) {
std::deque<std::set<alphabet::Symbol>> Ni;
Ni.push_back(std::set<alphabet::Symbol>{ });
int i = 1;
while(true) {
Ni.push_back(std::set<alphabet::Symbol>{ });
for(const auto& rule : grammar.getRawRules()) {
for(const auto& rhs : rule.second) {
if(rhs.size() == 0 || std::all_of(rhs.begin(), rhs.end(), [Ni, i](const alphabet::Symbol& symb){return Ni.at(i-1).count(symb);})) {
Ni.at(i).insert(rule.first);
}
}
}
if(Ni.at(i) == Ni.at(i-1))
break;
i += 1;
}
return Ni.at(i);
}
auto NullableNonterminalsCFG = NullableNonterminals::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::CFG < > >(NullableNonterminals::getNullableNonterminals); auto NullableNonterminalsCFG = NullableNonterminals::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::CFG < > >(NullableNonterminals::getNullableNonterminals);
auto NullableNonterminalsEpsilonFreeCFG = NullableNonterminals::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::EpsilonFreeCFG < > >(NullableNonterminals::getNullableNonterminals); auto NullableNonterminalsEpsilonFreeCFG = NullableNonterminals::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::EpsilonFreeCFG < > >(NullableNonterminals::getNullableNonterminals);
auto NullableNonterminalsGNF = NullableNonterminals::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::GNF < > >(NullableNonterminals::getNullableNonterminals); auto NullableNonterminalsGNF = NullableNonterminals::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::GNF < > >(NullableNonterminals::getNullableNonterminals);
...@@ -61,6 +21,10 @@ auto NullableNonterminalsLeftRG = NullableNonterminals::RegistratorWrapper<std:: ...@@ -61,6 +21,10 @@ auto NullableNonterminalsLeftRG = NullableNonterminals::RegistratorWrapper<std::
auto NullableNonterminalsRightLG = NullableNonterminals::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::RightLG < > >(NullableNonterminals::getNullableNonterminals); auto NullableNonterminalsRightLG = NullableNonterminals::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::RightLG < > >(NullableNonterminals::getNullableNonterminals);
auto NullableNonterminalsRightRG = NullableNonterminals::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::RightRG < > >(NullableNonterminals::getNullableNonterminals); auto NullableNonterminalsRightRG = NullableNonterminals::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::RightRG < > >(NullableNonterminals::getNullableNonterminals);
   
std::set<alphabet::Symbol> NullableNonterminals::getNullableNonterminals(const grammar::Grammar& grammar ) {
return dispatch(grammar.getData());
}
} /* namespace properties */ } /* namespace properties */
   
} /* namespace grammar */ } /* namespace grammar */
...@@ -13,6 +13,20 @@ ...@@ -13,6 +13,20 @@
#include <grammar/Grammar.h> #include <grammar/Grammar.h>
#include <alphabet/Symbol.h> #include <alphabet/Symbol.h>
   
#include <grammar/ContextFree/CFG.h>
#include <grammar/ContextFree/EpsilonFreeCFG.h>
#include <grammar/ContextFree/GNF.h>
#include <grammar/ContextFree/CNF.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 <set>
#include <deque>
#include <algorithm>
namespace grammar { namespace grammar {
   
namespace properties { namespace properties {
...@@ -33,10 +47,36 @@ public: ...@@ -33,10 +47,36 @@ public:
* @param grammar grammar * @param grammar grammar
* @return set of nullable nonterminals from grammar * @return set of nullable nonterminals from grammar
*/ */
template<class T> template<class T, class SymbolType = typename grammar::SymbolTypeOfGrammar < T > >
static std::set<alphabet::Symbol> getNullableNonterminals(const T& grammar); static std::set<SymbolType> getNullableNonterminals(const T& grammar);
}; };
   
template<class T, class SymbolType >
std::set<SymbolType> NullableNonterminals::getNullableNonterminals(const T& grammar) {
std::deque<std::set<SymbolType>> Ni;
Ni.push_back(std::set<SymbolType>{ });
int i = 1;
while(true) {
Ni.push_back(std::set<SymbolType>{ });
for(const auto& rule : grammar.getRawRules()) {
for(const auto& rhs : rule.second) {
if(rhs.size() == 0 || std::all_of(rhs.begin(), rhs.end(), [Ni, i](const SymbolType& symb){return Ni.at(i-1).count(symb);})) {
Ni.at(i).insert(rule.first);
}
}
}
if(Ni.at(i) == Ni.at(i-1))
break;
i += 1;
}
return Ni.at(i);
}
} /* namespace properties */ } /* namespace properties */
   
} /* namespace grammar */ } /* namespace grammar */
......
...@@ -7,55 +7,10 @@ ...@@ -7,55 +7,10 @@
   
#include "ProductiveNonterminals.h" #include "ProductiveNonterminals.h"
   
#include <grammar/ContextFree/CFG.h>
#include <grammar/ContextFree/EpsilonFreeCFG.h>
#include <grammar/ContextFree/GNF.h>
#include <grammar/ContextFree/CNF.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 <set>
#include <deque>
#include <algorithm>
namespace grammar { namespace grammar {
   
namespace properties { namespace properties {
   
template<class T>
std::set<alphabet::Symbol> ProductiveNonterminals::getProductiveNonterminals( const T & grammar ) {
// 1.
std::deque<std::set<alphabet::Symbol>> Ni;
Ni.push_back( std::set<alphabet::Symbol>( ) );
int i = 1;
// 2.
while( true ) {
Ni.push_back( Ni.at( i - 1 ) );
for( const auto & rule : grammar.getRawRules( ) ) {
for( const auto & rhs : rule.second ) {
if( std::all_of( rhs.begin( ), rhs.end( ), [ i, Ni, grammar ]( const alphabet::Symbol & symbol ) -> bool {
return Ni.at( i - 1 ) . count( symbol ) || grammar.getTerminalAlphabet( ). count( symbol );
} ) )
Ni.at( i ).insert( rule.first );
}
}
if( Ni.at( i ) == Ni.at( i - 1 ) )
break;
i = i + 1;
}
// 3.
return Ni.at( i );
}
auto ProductiveNonterminalsCFG = ProductiveNonterminals::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::CFG < > >(ProductiveNonterminals::getProductiveNonterminals); auto ProductiveNonterminalsCFG = ProductiveNonterminals::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::CFG < > >(ProductiveNonterminals::getProductiveNonterminals);
auto ProductiveNonterminalsEpsilonFreeCFG = ProductiveNonterminals::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::EpsilonFreeCFG < > >(ProductiveNonterminals::getProductiveNonterminals); auto ProductiveNonterminalsEpsilonFreeCFG = ProductiveNonterminals::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::EpsilonFreeCFG < > >(ProductiveNonterminals::getProductiveNonterminals);
auto ProductiveNonterminalsGNF = ProductiveNonterminals::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::GNF < > >(ProductiveNonterminals::getProductiveNonterminals); auto ProductiveNonterminalsGNF = ProductiveNonterminals::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::GNF < > >(ProductiveNonterminals::getProductiveNonterminals);
...@@ -66,6 +21,10 @@ auto ProductiveNonterminalsLeftRG = ProductiveNonterminals::RegistratorWrapper<s ...@@ -66,6 +21,10 @@ auto ProductiveNonterminalsLeftRG = ProductiveNonterminals::RegistratorWrapper<s
auto ProductiveNonterminalsRightLG = ProductiveNonterminals::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::RightLG < > >(ProductiveNonterminals::getProductiveNonterminals); auto ProductiveNonterminalsRightLG = ProductiveNonterminals::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::RightLG < > >(ProductiveNonterminals::getProductiveNonterminals);
auto ProductiveNonterminalsRightRG = ProductiveNonterminals::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::RightRG < > >(ProductiveNonterminals::getProductiveNonterminals); auto ProductiveNonterminalsRightRG = ProductiveNonterminals::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::RightRG < > >(ProductiveNonterminals::getProductiveNonterminals);
   
std::set<alphabet::Symbol> ProductiveNonterminals::getProductiveNonterminals(const grammar::Grammar& grammar ) {
return dispatch(grammar.getData());
}
} /* namespace properties */ } /* namespace properties */
   
} /* namespace grammar */ } /* namespace grammar */
...@@ -13,6 +13,20 @@ ...@@ -13,6 +13,20 @@
#include <grammar/Grammar.h> #include <grammar/Grammar.h>
#include <alphabet/Symbol.h> #include <alphabet/Symbol.h>
   
#include <grammar/ContextFree/CFG.h>
#include <grammar/ContextFree/EpsilonFreeCFG.h>
#include <grammar/ContextFree/GNF.h>
#include <grammar/ContextFree/CNF.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 <set>
#include <deque>
#include <algorithm>
namespace grammar { namespace grammar {
   
namespace properties { namespace properties {
...@@ -27,10 +41,41 @@ public: ...@@ -27,10 +41,41 @@ public:
/** /**
* Implements steps 1 through 3 in Melichar 3.6 * Implements steps 1 through 3 in Melichar 3.6
*/ */
template<class T> template<class T, class SymbolType = typename grammar::SymbolTypeOfGrammar < T > >
static std::set<alphabet::Symbol> getProductiveNonterminals( const T & grammar ); static std::set<SymbolType> getProductiveNonterminals( const T & grammar );
}; };
   
template<class T, class SymbolType >
std::set<SymbolType> ProductiveNonterminals::getProductiveNonterminals( const T & grammar ) {
// 1.
std::deque<std::set<SymbolType>> Ni;
Ni.push_back( std::set<SymbolType>( ) );
int i = 1;
// 2.
while( true ) {
Ni.push_back( Ni.at( i - 1 ) );
for( const auto & rule : grammar.getRawRules( ) ) {
for( const auto & rhs : rule.second ) {
if( std::all_of( rhs.begin( ), rhs.end( ), [ i, Ni, grammar ]( const SymbolType & symbol ) -> bool {
return Ni.at( i - 1 ) . count( symbol ) || grammar.getTerminalAlphabet( ). count( symbol );
} ) )
Ni.at( i ).insert( rule.first );
}
}
if( Ni.at( i ) == Ni.at( i - 1 ) )
break;
i = i + 1;
}
// 3.
return Ni.at( i );
}
} /* namespace properties */ } /* namespace properties */
   
} /* namespace grammar */ } /* namespace grammar */
......
...@@ -6,63 +6,11 @@ ...@@ -6,63 +6,11 @@
*/ */
   
#include "RecursiveNonterminal.h" #include "RecursiveNonterminal.h"
#include "NullableNonterminals.h"
#include <grammar/ContextFree/CFG.h>
#include <grammar/ContextFree/EpsilonFreeCFG.h>
#include <grammar/ContextFree/GNF.h>
#include <grammar/ContextFree/CNF.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 <set>
#include <deque>
#include <exception/CommonException.h>
   
namespace grammar { namespace grammar {
   
namespace properties { namespace properties {
   
template < class T >
bool RecursiveNonterminal::isNonterminalRecursive ( const T & grammar, const alphabet::Symbol & nonterminal ) {
if ( grammar.getNonterminalAlphabet ( ).count ( nonterminal ) == 0 )
throw exception::CommonException ( "Nonterminal symbol \"" + ( std::string ) nonterminal + "\" is not present in grammar." );
std::deque < std::set < alphabet::Symbol > > Ni;
Ni.push_back ( std::set < alphabet::Symbol > { nonterminal } );
unsigned i = 1;
auto rawRules = grammar.getRawRules ( );
auto nullable = grammar::properties::NullableNonterminals::getNullableNonterminals ( grammar );
while ( i <= grammar.getNonterminalAlphabet ( ).size ( ) ) {
Ni.push_back ( std::set < alphabet::Symbol > { } );
for ( const alphabet::Symbol & lhs : Ni.at ( i - 1 ) )
if ( rawRules.find ( lhs ) != rawRules.end ( ) )
for ( const std::vector < alphabet::Symbol > & rhs : rawRules.find ( lhs )->second )
for ( const alphabet::Symbol & rhsSymbol : rhs ) {
if ( grammar.getTerminalAlphabet ( ).count ( rhsSymbol ) ) break;
Ni.at ( i ).insert ( rhsSymbol );
if ( !nullable.count ( rhsSymbol ) ) break;
}
if ( Ni.at ( i ).count ( nonterminal ) ) return true;
i += 1;
}
return false;
}
auto RecursiveNonterminalCFG = RecursiveNonterminal::RegistratorWrapper < bool, grammar::CFG < > > ( RecursiveNonterminal::isNonterminalRecursive ); auto RecursiveNonterminalCFG = RecursiveNonterminal::RegistratorWrapper < bool, grammar::CFG < > > ( RecursiveNonterminal::isNonterminalRecursive );
auto RecursiveNonterminalEpsilonFreeCFG = RecursiveNonterminal::RegistratorWrapper < bool, grammar::EpsilonFreeCFG < > > ( RecursiveNonterminal::isNonterminalRecursive ); auto RecursiveNonterminalEpsilonFreeCFG = RecursiveNonterminal::RegistratorWrapper < bool, grammar::EpsilonFreeCFG < > > ( RecursiveNonterminal::isNonterminalRecursive );
auto RecursiveNonterminalGNF = RecursiveNonterminal::RegistratorWrapper < bool, grammar::GNF < > > ( RecursiveNonterminal::isNonterminalRecursive ); auto RecursiveNonterminalGNF = RecursiveNonterminal::RegistratorWrapper < bool, grammar::GNF < > > ( RecursiveNonterminal::isNonterminalRecursive );
......
...@@ -13,6 +13,23 @@ ...@@ -13,6 +13,23 @@
#include <grammar/Grammar.h> #include <grammar/Grammar.h>
#include <alphabet/Symbol.h> #include <alphabet/Symbol.h>
   
#include "NullableNonterminals.h"
#include <grammar/ContextFree/CFG.h>
#include <grammar/ContextFree/EpsilonFreeCFG.h>
#include <grammar/ContextFree/GNF.h>
#include <grammar/ContextFree/CNF.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 <set>
#include <deque>
#include <exception/CommonException.h>
namespace grammar { namespace grammar {
   
namespace properties { namespace properties {
...@@ -31,11 +48,47 @@ public: ...@@ -31,11 +48,47 @@ public:
* @param nonterminal nonterminal * @param nonterminal nonterminal
* @return bool which denote whether the nonterminal is recursive in the grammar * @return bool which denote whether the nonterminal is recursive in the grammar
*/ */
template < class T > template < class T, class SymbolType >
static bool isNonterminalRecursive ( const T & grammar, const alphabet::Symbol & nonterminal ); static bool isNonterminalRecursive ( const T & grammar, const SymbolType & nonterminal );
   
}; };
   
template < class T, class SymbolType >
bool RecursiveNonterminal::isNonterminalRecursive ( const T & grammar, const SymbolType & nonterminal ) {
if ( grammar.getNonterminalAlphabet ( ).count ( nonterminal ) == 0 )
throw exception::CommonException ( "Nonterminal symbol \"" + ( std::string ) nonterminal + "\" is not present in grammar." );
std::deque < std::set < SymbolType > > Ni;
Ni.push_back ( std::set < SymbolType > { nonterminal } );
unsigned i = 1;
auto rawRules = grammar.getRawRules ( );
auto nullable = grammar::properties::NullableNonterminals::getNullableNonterminals ( grammar );
while ( i <= grammar.getNonterminalAlphabet ( ).size ( ) ) {
Ni.push_back ( std::set < SymbolType > { } );
for ( const SymbolType & lhs : Ni.at ( i - 1 ) )
if ( rawRules.find ( lhs ) != rawRules.end ( ) )
for ( const std::vector < SymbolType > & rhs : rawRules.find ( lhs )->second )
for ( const SymbolType & rhsSymbol : rhs ) {
if ( grammar.getTerminalAlphabet ( ).count ( rhsSymbol ) ) break;
Ni.at ( i ).insert ( rhsSymbol );
if ( !nullable.count ( rhsSymbol ) ) break;
}
if ( Ni.at ( i ).count ( nonterminal ) ) return true;
i += 1;
}
return false;
}
} /* namespace properties */ } /* namespace properties */
   
} /* namespace grammar */ } /* namespace grammar */
......
...@@ -7,56 +7,10 @@ ...@@ -7,56 +7,10 @@
   
#include "UnreachableSymbols.h" #include "UnreachableSymbols.h"
   
#include <grammar/ContextFree/CFG.h>
#include <grammar/ContextFree/EpsilonFreeCFG.h>
#include <grammar/ContextFree/GNF.h>
#include <grammar/ContextFree/CNF.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 <algorithm>
#include <deque>
#include <set>
namespace grammar { namespace grammar {
   
namespace properties { namespace properties {
   
template<class T>
std::set<alphabet::Symbol> UnreachableSymbols::getUnreachableSymbols( const T & grammar ) {
// 1
std::deque<std::set<alphabet::Symbol>> Vi;
Vi.push_back( std::set<alphabet::Symbol>( ) );
Vi.at( 0 ).insert( grammar.getInitialSymbol( ) );
int i = 1;
// 2.
while( true ) {
Vi.push_back( Vi.at( i - 1 ) );
for( const auto & rule : grammar.getRawRules( ) ) {
if( Vi.at( i - 1 ).count( rule.first ) ) {
for( const auto & rhs : rule.second ) {
Vi.at( i ).insert( rhs.begin( ), rhs.end( ) );
}
}
}
if( Vi.at( i ) == Vi.at( i - 1 ) )
break;
i = i + 1;
}
// 3.
return Vi.at( i );
}
auto UnreachableSymbolsCFG = UnreachableSymbols::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::CFG < > >(UnreachableSymbols::getUnreachableSymbols); auto UnreachableSymbolsCFG = UnreachableSymbols::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::CFG < > >(UnreachableSymbols::getUnreachableSymbols);
auto UnreachableSymbolsEpsilonFreeCFG = UnreachableSymbols::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::EpsilonFreeCFG < > >(UnreachableSymbols::getUnreachableSymbols); auto UnreachableSymbolsEpsilonFreeCFG = UnreachableSymbols::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::EpsilonFreeCFG < > >(UnreachableSymbols::getUnreachableSymbols);
auto UnreachableSymbolsGNF = UnreachableSymbols::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::GNF < > >(UnreachableSymbols::getUnreachableSymbols); auto UnreachableSymbolsGNF = UnreachableSymbols::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::GNF < > >(UnreachableSymbols::getUnreachableSymbols);
...@@ -67,6 +21,10 @@ auto UnreachableSymbolsLeftRG = UnreachableSymbols::RegistratorWrapper<std::set< ...@@ -67,6 +21,10 @@ auto UnreachableSymbolsLeftRG = UnreachableSymbols::RegistratorWrapper<std::set<
auto UnreachableSymbolsRightLG = UnreachableSymbols::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::RightLG < > >(UnreachableSymbols::getUnreachableSymbols); auto UnreachableSymbolsRightLG = UnreachableSymbols::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::RightLG < > >(UnreachableSymbols::getUnreachableSymbols);
auto UnreachableSymbolsRightRG = UnreachableSymbols::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::RightRG < > >(UnreachableSymbols::getUnreachableSymbols); auto UnreachableSymbolsRightRG = UnreachableSymbols::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::RightRG < > >(UnreachableSymbols::getUnreachableSymbols);
   
std::set < alphabet::Symbol > UnreachableSymbols::getUnreachableSymbols ( const grammar::Grammar & grammar ) {
return dispatch ( grammar.getData ( ) );
}
} /* namespace properties */ } /* namespace properties */
   
} /* namespace grammar */ } /* namespace grammar */
...@@ -13,6 +13,20 @@ ...@@ -13,6 +13,20 @@
#include <grammar/Grammar.h> #include <grammar/Grammar.h>
#include <alphabet/Symbol.h> #include <alphabet/Symbol.h>
   
#include <grammar/ContextFree/CFG.h>
#include <grammar/ContextFree/EpsilonFreeCFG.h>
#include <grammar/ContextFree/GNF.h>
#include <grammar/ContextFree/CNF.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 <algorithm>
#include <deque>
#include <set>
namespace grammar { namespace grammar {
   
namespace properties { namespace properties {
...@@ -27,10 +41,42 @@ public: ...@@ -27,10 +41,42 @@ public:
/** /**
* Implements * Implements
*/ */
template<class T> template<class T, class SymbolType = typename grammar::SymbolTypeOfGrammar < T > >
static std::set<alphabet::Symbol> getUnreachableSymbols( const T & grammar ); static std::set<alphabet::Symbol> getUnreachableSymbols( const T & grammar );
}; };
   
template<class T, class SymbolType >
std::set<alphabet::Symbol> UnreachableSymbols::getUnreachableSymbols( const T & grammar ) {
// 1
std::deque<std::set<alphabet::Symbol>> Vi;
Vi.push_back( std::set<alphabet::Symbol>( ) );
Vi.at( 0 ).insert( grammar.getInitialSymbol( ) );
int i = 1;
// 2.
while( true ) {
Vi.push_back( Vi.at( i - 1 ) );
for( const auto & rule : grammar.getRawRules( ) ) {
if( Vi.at( i - 1 ).count( rule.first ) ) {
for( const auto & rhs : rule.second ) {
Vi.at( i ).insert( rhs.begin( ), rhs.end( ) );
}
}
}
if( Vi.at( i ) == Vi.at( i - 1 ) )
break;
i = i + 1;
}
// 3.
return Vi.at( i );
}
} /* namespace properties */ } /* namespace properties */
   
} /* namespace grammar */ } /* namespace grammar */
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment