diff --git a/alib2algo/src/regexp/glushkov/GlushkovFirst.cpp b/alib2algo/src/regexp/glushkov/GlushkovFirst.cpp deleted file mode 100644 index f40441b671d29f94f571ff85e6c5808679c9041d..0000000000000000000000000000000000000000 --- a/alib2algo/src/regexp/glushkov/GlushkovFirst.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/* - * GlushkovFirst.cpp - * - * Created on: 13. 3. 2014 - * Author: Tomas Pecka - */ - -#include "GlushkovFirst.h" -#include <regexp/unbounded/UnboundedRegExpAlternation.h> -#include <regexp/unbounded/UnboundedRegExpConcatenation.h> -#include <regexp/unbounded/UnboundedRegExpElement.h> -#include <regexp/unbounded/UnboundedRegExpEmpty.h> -#include <regexp/unbounded/UnboundedRegExpEpsilon.h> -#include <regexp/unbounded/UnboundedRegExpIteration.h> -#include <regexp/unbounded/UnboundedRegExpSymbol.h> - -#include "../properties/RegExpEpsilon.h" - -namespace regexp { - -std::set < UnboundedRegExpSymbol < alphabet::Symbol > > GlushkovFirst::first ( const regexp::UnboundedRegExp < > & re ) { - return re.getRegExp ( ).getStructure ( ).accept < std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > >, GlushkovFirst::Unbounded > ( ); -} - -std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > > GlushkovFirst::Unbounded::visit ( const regexp::UnboundedRegExpAlternation < alphabet::Symbol > & node ) { - std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > > ret, tmp; - - for ( auto const & element : node.getElements ( ) ) { - tmp = element->accept < std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > >, GlushkovFirst::Unbounded > ( ); - ret.insert ( tmp.begin ( ), tmp.end ( ) ); - } - - return ret; -} - -std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > > GlushkovFirst::Unbounded::visit ( const regexp::UnboundedRegExpConcatenation < alphabet::Symbol > & node ) { - std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > > ret, tmp; - - for ( auto const & element : node.getElements ( ) ) { - tmp = element->accept < std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > >, GlushkovFirst::Unbounded > ( ); - ret.insert ( tmp.begin ( ), tmp.end ( ) ); - - if ( !regexp::properties::RegExpEpsilon::languageContainsEpsilon ( * element ) ) // If regexp of this subtree can match epsilon, then we need to add next subtree - break; - } - - return ret; -} - -std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > > GlushkovFirst::Unbounded::visit ( const regexp::UnboundedRegExpIteration < alphabet::Symbol > & node ) { - return node.getElement ( ).accept < std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > >, GlushkovFirst::Unbounded > ( ); -} - -std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > > GlushkovFirst::Unbounded::visit ( const regexp::UnboundedRegExpSymbol < alphabet::Symbol > & node ) { - return std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > > { node }; -} - -std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > > GlushkovFirst::Unbounded::visit ( const regexp::UnboundedRegExpEpsilon < alphabet::Symbol > & /* node */ ) { - return std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > > ( ); -} - -std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > > GlushkovFirst::Unbounded::visit ( const regexp::UnboundedRegExpEmpty < alphabet::Symbol > & /* node */ ) { - return std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > > ( ); -} - -} /* namespace regexp */ diff --git a/alib2algo/src/regexp/glushkov/GlushkovFirst.h b/alib2algo/src/regexp/glushkov/GlushkovFirst.h index 80f699088d9b58f20f00995147b3689225031d49..ad87bf47a64bff1c05c7bef3e30156bc6c404e7d 100644 --- a/alib2algo/src/regexp/glushkov/GlushkovFirst.h +++ b/alib2algo/src/regexp/glushkov/GlushkovFirst.h @@ -13,6 +13,16 @@ #include <regexp/unbounded/UnboundedRegExp.h> #include <regexp/RegExpFeatures.h> +#include <regexp/unbounded/UnboundedRegExpAlternation.h> +#include <regexp/unbounded/UnboundedRegExpConcatenation.h> +#include <regexp/unbounded/UnboundedRegExpElement.h> +#include <regexp/unbounded/UnboundedRegExpEmpty.h> +#include <regexp/unbounded/UnboundedRegExpEpsilon.h> +#include <regexp/unbounded/UnboundedRegExpIteration.h> +#include <regexp/unbounded/UnboundedRegExpSymbol.h> + +#include <regexp/properties/RegExpEpsilon.h> + namespace regexp { /** @@ -26,19 +36,73 @@ public: * @param re RegExp to probe * @return all RegExpSymbols whichcan start the word. */ - static std::set < UnboundedRegExpSymbol < alphabet::Symbol > > first ( const regexp::UnboundedRegExp < > & re ); + template < class SymbolType > + static std::set < UnboundedRegExpSymbol < SymbolType > > first ( const regexp::UnboundedRegExp < SymbolType > & re ); + template < class SymbolType > class Unbounded { public: - static std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > > visit ( const regexp::UnboundedRegExpAlternation < alphabet::Symbol > & node ); - static std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > > visit ( const regexp::UnboundedRegExpConcatenation < alphabet::Symbol > & node ); - static std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > > visit ( const regexp::UnboundedRegExpIteration < alphabet::Symbol > & node ); - static std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > > visit ( const regexp::UnboundedRegExpSymbol < alphabet::Symbol > & node ); - static std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > > visit ( const regexp::UnboundedRegExpEmpty < alphabet::Symbol > & node ); - static std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > > visit ( const regexp::UnboundedRegExpEpsilon < alphabet::Symbol > & node ); + static std::set < regexp::UnboundedRegExpSymbol < SymbolType > > visit ( const regexp::UnboundedRegExpAlternation < SymbolType > & node ); + static std::set < regexp::UnboundedRegExpSymbol < SymbolType > > visit ( const regexp::UnboundedRegExpConcatenation < SymbolType > & node ); + static std::set < regexp::UnboundedRegExpSymbol < SymbolType > > visit ( const regexp::UnboundedRegExpIteration < SymbolType > & node ); + static std::set < regexp::UnboundedRegExpSymbol < SymbolType > > visit ( const regexp::UnboundedRegExpSymbol < SymbolType > & node ); + static std::set < regexp::UnboundedRegExpSymbol < SymbolType > > visit ( const regexp::UnboundedRegExpEmpty < SymbolType > & node ); + static std::set < regexp::UnboundedRegExpSymbol < SymbolType > > visit ( const regexp::UnboundedRegExpEpsilon < SymbolType > & node ); }; }; +template < class SymbolType > +std::set < UnboundedRegExpSymbol < SymbolType > > GlushkovFirst::first ( const regexp::UnboundedRegExp < SymbolType > & re ) { + return re.getRegExp ( ).getStructure ( ).template accept < std::set < regexp::UnboundedRegExpSymbol < SymbolType > >, GlushkovFirst::Unbounded < SymbolType > > ( ); +} + +template < class SymbolType > +std::set < regexp::UnboundedRegExpSymbol < SymbolType > > GlushkovFirst::Unbounded < SymbolType >::visit ( const regexp::UnboundedRegExpAlternation < SymbolType > & node ) { + std::set < regexp::UnboundedRegExpSymbol < SymbolType > > ret, tmp; + + for ( auto const & element : node.getElements ( ) ) { + tmp = element->template accept < std::set < regexp::UnboundedRegExpSymbol < SymbolType > >, GlushkovFirst::Unbounded < SymbolType > > ( ); + ret.insert ( tmp.begin ( ), tmp.end ( ) ); + } + + return ret; +} + +template < class SymbolType > +std::set < regexp::UnboundedRegExpSymbol < SymbolType > > GlushkovFirst::Unbounded < SymbolType >::visit ( const regexp::UnboundedRegExpConcatenation < SymbolType > & node ) { + std::set < regexp::UnboundedRegExpSymbol < SymbolType > > ret, tmp; + + for ( auto const & element : node.getElements ( ) ) { + tmp = element->template accept < std::set < regexp::UnboundedRegExpSymbol < SymbolType > >, GlushkovFirst::Unbounded < SymbolType > > ( ); + ret.insert ( tmp.begin ( ), tmp.end ( ) ); + + if ( ! regexp::properties::RegExpEpsilon::languageContainsEpsilon ( * element ) ) // If regexp of this subtree can match epsilon, then we need to add next subtree + break; + } + + return ret; +} + +template < class SymbolType > +std::set < regexp::UnboundedRegExpSymbol < SymbolType > > GlushkovFirst::Unbounded < SymbolType >::visit ( const regexp::UnboundedRegExpIteration < SymbolType > & node ) { + return node.getElement ( ).template accept < std::set < regexp::UnboundedRegExpSymbol < SymbolType > >, GlushkovFirst::Unbounded < SymbolType > > ( ); +} + +template < class SymbolType > +std::set < regexp::UnboundedRegExpSymbol < SymbolType > > GlushkovFirst::Unbounded < SymbolType >::visit ( const regexp::UnboundedRegExpSymbol < SymbolType > & node ) { + return std::set < regexp::UnboundedRegExpSymbol < SymbolType > > { node }; +} + +template < class SymbolType > +std::set < regexp::UnboundedRegExpSymbol < SymbolType > > GlushkovFirst::Unbounded < SymbolType >::visit ( const regexp::UnboundedRegExpEpsilon < SymbolType > & /* node */ ) { + return std::set < regexp::UnboundedRegExpSymbol < SymbolType > > ( ); +} + +template < class SymbolType > +std::set < regexp::UnboundedRegExpSymbol < SymbolType > > GlushkovFirst::Unbounded < SymbolType >::visit ( const regexp::UnboundedRegExpEmpty < SymbolType > & /* node */ ) { + return std::set < regexp::UnboundedRegExpSymbol < SymbolType > > ( ); +} + } /* namespace regexp */ #endif /* GLUSHKOV_FIRST_H_ */ diff --git a/alib2algo/src/regexp/glushkov/GlushkovFollow.cpp b/alib2algo/src/regexp/glushkov/GlushkovFollow.cpp deleted file mode 100644 index 2a97e1513c5802f148352c4950d6ada74b05c6a4..0000000000000000000000000000000000000000 --- a/alib2algo/src/regexp/glushkov/GlushkovFollow.cpp +++ /dev/null @@ -1,91 +0,0 @@ -/* - * GlushkovFollow.cpp - * - * Created on: 13. 3. 2014 - * Author: Tomas Pecka - */ - -#include "GlushkovFollow.h" -#include <regexp/unbounded/UnboundedRegExpAlternation.h> -#include <regexp/unbounded/UnboundedRegExpConcatenation.h> -#include <regexp/unbounded/UnboundedRegExpElement.h> -#include <regexp/unbounded/UnboundedRegExpEmpty.h> -#include <regexp/unbounded/UnboundedRegExpEpsilon.h> -#include <regexp/unbounded/UnboundedRegExpIteration.h> -#include <regexp/unbounded/UnboundedRegExpSymbol.h> - -#include "GlushkovFirst.h" -#include "GlushkovLast.h" -#include "GlushkovPos.h" - -#include "../properties/RegExpEpsilon.h" - -#include <iterator> - -namespace regexp { - -std::set < UnboundedRegExpSymbol < alphabet::Symbol > > GlushkovFollow::follow ( const regexp::UnboundedRegExp < > & re, const UnboundedRegExpSymbol < alphabet::Symbol > & symbol ) { - return re.getRegExp ( ).getStructure ( ).accept < std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > >, GlushkovFollow::Unbounded > ( symbol ); -} - -// ---------------------------------------------------------------------------- - -std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > > GlushkovFollow::Unbounded::visit ( const regexp::UnboundedRegExpAlternation < alphabet::Symbol > & node, const regexp::UnboundedRegExpSymbol < alphabet::Symbol > & symbolptr ) { - for ( auto const & element : node.getElements ( ) ) - if ( element->accept < bool, GlushkovPos::Unbounded > ( symbolptr ) ) - return element->accept < std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > >, GlushkovFollow::Unbounded > ( symbolptr ); - - throw exception::CommonException ( "GlushkovFollow::Unbounded::visit(Alt)" ); -} - -std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > > GlushkovFollow::Unbounded::visit ( const regexp::UnboundedRegExpConcatenation < alphabet::Symbol > & node, const regexp::UnboundedRegExpSymbol < alphabet::Symbol > & symbolptr ) { - std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > > ret, tmp, lastSet; - - for ( auto e = node.getElements ( ).begin ( ); e != node.getElements ( ).end ( ); e++ ) { - if ( ! ( * e )->accept < bool, GlushkovPos::Unbounded > ( symbolptr ) ) - continue; - - tmp = ( * e )->accept < std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > >, GlushkovFollow::Unbounded > ( symbolptr ); - ret.insert ( tmp.begin ( ), tmp.end ( ) ); - - lastSet = ( * e )->accept < std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > >, GlushkovLast::Unbounded > ( ); - - if ( lastSet.find ( symbolptr ) != lastSet.end ( ) ) - for ( auto f = next ( e ); f != node.getElements ( ).end ( ); f++ ) { - tmp = ( * f )->accept < std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > >, GlushkovFirst::Unbounded > ( ); - ret.insert ( tmp.begin ( ), tmp.end ( ) ); - - if ( !regexp::properties::RegExpEpsilon::languageContainsEpsilon ( * * f ) ) - break; - } - - } - - return ret; -} - -std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > > GlushkovFollow::Unbounded::visit ( const regexp::UnboundedRegExpIteration < alphabet::Symbol > & node, const regexp::UnboundedRegExpSymbol < alphabet::Symbol > & symbolptr ) { - std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > > ret = node.getElement ( ).accept < std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > >, GlushkovFollow::Unbounded > ( symbolptr ); - std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > > lastSet = node.getElement ( ).accept < std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > >, GlushkovLast::Unbounded > ( ); - - if ( lastSet.find ( symbolptr ) != lastSet.end ( ) ) { - std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > > firstSet = node.getElement ( ).accept < std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > >, GlushkovFirst::Unbounded > ( ); - ret.insert ( firstSet.begin ( ), firstSet.end ( ) ); - } - - return ret; -} - -std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > > GlushkovFollow::Unbounded::visit ( const regexp::UnboundedRegExpSymbol < alphabet::Symbol > & /* node */, const regexp::UnboundedRegExpSymbol < alphabet::Symbol > & /* symbolptr */ ) { - return std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > > ( ); -} - -std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > > GlushkovFollow::Unbounded::visit ( const regexp::UnboundedRegExpEmpty < alphabet::Symbol > & /* node */, const regexp::UnboundedRegExpSymbol < alphabet::Symbol > & /* symbolptr */ ) { - return std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > > ( ); -} - -std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > > GlushkovFollow::Unbounded::visit ( const regexp::UnboundedRegExpEpsilon < alphabet::Symbol > & /* node */, const regexp::UnboundedRegExpSymbol < alphabet::Symbol > & /* symbolptr */ ) { - return std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > > ( ); -} - -} /* namespace regexp */ diff --git a/alib2algo/src/regexp/glushkov/GlushkovFollow.h b/alib2algo/src/regexp/glushkov/GlushkovFollow.h index 547e6b081c403a5bc51e5764701e824c9c3801e1..139a5998c82cecf86adc585f5bb265477b042b18 100644 --- a/alib2algo/src/regexp/glushkov/GlushkovFollow.h +++ b/alib2algo/src/regexp/glushkov/GlushkovFollow.h @@ -9,10 +9,25 @@ #define GLUSHKOV_FOLLOW_H_ #include <set> +#include <iterator> #include <regexp/unbounded/UnboundedRegExp.h> #include <regexp/RegExpFeatures.h> +#include <regexp/unbounded/UnboundedRegExpAlternation.h> +#include <regexp/unbounded/UnboundedRegExpConcatenation.h> +#include <regexp/unbounded/UnboundedRegExpElement.h> +#include <regexp/unbounded/UnboundedRegExpEmpty.h> +#include <regexp/unbounded/UnboundedRegExpEpsilon.h> +#include <regexp/unbounded/UnboundedRegExpIteration.h> +#include <regexp/unbounded/UnboundedRegExpSymbol.h> + +#include "GlushkovFirst.h" +#include "GlushkovLast.h" +#include "GlushkovPos.h" + +#include <regexp/properties/RegExpEpsilon.h> + namespace regexp { /** @@ -27,19 +42,90 @@ public: * @param symbol GlushkovSymbol for which we need the follow() * @return all symbols that can follow specific symbol in word */ - static std::set < UnboundedRegExpSymbol < alphabet::Symbol > > follow ( const regexp::UnboundedRegExp < > & re, const UnboundedRegExpSymbol < alphabet::Symbol > & symbol ); + template < class SymbolType > + static std::set < UnboundedRegExpSymbol < SymbolType > > follow ( const regexp::UnboundedRegExp < SymbolType > & re, const UnboundedRegExpSymbol < SymbolType > & symbol ); + template < class SymbolType > class Unbounded { public: - static std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > > visit ( const regexp::UnboundedRegExpAlternation < alphabet::Symbol > & node, const regexp::UnboundedRegExpSymbol < alphabet::Symbol > & symbFollow ); - static std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > > visit ( const regexp::UnboundedRegExpConcatenation < alphabet::Symbol > & node, const regexp::UnboundedRegExpSymbol < alphabet::Symbol > & symbFollow ); - static std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > > visit ( const regexp::UnboundedRegExpIteration < alphabet::Symbol > & node, const regexp::UnboundedRegExpSymbol < alphabet::Symbol > & symbFollow ); - static std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > > visit ( const regexp::UnboundedRegExpSymbol < alphabet::Symbol > & node, const regexp::UnboundedRegExpSymbol < alphabet::Symbol > & symbFollow ); - static std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > > visit ( const regexp::UnboundedRegExpEmpty < alphabet::Symbol > & node, const regexp::UnboundedRegExpSymbol < alphabet::Symbol > & symbFollow ); - static std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > > visit ( const regexp::UnboundedRegExpEpsilon < alphabet::Symbol > & node, const regexp::UnboundedRegExpSymbol < alphabet::Symbol > & symbFollow ); + static std::set < regexp::UnboundedRegExpSymbol < SymbolType > > visit ( const regexp::UnboundedRegExpAlternation < SymbolType > & node, const regexp::UnboundedRegExpSymbol < SymbolType > & symbFollow ); + static std::set < regexp::UnboundedRegExpSymbol < SymbolType > > visit ( const regexp::UnboundedRegExpConcatenation < SymbolType > & node, const regexp::UnboundedRegExpSymbol < SymbolType > & symbFollow ); + static std::set < regexp::UnboundedRegExpSymbol < SymbolType > > visit ( const regexp::UnboundedRegExpIteration < SymbolType > & node, const regexp::UnboundedRegExpSymbol < SymbolType > & symbFollow ); + static std::set < regexp::UnboundedRegExpSymbol < SymbolType > > visit ( const regexp::UnboundedRegExpSymbol < SymbolType > & node, const regexp::UnboundedRegExpSymbol < SymbolType > & symbFollow ); + static std::set < regexp::UnboundedRegExpSymbol < SymbolType > > visit ( const regexp::UnboundedRegExpEmpty < SymbolType > & node, const regexp::UnboundedRegExpSymbol < SymbolType > & symbFollow ); + static std::set < regexp::UnboundedRegExpSymbol < SymbolType > > visit ( const regexp::UnboundedRegExpEpsilon < SymbolType > & node, const regexp::UnboundedRegExpSymbol < SymbolType > & symbFollow ); }; }; +template < class SymbolType > +std::set < UnboundedRegExpSymbol < SymbolType > > GlushkovFollow::follow ( const regexp::UnboundedRegExp < SymbolType > & re, const UnboundedRegExpSymbol < SymbolType > & symbol ) { + return re.getRegExp ( ).getStructure ( ).template accept < std::set < regexp::UnboundedRegExpSymbol < SymbolType > >, GlushkovFollow::Unbounded < SymbolType > > ( symbol ); +} + +template < class SymbolType > +std::set < regexp::UnboundedRegExpSymbol < SymbolType > > GlushkovFollow::Unbounded < SymbolType >::visit ( const regexp::UnboundedRegExpAlternation < SymbolType > & node, const regexp::UnboundedRegExpSymbol < SymbolType > & symbolptr ) { + for ( auto const & element : node.getElements ( ) ) + if ( element->template accept < bool, GlushkovPos::Unbounded < SymbolType > > ( symbolptr ) ) + return element->template accept < std::set < regexp::UnboundedRegExpSymbol < SymbolType > >, GlushkovFollow::Unbounded < SymbolType > > ( symbolptr ); + + throw exception::CommonException ( "GlushkovFollow::Unbounded < SymbolType >::visit(Alt)" ); +} + +template < class SymbolType > +std::set < regexp::UnboundedRegExpSymbol < SymbolType > > GlushkovFollow::Unbounded < SymbolType >::visit ( const regexp::UnboundedRegExpConcatenation < SymbolType > & node, const regexp::UnboundedRegExpSymbol < SymbolType > & symbolptr ) { + std::set < regexp::UnboundedRegExpSymbol < SymbolType > > ret, tmp, lastSet; + + for ( auto e = node.getElements ( ).begin ( ); e != node.getElements ( ).end ( ); e++ ) { + if ( ! ( * e )->template accept < bool, GlushkovPos::Unbounded < SymbolType > > ( symbolptr ) ) + continue; + + tmp = ( * e )->template accept < std::set < regexp::UnboundedRegExpSymbol < SymbolType > >, GlushkovFollow::Unbounded < SymbolType > > ( symbolptr ); + ret.insert ( tmp.begin ( ), tmp.end ( ) ); + + lastSet = ( * e )->template accept < std::set < regexp::UnboundedRegExpSymbol < SymbolType > >, GlushkovLast::Unbounded < SymbolType > > ( ); + + if ( lastSet.find ( symbolptr ) != lastSet.end ( ) ) + for ( auto f = next ( e ); f != node.getElements ( ).end ( ); f++ ) { + tmp = ( * f )->template accept < std::set < regexp::UnboundedRegExpSymbol < SymbolType > >, GlushkovFirst::Unbounded < SymbolType > > ( ); + ret.insert ( tmp.begin ( ), tmp.end ( ) ); + + if ( ! regexp::properties::RegExpEpsilon::languageContainsEpsilon ( * * f ) ) + break; + } + + } + + return ret; +} + +template < class SymbolType > +std::set < regexp::UnboundedRegExpSymbol < SymbolType > > GlushkovFollow::Unbounded < SymbolType >::visit ( const regexp::UnboundedRegExpIteration < SymbolType > & node, const regexp::UnboundedRegExpSymbol < SymbolType > & symbolptr ) { + std::set < regexp::UnboundedRegExpSymbol < SymbolType > > ret = node.getElement ( ).template accept < std::set < regexp::UnboundedRegExpSymbol < SymbolType > >, GlushkovFollow::Unbounded < SymbolType > > ( symbolptr ); + std::set < regexp::UnboundedRegExpSymbol < SymbolType > > lastSet = node.getElement ( ).template accept < std::set < regexp::UnboundedRegExpSymbol < SymbolType > >, GlushkovLast::Unbounded < SymbolType > > ( ); + + if ( lastSet.find ( symbolptr ) != lastSet.end ( ) ) { + std::set < regexp::UnboundedRegExpSymbol < SymbolType > > firstSet = node.getElement ( ).template accept < std::set < regexp::UnboundedRegExpSymbol < SymbolType > >, GlushkovFirst::Unbounded < SymbolType > > ( ); + ret.insert ( firstSet.begin ( ), firstSet.end ( ) ); + } + + return ret; +} + +template < class SymbolType > +std::set < regexp::UnboundedRegExpSymbol < SymbolType > > GlushkovFollow::Unbounded < SymbolType >::visit ( const regexp::UnboundedRegExpSymbol < SymbolType > & /* node */, const regexp::UnboundedRegExpSymbol < SymbolType > & /* symbolptr */ ) { + return std::set < regexp::UnboundedRegExpSymbol < SymbolType > > ( ); +} + +template < class SymbolType > +std::set < regexp::UnboundedRegExpSymbol < SymbolType > > GlushkovFollow::Unbounded < SymbolType >::visit ( const regexp::UnboundedRegExpEmpty < SymbolType > & /* node */, const regexp::UnboundedRegExpSymbol < SymbolType > & /* symbolptr */ ) { + return std::set < regexp::UnboundedRegExpSymbol < SymbolType > > ( ); +} + +template < class SymbolType > +std::set < regexp::UnboundedRegExpSymbol < SymbolType > > GlushkovFollow::Unbounded < SymbolType >::visit ( const regexp::UnboundedRegExpEpsilon < SymbolType > & /* node */, const regexp::UnboundedRegExpSymbol < SymbolType > & /* symbolptr */ ) { + return std::set < regexp::UnboundedRegExpSymbol < SymbolType > > ( ); +} + } /* namespace regexp */ #endif /* GLUSHKOV_FOLLOW_H_ */ diff --git a/alib2algo/src/regexp/glushkov/GlushkovIndexate.cpp b/alib2algo/src/regexp/glushkov/GlushkovIndexate.cpp index 9ee7de078c3acef3c17dfc162be97b2c5f687629..8d747c6b52ccabf7010f91271324ba0e93128b84 100644 --- a/alib2algo/src/regexp/glushkov/GlushkovIndexate.cpp +++ b/alib2algo/src/regexp/glushkov/GlushkovIndexate.cpp @@ -25,8 +25,6 @@ alphabet::Symbol GlushkovIndexate::getSymbolFromGlushkovPair ( const alphabet::S return symbolPair.getData ( ).first; } -// ----------------------------------------------------------------------------- - UnboundedRegExp < > GlushkovIndexate::index ( const regexp::UnboundedRegExp < > & re ) { int i = 1; diff --git a/alib2algo/src/regexp/glushkov/GlushkovLast.cpp b/alib2algo/src/regexp/glushkov/GlushkovLast.cpp deleted file mode 100644 index e8e52bbf0b381de9e129c37ff795f2b8020b9ac7..0000000000000000000000000000000000000000 --- a/alib2algo/src/regexp/glushkov/GlushkovLast.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/* - * GlushkovLast::Unbounded.cpp - * - * Created on: 13. 3. 2014 - * Author: Tomas Pecka - */ - -#include "GlushkovLast.h" -#include <regexp/unbounded/UnboundedRegExpAlternation.h> -#include <regexp/unbounded/UnboundedRegExpConcatenation.h> -#include <regexp/unbounded/UnboundedRegExpElement.h> -#include <regexp/unbounded/UnboundedRegExpEmpty.h> -#include <regexp/unbounded/UnboundedRegExpEpsilon.h> -#include <regexp/unbounded/UnboundedRegExpIteration.h> -#include <regexp/unbounded/UnboundedRegExpSymbol.h> - -#include "../properties/RegExpEpsilon.h" - -namespace regexp { - -std::set < UnboundedRegExpSymbol < alphabet::Symbol > > GlushkovLast::last ( const regexp::UnboundedRegExp < > & re ) { - return re.getRegExp ( ).getStructure ( ).accept < std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > >, GlushkovLast::Unbounded > ( ); -} - -std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > > GlushkovLast::Unbounded::visit ( const regexp::UnboundedRegExpAlternation < alphabet::Symbol > & node ) { - std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > > ret; - - for ( const auto & element : node.getElements ( ) ) { - std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > > tmp = element->accept < std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > >, GlushkovLast::Unbounded > ( ); - ret.insert ( tmp.begin ( ), tmp.end ( ) ); - } - - return ret; -} - -std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > > GlushkovLast::Unbounded::visit ( const regexp::UnboundedRegExpConcatenation < alphabet::Symbol > & node ) { - std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > > ret; - - for ( const auto & element : std::make_reverse ( node.getElements ( ) ) ) { - std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > > tmp = element->accept < std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > >, GlushkovLast::Unbounded > ( ); - ret.insert ( tmp.begin ( ), tmp.end ( ) ); - - if ( !regexp::properties::RegExpEpsilon::languageContainsEpsilon ( * element ) ) - break; - } - - return ret; -} - -std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > > GlushkovLast::Unbounded::visit ( const regexp::UnboundedRegExpIteration < alphabet::Symbol > & node ) { - return node.getElement ( ).accept < std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > >, GlushkovLast::Unbounded > ( ); -} - -std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > > GlushkovLast::Unbounded::visit ( const regexp::UnboundedRegExpSymbol < alphabet::Symbol > & node ) { - return std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > > { node }; -} - -std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > > GlushkovLast::Unbounded::visit ( const regexp::UnboundedRegExpEpsilon < alphabet::Symbol > & /* node */ ) { - return std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > > ( ); -} - -std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > > GlushkovLast::Unbounded::visit ( const regexp::UnboundedRegExpEmpty < alphabet::Symbol > & /* node */ ) { - return std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > > ( ); -} - -} /* namespace regexp */ diff --git a/alib2algo/src/regexp/glushkov/GlushkovLast.h b/alib2algo/src/regexp/glushkov/GlushkovLast.h index acb9c651c77a717693e8191d8e601e7ff5cec373..cf71bfa501e13b98860cdefbda7227a4f6c2fc44 100644 --- a/alib2algo/src/regexp/glushkov/GlushkovLast.h +++ b/alib2algo/src/regexp/glushkov/GlushkovLast.h @@ -13,6 +13,16 @@ #include <regexp/unbounded/UnboundedRegExp.h> #include <regexp/RegExpFeatures.h> +#include <regexp/unbounded/UnboundedRegExpAlternation.h> +#include <regexp/unbounded/UnboundedRegExpConcatenation.h> +#include <regexp/unbounded/UnboundedRegExpElement.h> +#include <regexp/unbounded/UnboundedRegExpEmpty.h> +#include <regexp/unbounded/UnboundedRegExpEpsilon.h> +#include <regexp/unbounded/UnboundedRegExpIteration.h> +#include <regexp/unbounded/UnboundedRegExpSymbol.h> + +#include <regexp/properties/RegExpEpsilon.h> + namespace regexp { /** @@ -26,19 +36,73 @@ public: * @param re RegExp to probe * @return all RegExpSymbols that can terminate the word. */ - static std::set < UnboundedRegExpSymbol < alphabet::Symbol > > last ( const regexp::UnboundedRegExp < > & re ); + template < class SymbolType > + static std::set < UnboundedRegExpSymbol < SymbolType > > last ( const regexp::UnboundedRegExp < SymbolType > & re ); + template < class SymbolType > class Unbounded { public: - static std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > > visit ( const regexp::UnboundedRegExpAlternation < alphabet::Symbol > & node ); - static std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > > visit ( const regexp::UnboundedRegExpConcatenation < alphabet::Symbol > & node ); - static std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > > visit ( const regexp::UnboundedRegExpIteration < alphabet::Symbol > & node ); - static std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > > visit ( const regexp::UnboundedRegExpSymbol < alphabet::Symbol > & node ); - static std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > > visit ( const regexp::UnboundedRegExpEmpty < alphabet::Symbol > & node ); - static std::set < regexp::UnboundedRegExpSymbol < alphabet::Symbol > > visit ( const regexp::UnboundedRegExpEpsilon < alphabet::Symbol > & node ); + static std::set < regexp::UnboundedRegExpSymbol < SymbolType > > visit ( const regexp::UnboundedRegExpAlternation < SymbolType > & node ); + static std::set < regexp::UnboundedRegExpSymbol < SymbolType > > visit ( const regexp::UnboundedRegExpConcatenation < SymbolType > & node ); + static std::set < regexp::UnboundedRegExpSymbol < SymbolType > > visit ( const regexp::UnboundedRegExpIteration < SymbolType > & node ); + static std::set < regexp::UnboundedRegExpSymbol < SymbolType > > visit ( const regexp::UnboundedRegExpSymbol < SymbolType > & node ); + static std::set < regexp::UnboundedRegExpSymbol < SymbolType > > visit ( const regexp::UnboundedRegExpEmpty < SymbolType > & node ); + static std::set < regexp::UnboundedRegExpSymbol < SymbolType > > visit ( const regexp::UnboundedRegExpEpsilon < SymbolType > & node ); }; }; +template < class SymbolType > +std::set < UnboundedRegExpSymbol < SymbolType > > GlushkovLast::last ( const regexp::UnboundedRegExp < SymbolType > & re ) { + return re.getRegExp ( ).getStructure ( ).template accept < std::set < regexp::UnboundedRegExpSymbol < SymbolType > >, GlushkovLast::Unbounded < SymbolType > > ( ); +} + +template < class SymbolType > +std::set < regexp::UnboundedRegExpSymbol < SymbolType > > GlushkovLast::Unbounded < SymbolType >::visit ( const regexp::UnboundedRegExpAlternation < SymbolType > & node ) { + std::set < regexp::UnboundedRegExpSymbol < SymbolType > > ret; + + for ( const auto & element : node.getElements ( ) ) { + std::set < regexp::UnboundedRegExpSymbol < SymbolType > > tmp = element->template accept < std::set < regexp::UnboundedRegExpSymbol < SymbolType > >, GlushkovLast::Unbounded < SymbolType > > ( ); + ret.insert ( tmp.begin ( ), tmp.end ( ) ); + } + + return ret; +} + +template < class SymbolType > +std::set < regexp::UnboundedRegExpSymbol < SymbolType > > GlushkovLast::Unbounded < SymbolType >::visit ( const regexp::UnboundedRegExpConcatenation < SymbolType > & node ) { + std::set < regexp::UnboundedRegExpSymbol < SymbolType > > ret; + + for ( const auto & element : std::make_reverse ( node.getElements ( ) ) ) { + std::set < regexp::UnboundedRegExpSymbol < SymbolType > > tmp = element->template accept < std::set < regexp::UnboundedRegExpSymbol < SymbolType > >, GlushkovLast::Unbounded < SymbolType > > ( ); + ret.insert ( tmp.begin ( ), tmp.end ( ) ); + + if ( ! regexp::properties::RegExpEpsilon::languageContainsEpsilon ( * element ) ) + break; + } + + return ret; +} + +template < class SymbolType > +std::set < regexp::UnboundedRegExpSymbol < SymbolType > > GlushkovLast::Unbounded < SymbolType >::visit ( const regexp::UnboundedRegExpIteration < SymbolType > & node ) { + return node.getElement ( ).template accept < std::set < regexp::UnboundedRegExpSymbol < SymbolType > >, GlushkovLast::Unbounded < SymbolType > > ( ); +} + +template < class SymbolType > +std::set < regexp::UnboundedRegExpSymbol < SymbolType > > GlushkovLast::Unbounded < SymbolType >::visit ( const regexp::UnboundedRegExpSymbol < SymbolType > & node ) { + return std::set < regexp::UnboundedRegExpSymbol < SymbolType > > { node }; +} + +template < class SymbolType > +std::set < regexp::UnboundedRegExpSymbol < SymbolType > > GlushkovLast::Unbounded < SymbolType >::visit ( const regexp::UnboundedRegExpEpsilon < SymbolType > & /* node */ ) { + return std::set < regexp::UnboundedRegExpSymbol < SymbolType > > ( ); +} + +template < class SymbolType > +std::set < regexp::UnboundedRegExpSymbol < SymbolType > > GlushkovLast::Unbounded < SymbolType >::visit ( const regexp::UnboundedRegExpEmpty < SymbolType > & /* node */ ) { + return std::set < regexp::UnboundedRegExpSymbol < SymbolType > > ( ); +} + } /* namespace regexp */ #endif /* GLUSHKOV_LAST_H_ */ diff --git a/alib2algo/src/regexp/glushkov/GlushkovPos.cpp b/alib2algo/src/regexp/glushkov/GlushkovPos.cpp deleted file mode 100644 index 682b312d4c06c425f9b6e35dfd6b45cf33aa7c21..0000000000000000000000000000000000000000 --- a/alib2algo/src/regexp/glushkov/GlushkovPos.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/* - * GlushkovTraversal.cpp - * - * Created on: 13. 3. 2014 - * Author: Tomas Pecka - */ - -#include "GlushkovPos.h" -#include <regexp/unbounded/UnboundedRegExpAlternation.h> -#include <regexp/unbounded/UnboundedRegExpConcatenation.h> -#include <regexp/unbounded/UnboundedRegExpElement.h> -#include <regexp/unbounded/UnboundedRegExpEmpty.h> -#include <regexp/unbounded/UnboundedRegExpEpsilon.h> -#include <regexp/unbounded/UnboundedRegExpIteration.h> -#include <regexp/unbounded/UnboundedRegExpSymbol.h> - -namespace regexp { - -bool GlushkovPos::pos ( const UnboundedRegExpSymbol < alphabet::Symbol > & symbol, const regexp::UnboundedRegExp < > & node ) { - return node.getRegExp ( ).getStructure ( ).accept < bool, GlushkovPos::Unbounded > ( symbol ); -} - -bool GlushkovPos::Unbounded::visit ( const regexp::UnboundedRegExpAlternation < alphabet::Symbol > & node, const regexp::UnboundedRegExpSymbol < alphabet::Symbol > & symbol ) { - for ( const auto & element : node.getElements ( ) ) - if ( element->accept < bool, GlushkovPos::Unbounded > ( symbol ) ) - return true; - - return false; -} - -bool GlushkovPos::Unbounded::visit ( const regexp::UnboundedRegExpConcatenation < alphabet::Symbol > & node, const regexp::UnboundedRegExpSymbol < alphabet::Symbol > & symbol ) { - for ( const auto & element : node.getElements ( ) ) - if ( element->accept < bool, GlushkovPos::Unbounded > ( symbol ) ) - return true; - - return false; -} - -bool GlushkovPos::Unbounded::visit ( const regexp::UnboundedRegExpIteration < alphabet::Symbol > & node, const regexp::UnboundedRegExpSymbol < alphabet::Symbol > & symbol ) { - return node.getElement ( ).accept < bool, GlushkovPos::Unbounded > ( symbol ); -} - -bool GlushkovPos::Unbounded::visit ( const regexp::UnboundedRegExpSymbol < alphabet::Symbol > & node, const regexp::UnboundedRegExpSymbol < alphabet::Symbol > & symbol ) { - return symbol == node; -} - -bool GlushkovPos::Unbounded::visit ( const regexp::UnboundedRegExpEmpty < alphabet::Symbol > & /* node */, const regexp::UnboundedRegExpSymbol < alphabet::Symbol > & /* symbol */ ) { - return false; -} - -bool GlushkovPos::Unbounded::visit ( const regexp::UnboundedRegExpEpsilon < alphabet::Symbol > & /* node */, const regexp::UnboundedRegExpSymbol < alphabet::Symbol > & /* symbol */ ) { - return false; -} - -} /* namespace regexp */ diff --git a/alib2algo/src/regexp/glushkov/GlushkovPos.h b/alib2algo/src/regexp/glushkov/GlushkovPos.h index cffeafcbb04d1598491c8a0f8673297ad0816f3d..c6cb444f439db42f69dade585f833f0f9aa9963a 100644 --- a/alib2algo/src/regexp/glushkov/GlushkovPos.h +++ b/alib2algo/src/regexp/glushkov/GlushkovPos.h @@ -11,6 +11,14 @@ #include <regexp/unbounded/UnboundedRegExp.h> #include <regexp/RegExpFeatures.h> +#include <regexp/unbounded/UnboundedRegExpAlternation.h> +#include <regexp/unbounded/UnboundedRegExpConcatenation.h> +#include <regexp/unbounded/UnboundedRegExpElement.h> +#include <regexp/unbounded/UnboundedRegExpEmpty.h> +#include <regexp/unbounded/UnboundedRegExpEpsilon.h> +#include <regexp/unbounded/UnboundedRegExpIteration.h> +#include <regexp/unbounded/UnboundedRegExpSymbol.h> + namespace regexp { /** @@ -23,19 +31,64 @@ public: /** * @return bool true if symbol is in this regexp */ - static bool pos ( const UnboundedRegExpSymbol < alphabet::Symbol > & symbol, const regexp::UnboundedRegExp < > & node ); + template < class SymbolType > + static bool pos ( const UnboundedRegExpSymbol < SymbolType > & symbol, const regexp::UnboundedRegExp < SymbolType > & node ); + template < class SymbolType > class Unbounded { public: - static bool visit ( const regexp::UnboundedRegExpAlternation < alphabet::Symbol > & node, const regexp::UnboundedRegExpSymbol < alphabet::Symbol > & symbSearch ); - static bool visit ( const regexp::UnboundedRegExpConcatenation < alphabet::Symbol > & node, const regexp::UnboundedRegExpSymbol < alphabet::Symbol > & symbSearch ); - static bool visit ( const regexp::UnboundedRegExpIteration < alphabet::Symbol > & node, const regexp::UnboundedRegExpSymbol < alphabet::Symbol > & symbSearch ); - static bool visit ( const regexp::UnboundedRegExpSymbol < alphabet::Symbol > & node, const regexp::UnboundedRegExpSymbol < alphabet::Symbol > & symbSearch ); - static bool visit ( const regexp::UnboundedRegExpEmpty < alphabet::Symbol > & node, const regexp::UnboundedRegExpSymbol < alphabet::Symbol > & symbSearch ); - static bool visit ( const regexp::UnboundedRegExpEpsilon < alphabet::Symbol > & node, const regexp::UnboundedRegExpSymbol < alphabet::Symbol > & symbSearch ); + static bool visit ( const regexp::UnboundedRegExpAlternation < SymbolType > & node, const regexp::UnboundedRegExpSymbol < SymbolType > & symbSearch ); + static bool visit ( const regexp::UnboundedRegExpConcatenation < SymbolType > & node, const regexp::UnboundedRegExpSymbol < SymbolType > & symbSearch ); + static bool visit ( const regexp::UnboundedRegExpIteration < SymbolType > & node, const regexp::UnboundedRegExpSymbol < SymbolType > & symbSearch ); + static bool visit ( const regexp::UnboundedRegExpSymbol < SymbolType > & node, const regexp::UnboundedRegExpSymbol < SymbolType > & symbSearch ); + static bool visit ( const regexp::UnboundedRegExpEmpty < SymbolType > & node, const regexp::UnboundedRegExpSymbol < SymbolType > & symbSearch ); + static bool visit ( const regexp::UnboundedRegExpEpsilon < SymbolType > & node, const regexp::UnboundedRegExpSymbol < SymbolType > & symbSearch ); }; }; +template < class SymbolType > +bool GlushkovPos::pos ( const UnboundedRegExpSymbol < SymbolType > & symbol, const regexp::UnboundedRegExp < SymbolType > & node ) { + return node.getRegExp ( ).getStructure ( ).template accept < bool, GlushkovPos::Unbounded < SymbolType > > ( symbol ); +} + +template < class SymbolType > +bool GlushkovPos::Unbounded < SymbolType >::visit ( const regexp::UnboundedRegExpAlternation < SymbolType > & node, const regexp::UnboundedRegExpSymbol < SymbolType > & symbol ) { + for ( const auto & element : node.getElements ( ) ) + if ( element->template accept < bool, GlushkovPos::Unbounded < SymbolType > > ( symbol ) ) + return true; + + return false; +} + +template < class SymbolType > +bool GlushkovPos::Unbounded < SymbolType >::visit ( const regexp::UnboundedRegExpConcatenation < SymbolType > & node, const regexp::UnboundedRegExpSymbol < SymbolType > & symbol ) { + for ( const auto & element : node.getElements ( ) ) + if ( element->template accept < bool, GlushkovPos::Unbounded < SymbolType > > ( symbol ) ) + return true; + + return false; +} + +template < class SymbolType > +bool GlushkovPos::Unbounded < SymbolType >::visit ( const regexp::UnboundedRegExpIteration < SymbolType > & node, const regexp::UnboundedRegExpSymbol < SymbolType > & symbol ) { + return node.getElement ( ).template accept < bool, GlushkovPos::Unbounded < SymbolType > > ( symbol ); +} + +template < class SymbolType > +bool GlushkovPos::Unbounded < SymbolType >::visit ( const regexp::UnboundedRegExpSymbol < SymbolType > & node, const regexp::UnboundedRegExpSymbol < SymbolType > & symbol ) { + return symbol == node; +} + +template < class SymbolType > +bool GlushkovPos::Unbounded < SymbolType >::visit ( const regexp::UnboundedRegExpEmpty < SymbolType > & /* node */, const regexp::UnboundedRegExpSymbol < SymbolType > & /* symbol */ ) { + return false; +} + +template < class SymbolType > +bool GlushkovPos::Unbounded < SymbolType >::visit ( const regexp::UnboundedRegExpEpsilon < SymbolType > & /* node */, const regexp::UnboundedRegExpSymbol < SymbolType > & /* symbol */ ) { + return false; +} + } /* namespace regexp */ #endif /* GLUSHKOV_POS_H_ */