From 10444ab6ae6ca0eefd033d55f596f5d4f56b7023 Mon Sep 17 00:00:00 2001 From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz> Date: Thu, 1 Dec 2016 21:55:10 +0100 Subject: [PATCH] template properties retrieving algorithms --- .../grammar/properties/IsLanguageEmpty.cpp | 17 +----- .../src/grammar/properties/IsLanguageEmpty.h | 17 ++++++ .../IsLanguageGeneratingEpsilon.cpp | 17 +----- .../properties/IsLanguageGeneratingEpsilon.h | 17 ++++++ .../properties/NonterminalUnitRuleCycle.cpp | 46 --------------- .../properties/NonterminalUnitRuleCycle.h | 50 +++++++++++++++- .../properties/NullableNonterminals.cpp | 44 ++------------ .../grammar/properties/NullableNonterminals.h | 44 +++++++++++++- .../properties/ProductiveNonterminals.cpp | 49 ++-------------- .../properties/ProductiveNonterminals.h | 49 +++++++++++++++- .../properties/RecursiveNonterminal.cpp | 52 ----------------- .../grammar/properties/RecursiveNonterminal.h | 57 ++++++++++++++++++- .../grammar/properties/UnreachableSymbols.cpp | 50 ++-------------- .../grammar/properties/UnreachableSymbols.h | 48 +++++++++++++++- 14 files changed, 289 insertions(+), 268 deletions(-) diff --git a/alib2algo/src/grammar/properties/IsLanguageEmpty.cpp b/alib2algo/src/grammar/properties/IsLanguageEmpty.cpp index bba4aa3ffe..c0caf51f88 100644 --- a/alib2algo/src/grammar/properties/IsLanguageEmpty.cpp +++ b/alib2algo/src/grammar/properties/IsLanguageEmpty.cpp @@ -7,25 +7,12 @@ #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 properties { -template<class T> -bool IsLanguageEmpty::isLanguageEmpty( const T & grammar ) { - return grammar::properties::ProductiveNonterminals::getProductiveNonterminals( grammar ).count( grammar.getInitialSymbol( ) ); +bool IsLanguageEmpty::isLanguageEmpty(const grammar::Grammar& grammar) { + return dispatch(grammar.getData()); } auto IsLanguageEmptyCFG = IsLanguageEmpty::RegistratorWrapper<bool, grammar::CFG < > >(IsLanguageEmpty::isLanguageEmpty); diff --git a/alib2algo/src/grammar/properties/IsLanguageEmpty.h b/alib2algo/src/grammar/properties/IsLanguageEmpty.h index 8a67a20b9a..14e1916604 100644 --- a/alib2algo/src/grammar/properties/IsLanguageEmpty.h +++ b/alib2algo/src/grammar/properties/IsLanguageEmpty.h @@ -12,6 +12,18 @@ #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 properties { @@ -33,6 +45,11 @@ public: 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 grammar */ diff --git a/alib2algo/src/grammar/properties/IsLanguageGeneratingEpsilon.cpp b/alib2algo/src/grammar/properties/IsLanguageGeneratingEpsilon.cpp index b030f827c6..d8666e129f 100644 --- a/alib2algo/src/grammar/properties/IsLanguageGeneratingEpsilon.cpp +++ b/alib2algo/src/grammar/properties/IsLanguageGeneratingEpsilon.cpp @@ -7,25 +7,12 @@ #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 properties { -template<class T> -bool IsLanguageGeneratingEpsilon::isLanguageGeneratingEpsilon( const T & grammar ) { - return grammar::properties::NullableNonterminals::getNullableNonterminals( grammar ).count( grammar.getInitialSymbol( ) ); +bool IsLanguageGeneratingEpsilon::isLanguageGeneratingEpsilon(const grammar::Grammar& grammar) { + return dispatch(grammar.getData()); } auto IsLanguageGeneratingEpsilonCFG = IsLanguageGeneratingEpsilon::RegistratorWrapper<bool, grammar::CFG < > >(IsLanguageGeneratingEpsilon::isLanguageGeneratingEpsilon); diff --git a/alib2algo/src/grammar/properties/IsLanguageGeneratingEpsilon.h b/alib2algo/src/grammar/properties/IsLanguageGeneratingEpsilon.h index 9ed1f538b4..ce9293508d 100644 --- a/alib2algo/src/grammar/properties/IsLanguageGeneratingEpsilon.h +++ b/alib2algo/src/grammar/properties/IsLanguageGeneratingEpsilon.h @@ -12,6 +12,18 @@ #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 properties { @@ -33,6 +45,11 @@ public: 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 grammar */ diff --git a/alib2algo/src/grammar/properties/NonterminalUnitRuleCycle.cpp b/alib2algo/src/grammar/properties/NonterminalUnitRuleCycle.cpp index c3bd13edc9..e58c4e9460 100644 --- a/alib2algo/src/grammar/properties/NonterminalUnitRuleCycle.cpp +++ b/alib2algo/src/grammar/properties/NonterminalUnitRuleCycle.cpp @@ -7,56 +7,10 @@ #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 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 NonterminalUnitRuleCycleEpsilonFreeCFG = NonterminalUnitRuleCycle::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::EpsilonFreeCFG < > >(NonterminalUnitRuleCycle::getNonterminalUnitRuleCycle); auto NonterminalUnitRuleCycleGNF = NonterminalUnitRuleCycle::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::GNF < > >(NonterminalUnitRuleCycle::getNonterminalUnitRuleCycle); diff --git a/alib2algo/src/grammar/properties/NonterminalUnitRuleCycle.h b/alib2algo/src/grammar/properties/NonterminalUnitRuleCycle.h index 3080c7b7b4..3103915791 100644 --- a/alib2algo/src/grammar/properties/NonterminalUnitRuleCycle.h +++ b/alib2algo/src/grammar/properties/NonterminalUnitRuleCycle.h @@ -13,6 +13,21 @@ #include <grammar/Grammar.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 properties { @@ -33,10 +48,41 @@ public: * @param nonterminal nonterminal * @return set of nonterminals for which we can be derived from giveUnitRuleCyclen nonterminals in finite number of steps */ - template<class T> - static std::set<alphabet::Symbol> getNonterminalUnitRuleCycle(const T& grammar, const alphabet::Symbol& nonterminal); + template<class T, class SymbolType> + 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 grammar */ diff --git a/alib2algo/src/grammar/properties/NullableNonterminals.cpp b/alib2algo/src/grammar/properties/NullableNonterminals.cpp index 754c52aba4..1d503d0034 100644 --- a/alib2algo/src/grammar/properties/NullableNonterminals.cpp +++ b/alib2algo/src/grammar/properties/NullableNonterminals.cpp @@ -7,50 +7,10 @@ #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 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 NullableNonterminalsEpsilonFreeCFG = NullableNonterminals::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::EpsilonFreeCFG < > >(NullableNonterminals::getNullableNonterminals); auto NullableNonterminalsGNF = NullableNonterminals::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::GNF < > >(NullableNonterminals::getNullableNonterminals); @@ -61,6 +21,10 @@ auto NullableNonterminalsLeftRG = NullableNonterminals::RegistratorWrapper<std:: auto NullableNonterminalsRightLG = NullableNonterminals::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::RightLG < > >(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 grammar */ diff --git a/alib2algo/src/grammar/properties/NullableNonterminals.h b/alib2algo/src/grammar/properties/NullableNonterminals.h index 34edd8f8eb..9423ac9ac6 100644 --- a/alib2algo/src/grammar/properties/NullableNonterminals.h +++ b/alib2algo/src/grammar/properties/NullableNonterminals.h @@ -13,6 +13,20 @@ #include <grammar/Grammar.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 properties { @@ -33,10 +47,36 @@ public: * @param grammar grammar * @return set of nullable nonterminals from grammar */ - template<class T> - static std::set<alphabet::Symbol> getNullableNonterminals(const T& grammar); + template<class T, class SymbolType = typename grammar::SymbolTypeOfGrammar < T > > + 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 grammar */ diff --git a/alib2algo/src/grammar/properties/ProductiveNonterminals.cpp b/alib2algo/src/grammar/properties/ProductiveNonterminals.cpp index 8e9a83d0a0..a62f6c3c2e 100644 --- a/alib2algo/src/grammar/properties/ProductiveNonterminals.cpp +++ b/alib2algo/src/grammar/properties/ProductiveNonterminals.cpp @@ -7,55 +7,10 @@ #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 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 ProductiveNonterminalsEpsilonFreeCFG = ProductiveNonterminals::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::EpsilonFreeCFG < > >(ProductiveNonterminals::getProductiveNonterminals); auto ProductiveNonterminalsGNF = ProductiveNonterminals::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::GNF < > >(ProductiveNonterminals::getProductiveNonterminals); @@ -66,6 +21,10 @@ auto ProductiveNonterminalsLeftRG = ProductiveNonterminals::RegistratorWrapper<s auto ProductiveNonterminalsRightLG = ProductiveNonterminals::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::RightLG < > >(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 grammar */ diff --git a/alib2algo/src/grammar/properties/ProductiveNonterminals.h b/alib2algo/src/grammar/properties/ProductiveNonterminals.h index e2f63416d0..a5c6d46415 100644 --- a/alib2algo/src/grammar/properties/ProductiveNonterminals.h +++ b/alib2algo/src/grammar/properties/ProductiveNonterminals.h @@ -13,6 +13,20 @@ #include <grammar/Grammar.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 properties { @@ -27,10 +41,41 @@ public: /** * Implements steps 1 through 3 in Melichar 3.6 */ - template<class T> - static std::set<alphabet::Symbol> getProductiveNonterminals( const T & grammar ); + template<class T, class SymbolType = typename grammar::SymbolTypeOfGrammar < T > > + 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 grammar */ diff --git a/alib2algo/src/grammar/properties/RecursiveNonterminal.cpp b/alib2algo/src/grammar/properties/RecursiveNonterminal.cpp index e390e5676a..20ecaa30ac 100644 --- a/alib2algo/src/grammar/properties/RecursiveNonterminal.cpp +++ b/alib2algo/src/grammar/properties/RecursiveNonterminal.cpp @@ -6,63 +6,11 @@ */ #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 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 RecursiveNonterminalEpsilonFreeCFG = RecursiveNonterminal::RegistratorWrapper < bool, grammar::EpsilonFreeCFG < > > ( RecursiveNonterminal::isNonterminalRecursive ); auto RecursiveNonterminalGNF = RecursiveNonterminal::RegistratorWrapper < bool, grammar::GNF < > > ( RecursiveNonterminal::isNonterminalRecursive ); diff --git a/alib2algo/src/grammar/properties/RecursiveNonterminal.h b/alib2algo/src/grammar/properties/RecursiveNonterminal.h index b6b9c288be..f5a63e3777 100644 --- a/alib2algo/src/grammar/properties/RecursiveNonterminal.h +++ b/alib2algo/src/grammar/properties/RecursiveNonterminal.h @@ -13,6 +13,23 @@ #include <grammar/Grammar.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 properties { @@ -31,11 +48,47 @@ public: * @param nonterminal nonterminal * @return bool which denote whether the nonterminal is recursive in the grammar */ - template < class T > - static bool isNonterminalRecursive ( const T & grammar, const alphabet::Symbol & nonterminal ); + template < class T, class SymbolType > + 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 grammar */ diff --git a/alib2algo/src/grammar/properties/UnreachableSymbols.cpp b/alib2algo/src/grammar/properties/UnreachableSymbols.cpp index 33422b3cea..3dbf6be5a2 100644 --- a/alib2algo/src/grammar/properties/UnreachableSymbols.cpp +++ b/alib2algo/src/grammar/properties/UnreachableSymbols.cpp @@ -7,56 +7,10 @@ #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 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 UnreachableSymbolsEpsilonFreeCFG = UnreachableSymbols::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::EpsilonFreeCFG < > >(UnreachableSymbols::getUnreachableSymbols); auto UnreachableSymbolsGNF = UnreachableSymbols::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::GNF < > >(UnreachableSymbols::getUnreachableSymbols); @@ -67,6 +21,10 @@ auto UnreachableSymbolsLeftRG = UnreachableSymbols::RegistratorWrapper<std::set< auto UnreachableSymbolsRightLG = UnreachableSymbols::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::RightLG < > >(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 grammar */ diff --git a/alib2algo/src/grammar/properties/UnreachableSymbols.h b/alib2algo/src/grammar/properties/UnreachableSymbols.h index e4b1979225..e09346d906 100644 --- a/alib2algo/src/grammar/properties/UnreachableSymbols.h +++ b/alib2algo/src/grammar/properties/UnreachableSymbols.h @@ -13,6 +13,20 @@ #include <grammar/Grammar.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 properties { @@ -27,10 +41,42 @@ public: /** * Implements */ - template<class T> + template<class T, class SymbolType = typename grammar::SymbolTypeOfGrammar < T > > 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 grammar */ -- GitLab