diff --git a/alib2algo/src/equations/LeftRegularEquationSolver.cpp b/alib2algo/src/equations/LeftRegularEquationSolver.cpp index 6d404df1d30f9147c89de12be6970c599e950a5f..cc9fed801761292214289595d2801af941658e28 100644 --- a/alib2algo/src/equations/LeftRegularEquationSolver.cpp +++ b/alib2algo/src/equations/LeftRegularEquationSolver.cpp @@ -24,6 +24,7 @@ regexp::UnboundedRegExp LeftRegularEquationSolver::eliminate( void ) { * => A = 10*B + 20*C */ regexp::UnboundedRegExpIteration loop( std::move( m_eqTransition[ a ][ a ] ) ); + opt.optimize( loop ); // for all transitions from A apply Arden's Lemma for( auto itB = std::next( itA ) ; itB != m_symbolsByDepth.rend( ); itB ++ ) { @@ -34,6 +35,7 @@ regexp::UnboundedRegExp LeftRegularEquationSolver::eliminate( void ) { regexp::UnboundedRegExpAlternation alt; alt.appendElement( std::move( concat ) ); m_eqTransition[ a ][ b ] = std::move( alt ); + opt.optimize( m_eqTransition[ a ][ b ] ); } regexp::UnboundedRegExpConcatenation concat; concat.appendElement( std::move( m_eqFinal[ a ] ) ); @@ -41,6 +43,7 @@ regexp::UnboundedRegExp LeftRegularEquationSolver::eliminate( void ) { regexp::UnboundedRegExpAlternation alt; alt.appendElement( std::move( concat ) ); m_eqFinal[ a ] = std::move( alt ); + opt.optimize( m_eqFinal[ a ] ); /* * eliminate A from rest of the equations using this pattern: @@ -58,7 +61,8 @@ regexp::UnboundedRegExp LeftRegularEquationSolver::eliminate( void ) { regexp::UnboundedRegExpAlternation alt; alt.appendElement( std::move( m_eqTransition[ b ][ c ] ) ); alt.appendElement( std::move( concat ) ); - m_eqTransition[ b ][ c ] = /* opt.optimize( */ std::move( alt ) /* ) */; + m_eqTransition[ b ][ c ] = std::move( alt ); + opt.optimize( m_eqTransition[ b ][ c ] ); } regexp::UnboundedRegExpConcatenation concat; @@ -67,7 +71,8 @@ regexp::UnboundedRegExp LeftRegularEquationSolver::eliminate( void ) { regexp::UnboundedRegExpAlternation alt; alt.appendElement( std::move( m_eqFinal[ b ] ) ); alt.appendElement( std::move( concat ) ); - m_eqFinal[ b ] = /* opt.optimize( */ std::move( alt ) /* ) */; + m_eqFinal[ b ] = std::move( alt ); + opt.optimize( m_eqFinal[ b ] ); } } diff --git a/alib2algo/src/equations/RightRegularEquationSolver.cpp b/alib2algo/src/equations/RightRegularEquationSolver.cpp index 4a1ecbe5ae15c9767d851a831bac50bead72d802..b9d1dac2ea680a800396236f035b452b9d541d50 100644 --- a/alib2algo/src/equations/RightRegularEquationSolver.cpp +++ b/alib2algo/src/equations/RightRegularEquationSolver.cpp @@ -24,6 +24,7 @@ regexp::UnboundedRegExp RightRegularEquationSolver::eliminate( void ) { * => A = 0*1B + 0*2C */ regexp::UnboundedRegExpIteration loop( std::move( m_eqTransition[ a ][ a ] ) ); + opt.optimize( loop ); // for all transitions from A apply Arden's Lemma for( auto itB = std::next( itA ) ; itB != m_symbolsByDepth.rend( ); itB ++ ) { @@ -34,6 +35,7 @@ regexp::UnboundedRegExp RightRegularEquationSolver::eliminate( void ) { regexp::UnboundedRegExpAlternation alt; alt.appendElement( std::move( concat ) ); m_eqTransition[ a ][ b ] = std::move( alt ); + opt.optimize( m_eqTransition[ a ][ b ] ); } regexp::UnboundedRegExpConcatenation concat; concat.appendElement( std::move( loop ) ); @@ -41,6 +43,7 @@ regexp::UnboundedRegExp RightRegularEquationSolver::eliminate( void ) { regexp::UnboundedRegExpAlternation alt; alt.appendElement( std::move( concat ) ); m_eqFinal[ a ] = std::move( alt ); + opt.optimize( m_eqFinal[ a ] ); /* * eliminate A from rest of the equations using this pattern: @@ -59,6 +62,7 @@ regexp::UnboundedRegExp RightRegularEquationSolver::eliminate( void ) { alt.appendElement( std::move( m_eqTransition[ b ][ c ] ) ); alt.appendElement( std::move( concat ) ); m_eqTransition[ b ][ c ] = std::move( alt ); + opt.optimize( m_eqTransition[ b ][ c ] ); } regexp::UnboundedRegExpConcatenation concat; @@ -68,6 +72,7 @@ regexp::UnboundedRegExp RightRegularEquationSolver::eliminate( void ) { alt.appendElement( std::move( m_eqFinal[ b ] ) ); alt.appendElement( std::move( concat ) ); m_eqFinal[ b ] = std::move( alt ); + opt.optimize( m_eqFinal[ b ] ); } } diff --git a/alib2algo/src/regexp/RegExpOptimize.cpp b/alib2algo/src/regexp/RegExpOptimize.cpp index 0d247c7493db38d16aa107face5d2bd9063fbf61..e4c84ffc635658eac896fecec462d51f5274b1b5 100644 --- a/alib2algo/src/regexp/RegExpOptimize.cpp +++ b/alib2algo/src/regexp/RegExpOptimize.cpp @@ -2,7 +2,7 @@ * RegExpOptimize.cpp * * Created on: 20. 1. 2014 - * Author: Tomas Pecka + * Author: Tomas Pecka */ #include "RegExpOptimize.h" @@ -15,136 +15,184 @@ namespace regexp { UnboundedRegExp RegExpOptimize::optimize( UnboundedRegExp const & regexp ) { - UnboundedRegExpElement* optimized = optimize( & regexp.getRegExp( ) ); + UnboundedRegExpElement* optimized = optimize( & regexp.getRegExp( ) ); - UnboundedRegExp ret( std::move( * optimized ) ); + UnboundedRegExp ret( std::move( * optimized ) ); - delete optimized; + delete optimized; - return ret; + return ret; +} + +void RegExpOptimize::optimize( UnboundedRegExpElement & element ) { + UnboundedRegExpElement* optimized = optimize( & element ); + + UnboundedRegExpAlternation * alternation = dynamic_cast<UnboundedRegExpAlternation *>( & element ); + if( alternation ) { + UnboundedRegExpAlternation * alternationOptimized = dynamic_cast<UnboundedRegExpAlternation *>( optimized ); + if( alternationOptimized ) { + * alternation = std::move( * alternationOptimized ); + delete alternationOptimized; + } else { + * alternation = UnboundedRegExpAlternation { }; + alternation->appendElement( std::move( * optimized ) ); + delete optimized; + } + return; + } + + UnboundedRegExpConcatenation * concatenation = dynamic_cast<UnboundedRegExpConcatenation *>( & element ); + if( concatenation ) { + UnboundedRegExpConcatenation * concatenationOptimized = dynamic_cast<UnboundedRegExpConcatenation *>( optimized ); + if( concatenationOptimized ) { + * concatenation = std::move( * concatenationOptimized ); + delete concatenationOptimized; + } else { + * concatenation = UnboundedRegExpConcatenation { }; + concatenation->appendElement( std::move( * optimized ) ); + delete optimized; + } + return; + } + + UnboundedRegExpIteration * iteration = dynamic_cast<UnboundedRegExpIteration *>( & element ); + if( iteration ) { + UnboundedRegExpIteration * iterationOptimized = dynamic_cast<UnboundedRegExpIteration *>( optimized ); + if( iterationOptimized ) { + * iteration = std::move( * iterationOptimized ); + delete iterationOptimized; + } else { + * iteration = UnboundedRegExpIteration { std::move( * optimized ) }; + delete optimized; + } + return; + } + + // Nothing to optimize original element was UnboundedRegExpSymbol, UnboundedRegExpEpsilon, or UnboundedRegExpEmpty + return; } UnboundedRegExpElement* RegExpOptimize::optimize( UnboundedRegExpElement const * const & node ) { - const UnboundedRegExpAlternation * alternation = dynamic_cast<const UnboundedRegExpAlternation*>( node ); - if( alternation ) - return optimize( alternation ); + const UnboundedRegExpAlternation * alternation = dynamic_cast<const UnboundedRegExpAlternation*>( node ); + if( alternation ) + return optimize( alternation ); - const UnboundedRegExpConcatenation * concatenation = dynamic_cast<const UnboundedRegExpConcatenation*>( node ); - if( concatenation ) - return optimize( concatenation ); + const UnboundedRegExpConcatenation * concatenation = dynamic_cast<const UnboundedRegExpConcatenation*>( node ); + if( concatenation ) + return optimize( concatenation ); - const UnboundedRegExpIteration * iteration = dynamic_cast<const UnboundedRegExpIteration*>( node ); - if( iteration ) - return optimize( iteration ); + const UnboundedRegExpIteration * iteration = dynamic_cast<const UnboundedRegExpIteration*>( node ); + if( iteration ) + return optimize( iteration ); - const UnboundedRegExpSymbol * symbol = dynamic_cast<const UnboundedRegExpSymbol*>( node ); - if( symbol ) - return optimize( symbol ); + const UnboundedRegExpSymbol * symbol = dynamic_cast<const UnboundedRegExpSymbol*>( node ); + if( symbol ) + return optimize( symbol ); - const UnboundedRegExpEmpty * empty= dynamic_cast<const UnboundedRegExpEmpty*>( node ); - if( empty ) - return optimize( empty ); + const UnboundedRegExpEmpty * empty= dynamic_cast<const UnboundedRegExpEmpty*>( node ); + if( empty ) + return optimize( empty ); - const UnboundedRegExpEpsilon * eps = dynamic_cast<const UnboundedRegExpEpsilon*>( node ); - if( eps ) - return optimize( eps ); + const UnboundedRegExpEpsilon * eps = dynamic_cast<const UnboundedRegExpEpsilon*>( node ); + if( eps ) + return optimize( eps ); - throw exception::AlibException( "RegExpOptimize::optimize - unknown UnboundedRegExpElement node" ); + throw exception::AlibException( "RegExpOptimize::optimize - unknown UnboundedRegExpElement node" ); } UnboundedRegExpElement * RegExpOptimize::optimize( UnboundedRegExpAlternation const * const & node ) { - UnboundedRegExpAlternation* alt = new UnboundedRegExpAlternation( ); + UnboundedRegExpAlternation* alt = new UnboundedRegExpAlternation( ); - for( const auto & child : node->elements ) - alt->elements.push_back( optimize( child ) ); + for( const auto & child : node->elements ) + alt->elements.push_back( optimize( child ) ); - // optimize while you can - while( A1( alt ) || A2( alt ) || A3( alt ) || A4( alt ) || A10( alt ) || V2( alt ) || V5( alt ) || V6( alt ) || X1( alt ) ); + // optimize while you can + while( A1( alt ) || A2( alt ) || A3( alt ) || A4( alt ) || A10( alt ) || V2( alt ) || V5( alt ) || V6( alt ) || X1( alt ) ); - if( alt->elements.size( ) == 1 ) - { - UnboundedRegExpElement* ret = alt->elements.front( ); - alt->elements.clear( ); - delete alt; - return ret; - } + if( alt->elements.size( ) == 1 ) + { + UnboundedRegExpElement* ret = alt->elements.front( ); + alt->elements.clear( ); + delete alt; + return ret; + } - if( alt->elements.size( ) == 0 ) { - delete alt; - return new UnboundedRegExpEmpty( ); - } + if( alt->elements.size( ) == 0 ) { + delete alt; + return new UnboundedRegExpEmpty( ); + } - return alt; + return alt; } UnboundedRegExpElement * RegExpOptimize::optimize( UnboundedRegExpConcatenation const * const & node ) { - UnboundedRegExpConcatenation* concat = new UnboundedRegExpConcatenation( ); - - for( const auto & child : node->elements ) - concat->elements.push_back( optimize( child ) ); - - do - { - // A7 is implemented here ~ if not here, it went into infinite loop FIXME - if( std::any_of( concat->elements.begin( ), concat->elements.end( ), []( UnboundedRegExpElement const * const & a ) -> bool{ return dynamic_cast<UnboundedRegExpEmpty const *>( a ); } ) ) - { - delete concat; - return new UnboundedRegExpEmpty( ); - } - } - while( A5( concat ) || A6( concat ) || /* A7( concat ) || */ A8( concat ) || A9( concat ) || V8( concat ) );//|| V9( concat ) ); - - if( concat->elements.size( ) == 1 ) - { - UnboundedRegExpElement* ret = concat->elements.front( ); - concat->elements.clear( ); - delete concat; - return ret; - } - - if( concat->elements.size( ) == 0 ) { - delete concat; - return new UnboundedRegExpEpsilon( ); - } - - return concat; + UnboundedRegExpConcatenation* concat = new UnboundedRegExpConcatenation( ); + + for( const auto & child : node->elements ) + concat->elements.push_back( optimize( child ) ); + + do + { + // A7 is implemented here ~ if not here, it went into infinite loop FIXME + if( std::any_of( concat->elements.begin( ), concat->elements.end( ), []( UnboundedRegExpElement const * const & a ) -> bool{ return dynamic_cast<UnboundedRegExpEmpty const *>( a ); } ) ) + { + delete concat; + return new UnboundedRegExpEmpty( ); + } + } + while( A5( concat ) || A6( concat ) || /* A7( concat ) || */ A8( concat ) || A9( concat ) || V8( concat ) );//|| V9( concat ) ); + + if( concat->elements.size( ) == 1 ) + { + UnboundedRegExpElement* ret = concat->elements.front( ); + concat->elements.clear( ); + delete concat; + return ret; + } + + if( concat->elements.size( ) == 0 ) { + delete concat; + return new UnboundedRegExpEpsilon( ); + } + + return concat; } UnboundedRegExpElement * RegExpOptimize::optimize( UnboundedRegExpIteration const * const & node ) { - UnboundedRegExpIteration* iter = new UnboundedRegExpIteration(* optimize( node->element ) ); - - do - { - // V1 is implemented right here - if( dynamic_cast<UnboundedRegExpEmpty*>( iter->element ) ) - { - delete iter; - return new UnboundedRegExpEpsilon( ); - } - } - while( A11( iter ) || V1( iter ) || V3( iter ) || V4( iter ) || V10( iter ) ); - - return iter; + UnboundedRegExpIteration* iter = new UnboundedRegExpIteration(* optimize( node->element ) ); + + do + { + // V1 is implemented right here + if( dynamic_cast<UnboundedRegExpEmpty*>( iter->element ) ) + { + delete iter; + return new UnboundedRegExpEpsilon( ); + } + } + while( A11( iter ) || V1( iter ) || V3( iter ) || V4( iter ) || V10( iter ) ); + + return iter; } UnboundedRegExpElement * RegExpOptimize::optimize( UnboundedRegExpSymbol const * const & node ) { - return node->clone( ); + return node->clone( ); } UnboundedRegExpElement * RegExpOptimize::optimize( UnboundedRegExpEmpty const * const & node ) { - return node->clone( ); + return node->clone( ); } UnboundedRegExpElement * RegExpOptimize::optimize( UnboundedRegExpEpsilon const * const & node ) { - return node->clone( ); + return node->clone( ); } // ---------------------------------------------------------------------------- @@ -156,34 +204,34 @@ UnboundedRegExpElement * RegExpOptimize::optimize( UnboundedRegExpEpsilon const */ bool RegExpOptimize::A1( UnboundedRegExpAlternation * const & node ) { - bool optimized = false; + bool optimized = false; - for( auto it = node->elements.begin( ); it != node->elements.end( ); ) - { - UnboundedRegExpAlternation * const & childUnboundedRegExpAlternation = dynamic_cast<UnboundedRegExpAlternation *>( * it ); + for( auto it = node->elements.begin( ); it != node->elements.end( ); ) + { + UnboundedRegExpAlternation * const & childUnboundedRegExpAlternation = dynamic_cast<UnboundedRegExpAlternation *>( * it ); - if( childUnboundedRegExpAlternation ) - { - it = node->elements.erase( it ); + if( childUnboundedRegExpAlternation ) + { + it = node->elements.erase( it ); - size_t off = it - node->elements.begin(); - node->elements.insert( it, childUnboundedRegExpAlternation->elements.begin( ), childUnboundedRegExpAlternation->elements.end( ) ); - it = node->elements.begin() + off; + size_t off = it - node->elements.begin(); + node->elements.insert( it, childUnboundedRegExpAlternation->elements.begin( ), childUnboundedRegExpAlternation->elements.end( ) ); + it = node->elements.begin() + off; - //TODO on g++-4.9 use: it = node->elements.insert( it, childUnboundedRegExpAlternation->elements.begin( ), childUnboundedRegExpAlternation->elements.end( ) ); + //TODO on g++-4.9 use: it = node->elements.insert( it, childUnboundedRegExpAlternation->elements.begin( ), childUnboundedRegExpAlternation->elements.end( ) ); - childUnboundedRegExpAlternation->elements.clear( ); - delete childUnboundedRegExpAlternation; + childUnboundedRegExpAlternation->elements.clear( ); + delete childUnboundedRegExpAlternation; - optimized = true; - } - else - { - it ++; - } - } + optimized = true; + } + else + { + it ++; + } + } - return optimized; + return optimized; } /** @@ -193,13 +241,13 @@ bool RegExpOptimize::A1( UnboundedRegExpAlternation * const & node ) */ bool RegExpOptimize::A2( UnboundedRegExpAlternation * const & node ) { - std::function<bool( UnboundedRegExpElement const * const & a, UnboundedRegExpElement const * const & b )> cmp = [ ]( UnboundedRegExpElement const * const & a, UnboundedRegExpElement const * const & b ) -> bool { return *a < *b; }; + std::function<bool( UnboundedRegExpElement const * const & a, UnboundedRegExpElement const * const & b )> cmp = [ ]( UnboundedRegExpElement const * const & a, UnboundedRegExpElement const * const & b ) -> bool { return *a < *b; }; - if( std::is_sorted( node->elements.begin( ), node->elements.end( ), cmp ) ) - return false; + if( std::is_sorted( node->elements.begin( ), node->elements.end( ), cmp ) ) + return false; - std::sort( node->elements.begin(), node->elements.end(), cmp ); - return true; + std::sort( node->elements.begin(), node->elements.end(), cmp ); + return true; } /** @@ -209,30 +257,30 @@ bool RegExpOptimize::A2( UnboundedRegExpAlternation * const & node ) */ bool RegExpOptimize::A3( UnboundedRegExpAlternation * const & node ) { - bool optimized = false; + bool optimized = false; - // input can be \0 + \0, so at least one element must be preserved + // input can be \0 + \0, so at least one element must be preserved - // FIXME: alib2 uses shared_ptrs, rewrite this using remove_if then + // FIXME: alib2 uses shared_ptrs, rewrite this using remove_if then - for( auto it = node->elements.begin( ); it != node->elements.end( ); ) - { - UnboundedRegExpEmpty const * const & empty = dynamic_cast<UnboundedRegExpEmpty const *>( * it ); + for( auto it = node->elements.begin( ); it != node->elements.end( ); ) + { + UnboundedRegExpEmpty const * const & empty = dynamic_cast<UnboundedRegExpEmpty const *>( * it ); - if( empty && node->elements.size( ) > 1 ) - { - it = node->elements.erase( it ); - delete empty; + if( empty && node->elements.size( ) > 1 ) + { + it = node->elements.erase( it ); + delete empty; - optimized = true; - } - else - { - it ++; - } - } + optimized = true; + } + else + { + it ++; + } + } - return optimized; + return optimized; } /** @@ -242,35 +290,35 @@ bool RegExpOptimize::A3( UnboundedRegExpAlternation * const & node ) */ bool RegExpOptimize::A4( UnboundedRegExpAlternation * const & node ) { - /* - * two ways of implementing this opitimization: - * - sort and call std::unique ( O(n lg n) + O(n) ), but it also sorts... - * - check every element against other ( O(n*n) ) - * - * As we always sort in optimization, we can use the first version, but A4 must be __always__ called __after__ A2 - */ - - // uncomment if smart ptrs used - // node->elements.unique( [ ]( UnboundedRegExpElement const * const & a, UnboundedRegExpElement const * const & b ) -> bool { - // return *a == *b; - // } ); - - bool optimized = false; - if(node->elements.size() != 0) for( auto it = std::next( node->elements.begin( ) ); it != node->elements.end( ); ) - { - if ( ** it == ** std::prev( it ) ) - { - delete * it; - it = node->elements.erase( it ); - optimized = true; - } - else - { - it ++; - } - } - - return optimized; + /* + * two ways of implementing this opitimization: + * - sort and call std::unique ( O(n lg n) + O(n) ), but it also sorts... + * - check every element against other ( O(n*n) ) + * + * As we always sort in optimization, we can use the first version, but A4 must be __always__ called __after__ A2 + */ + + // uncomment if smart ptrs used + // node->elements.unique( [ ]( UnboundedRegExpElement const * const & a, UnboundedRegExpElement const * const & b ) -> bool { + // return *a == *b; + // } ); + + bool optimized = false; + if(node->elements.size() != 0) for( auto it = std::next( node->elements.begin( ) ); it != node->elements.end( ); ) + { + if ( ** it == ** std::prev( it ) ) + { + delete * it; + it = node->elements.erase( it ); + optimized = true; + } + else + { + it ++; + } + } + + return optimized; } /** @@ -280,32 +328,32 @@ bool RegExpOptimize::A4( UnboundedRegExpAlternation * const & node ) */ bool RegExpOptimize::A5( UnboundedRegExpConcatenation * const & node ) { - bool optimized = false; + bool optimized = false; - for( auto it = node->elements.begin( ); it != node->elements.end( ); ) - { - UnboundedRegExpConcatenation * const & childUnboundedRegExpConcatenation = dynamic_cast<UnboundedRegExpConcatenation *>( * it ); + for( auto it = node->elements.begin( ); it != node->elements.end( ); ) + { + UnboundedRegExpConcatenation * const & childUnboundedRegExpConcatenation = dynamic_cast<UnboundedRegExpConcatenation *>( * it ); - if( childUnboundedRegExpConcatenation ) - { - it = node->elements.erase( it ); + if( childUnboundedRegExpConcatenation ) + { + it = node->elements.erase( it ); - size_t off = it - node->elements.begin(); - node->elements.insert( it, childUnboundedRegExpConcatenation->elements.begin( ), childUnboundedRegExpConcatenation->elements.end( ) ); - it = node->elements.begin() + off; + size_t off = it - node->elements.begin(); + node->elements.insert( it, childUnboundedRegExpConcatenation->elements.begin( ), childUnboundedRegExpConcatenation->elements.end( ) ); + it = node->elements.begin() + off; - //TODO on g++-4.9 use: it = node->elements.insert( it, childUnboundedRegExpConcatenation->elements.begin( ), childUnboundedRegExpConcatenation->elements.end( ) ); + //TODO on g++-4.9 use: it = node->elements.insert( it, childUnboundedRegExpConcatenation->elements.begin( ), childUnboundedRegExpConcatenation->elements.end( ) ); - childUnboundedRegExpConcatenation->elements.clear( ); - delete childUnboundedRegExpConcatenation; + childUnboundedRegExpConcatenation->elements.clear( ); + delete childUnboundedRegExpConcatenation; - optimized = true; - } - else - it ++; - } + optimized = true; + } + else + it ++; + } - return optimized; + return optimized; } /** @@ -315,25 +363,25 @@ bool RegExpOptimize::A5( UnboundedRegExpConcatenation * const & node ) */ bool RegExpOptimize::A6( UnboundedRegExpConcatenation * const & node ) { - bool optimized = false; + bool optimized = false; - // FIXME: alib2 uses shared_ptrs, rewrite this using remove_if then + // FIXME: alib2 uses shared_ptrs, rewrite this using remove_if then - for( auto it = node->elements.begin( ); it != node->elements.end( ); ) - { - UnboundedRegExpEpsilon* epsilon = dynamic_cast<UnboundedRegExpEpsilon*>( * it ); - if( epsilon && node->elements.size( ) > 1 ) - { - delete * it; - it = node->elements.erase( it ); + for( auto it = node->elements.begin( ); it != node->elements.end( ); ) + { + UnboundedRegExpEpsilon* epsilon = dynamic_cast<UnboundedRegExpEpsilon*>( * it ); + if( epsilon && node->elements.size( ) > 1 ) + { + delete * it; + it = node->elements.erase( it ); - optimized = true; - } - else - it ++; - } + optimized = true; + } + else + it ++; + } - return optimized; + return optimized; } /** @@ -343,22 +391,22 @@ bool RegExpOptimize::A6( UnboundedRegExpConcatenation * const & node ) */ bool RegExpOptimize::A7( UnboundedRegExpConcatenation * const & node ) { - bool optimized = false; + bool optimized = false; - // FIXME: alib2 uses shared_ptrs, rewrite this using remove_if then + // FIXME: alib2 uses shared_ptrs, rewrite this using remove_if then - if( std::any_of( node->elements.begin( ), node->elements.end( ), []( UnboundedRegExpElement const * const & a ) -> bool{ return dynamic_cast<UnboundedRegExpEmpty const *>( a ); } ) ) - { - for( auto const& child : node->elements ) - delete child; + if( std::any_of( node->elements.begin( ), node->elements.end( ), []( UnboundedRegExpElement const * const & a ) -> bool{ return dynamic_cast<UnboundedRegExpEmpty const *>( a ); } ) ) + { + for( auto const& child : node->elements ) + delete child; - node->elements.clear( ); - node->elements.push_back( new UnboundedRegExpEmpty( ) ); + node->elements.clear( ); + node->elements.push_back( new UnboundedRegExpEmpty( ) ); - optimized = true; - } + optimized = true; + } - return optimized; + return optimized; } /** @@ -369,44 +417,44 @@ bool RegExpOptimize::A7( UnboundedRegExpConcatenation * const & node ) bool RegExpOptimize::A8( UnboundedRegExpConcatenation * const & node ) { /* - bool optimized = false; - - for( auto it = std::next( node->elements.begin( ) ); it != node->elements.end( ); ) - { - UnboundedRegExpAlternation * alt = dynamic_cast<UnboundedRegExpAlternation*>( * it ); - if( ! alt ) - { - it ++; - continue; - } - - // take everything to the left and copy it as prefix of every element in alternation. - UnboundedRegExpConcatenation * leftPart = new UnboundedRegExpConcatenation( ); - leftPart->elements.insert( leftPart->elements.end( ), node->elements.begin( ), it ); - - for( auto altIt = alt->elements.begin( ); altIt != alt->elements.end( ); altIt ++ ) - { - UnboundedRegExpConcatenation * altElem = new UnboundedRegExpConcatenation( ); - altElem->elements.push_back( leftPart->clone( ) ); - altElem->elements.push_back( * altIt ); - - * altIt = altElem; - } - - UnboundedRegExpElement * optIt = optimize( * it ); - delete *it; - *it = optIt; - - delete leftPart; - it = node->elements.erase( node->elements.begin( ), it ); - - optimized = true; - it ++; - } - - return optimized; + bool optimized = false; + + for( auto it = std::next( node->elements.begin( ) ); it != node->elements.end( ); ) + { + UnboundedRegExpAlternation * alt = dynamic_cast<UnboundedRegExpAlternation*>( * it ); + if( ! alt ) + { + it ++; + continue; + } + + // take everything to the left and copy it as prefix of every element in alternation. + UnboundedRegExpConcatenation * leftPart = new UnboundedRegExpConcatenation( ); + leftPart->elements.insert( leftPart->elements.end( ), node->elements.begin( ), it ); + + for( auto altIt = alt->elements.begin( ); altIt != alt->elements.end( ); altIt ++ ) + { + UnboundedRegExpConcatenation * altElem = new UnboundedRegExpConcatenation( ); + altElem->elements.push_back( leftPart->clone( ) ); + altElem->elements.push_back( * altIt ); + + * altIt = altElem; + } + + UnboundedRegExpElement * optIt = optimize( * it ); + delete *it; + *it = optIt; + + delete leftPart; + it = node->elements.erase( node->elements.begin( ), it ); + + optimized = true; + it ++; + } + + return optimized; */ - return false; + return false; } /** @@ -417,47 +465,47 @@ bool RegExpOptimize::A8( UnboundedRegExpConcatenation * const & node ) bool RegExpOptimize::A9( UnboundedRegExpConcatenation * const & node ) { /* - bool optimized = false; - - for( auto it = node->elements.begin( ); it != std::prev( node->elements.end( ) ); ) - { - UnboundedRegExpAlternation * alt = dynamic_cast<UnboundedRegExpAlternation*>( * it ); - if( ! alt ) - { - it ++; - continue; - } - - // take everything to the right and copy it as suffix of every element in alternation. - UnboundedRegExpConcatenation * rest = new UnboundedRegExpConcatenation( ); - rest->elements.insert( rest->elements.end( ), std::next( it ), node->elements.end( ) ); - - for( auto altIt = alt->elements.begin( ); altIt != alt->elements.end( ); altIt ++ ) - { - UnboundedRegExpConcatenation * altElem = new UnboundedRegExpConcatenation( ); - altElem->elements.push_back( * altIt ); - altElem->elements.push_back( rest->clone( ) ); - - * altIt = altElem; - } - - UnboundedRegExpElement * optIt = optimize( * it ); - delete *it; - *it = optIt; - - delete rest; - it = node->elements.erase( std::next( it ), node->elements.end( ) ); - optimized = true; - - // as we move (delete) the rest of this expression, it surely wont do another round. More optimizations to be performerd are in subtree now. - // we do not care about this here as method optimize(UnboundedRegExpAlternation) will take care of this in next iteration - // it ++; - break; - } - - return optimized; + bool optimized = false; + + for( auto it = node->elements.begin( ); it != std::prev( node->elements.end( ) ); ) + { + UnboundedRegExpAlternation * alt = dynamic_cast<UnboundedRegExpAlternation*>( * it ); + if( ! alt ) + { + it ++; + continue; + } + + // take everything to the right and copy it as suffix of every element in alternation. + UnboundedRegExpConcatenation * rest = new UnboundedRegExpConcatenation( ); + rest->elements.insert( rest->elements.end( ), std::next( it ), node->elements.end( ) ); + + for( auto altIt = alt->elements.begin( ); altIt != alt->elements.end( ); altIt ++ ) + { + UnboundedRegExpConcatenation * altElem = new UnboundedRegExpConcatenation( ); + altElem->elements.push_back( * altIt ); + altElem->elements.push_back( rest->clone( ) ); + + * altIt = altElem; + } + + UnboundedRegExpElement * optIt = optimize( * it ); + delete *it; + *it = optIt; + + delete rest; + it = node->elements.erase( std::next( it ), node->elements.end( ) ); + optimized = true; + + // as we move (delete) the rest of this expression, it surely wont do another round. More optimizations to be performerd are in subtree now. + // we do not care about this here as method optimize(UnboundedRegExpAlternation) will take care of this in next iteration + // it ++; + break; + } + + return optimized; */ - return false; + return false; } /** @@ -467,71 +515,71 @@ bool RegExpOptimize::A9( UnboundedRegExpConcatenation * const & node ) */ bool RegExpOptimize::A10( UnboundedRegExpAlternation * const & node ) { - bool optimized = false, optimizedIter = false; - - /* - * problem: - * - \e + x*x = x* - * - but if we do not have the eps, but we do have iteration, then \e \in h(iter), therefore \e in h(node). - */ - - for( auto it = node->elements.begin( ); it != node->elements.end( ); ) - { - optimizedIter = false; - - // check if we have some epsilon or iteration left, else nothing to do - auto eps = find_if( node->elements.begin( ), node->elements.end( ), [ ]( UnboundedRegExpElement const * const & a ) -> bool { - return dynamic_cast<UnboundedRegExpEpsilon const *>( a ) || dynamic_cast<UnboundedRegExpIteration const*>( a ); - }); - if( eps == node->elements.end( ) ) - break; - - UnboundedRegExpConcatenation const * const & childConcat = dynamic_cast<UnboundedRegExpConcatenation const *>( *it ); - if( childConcat ) - { - // if iteration is first element of concatenation - UnboundedRegExpIteration const * const & iter = dynamic_cast<UnboundedRegExpIteration const *>( childConcat->elements.front( ) ); - - if( iter ) - { - // concatenation without the iteration node - UnboundedRegExpConcatenation *tmpConcat = dynamic_cast<UnboundedRegExpConcatenation *>( childConcat->clone( ) ); - delete tmpConcat->elements.front( ); - tmpConcat->elements.erase( tmpConcat->elements.begin( ) ); - UnboundedRegExpElement * tmpConcatOpt = optimize( tmpConcat ); - - // check if iteration element is the same subtree as rest of concatenation - if( * iter->element == * tmpConcatOpt ) - { - optimized = optimizedIter = true; - - node->elements.push_back( iter->clone( ) ); - - delete childConcat; - it = node->elements.erase( it ); - - // find the eps again - invalidated after prev erase - eps = find_if( node->elements.begin( ), node->elements.end( ), [ ]( UnboundedRegExpElement const * const & a ) -> bool { - return dynamic_cast<UnboundedRegExpEpsilon const *>( a ); - }); - // if it was eps, delete it - // if it was not the eps but iteration, keep it - if( eps != node->elements.end( ) ) - { - delete *eps; - it = node->elements.erase( eps ); - } - } - delete tmpConcat; - delete tmpConcatOpt; - } - } - - if( ! optimizedIter ) - it ++; - } - - return optimized; + bool optimized = false, optimizedIter = false; + + /* + * problem: + * - \e + x*x = x* + * - but if we do not have the eps, but we do have iteration, then \e \in h(iter), therefore \e in h(node). + */ + + for( auto it = node->elements.begin( ); it != node->elements.end( ); ) + { + optimizedIter = false; + + // check if we have some epsilon or iteration left, else nothing to do + auto eps = find_if( node->elements.begin( ), node->elements.end( ), [ ]( UnboundedRegExpElement const * const & a ) -> bool { + return dynamic_cast<UnboundedRegExpEpsilon const *>( a ) || dynamic_cast<UnboundedRegExpIteration const*>( a ); + }); + if( eps == node->elements.end( ) ) + break; + + UnboundedRegExpConcatenation const * const & childConcat = dynamic_cast<UnboundedRegExpConcatenation const *>( *it ); + if( childConcat ) + { + // if iteration is first element of concatenation + UnboundedRegExpIteration const * const & iter = dynamic_cast<UnboundedRegExpIteration const *>( childConcat->elements.front( ) ); + + if( iter ) + { + // concatenation without the iteration node + UnboundedRegExpConcatenation *tmpConcat = dynamic_cast<UnboundedRegExpConcatenation *>( childConcat->clone( ) ); + delete tmpConcat->elements.front( ); + tmpConcat->elements.erase( tmpConcat->elements.begin( ) ); + UnboundedRegExpElement * tmpConcatOpt = optimize( tmpConcat ); + + // check if iteration element is the same subtree as rest of concatenation + if( * iter->element == * tmpConcatOpt ) + { + optimized = optimizedIter = true; + + node->elements.push_back( iter->clone( ) ); + + delete childConcat; + it = node->elements.erase( it ); + + // find the eps again - invalidated after prev erase + eps = find_if( node->elements.begin( ), node->elements.end( ), [ ]( UnboundedRegExpElement const * const & a ) -> bool { + return dynamic_cast<UnboundedRegExpEpsilon const *>( a ); + }); + // if it was eps, delete it + // if it was not the eps but iteration, keep it + if( eps != node->elements.end( ) ) + { + delete *eps; + it = node->elements.erase( eps ); + } + } + delete tmpConcat; + delete tmpConcatOpt; + } + } + + if( ! optimizedIter ) + it ++; + } + + return optimized; } /** @@ -541,28 +589,28 @@ bool RegExpOptimize::A10( UnboundedRegExpAlternation * const & node ) */ bool RegExpOptimize::A11( UnboundedRegExpIteration * const & node ) { - bool optimized = false; + bool optimized = false; - UnboundedRegExpAlternation * const & childAlt = dynamic_cast<UnboundedRegExpAlternation *>( node->element ); + UnboundedRegExpAlternation * const & childAlt = dynamic_cast<UnboundedRegExpAlternation *>( node->element ); - if( childAlt ) - { - // check if eps inside iteration's alternation - auto eps = find_if( childAlt->elements.begin( ), childAlt->elements.end( ), [ ]( UnboundedRegExpElement const * const & a ) -> bool { - return dynamic_cast<UnboundedRegExpEpsilon const *>( a ); - }); + if( childAlt ) + { + // check if eps inside iteration's alternation + auto eps = find_if( childAlt->elements.begin( ), childAlt->elements.end( ), [ ]( UnboundedRegExpElement const * const & a ) -> bool { + return dynamic_cast<UnboundedRegExpEpsilon const *>( a ); + }); - // if no eps - if( eps == childAlt->elements.end( ) ) - return false; + // if no eps + if( eps == childAlt->elements.end( ) ) + return false; - // remove eps from alternation - optimized = true; - delete * eps; - childAlt->elements.erase( eps ); - } + // remove eps from alternation + optimized = true; + delete * eps; + childAlt->elements.erase( eps ); + } - return optimized; + return optimized; } /** @@ -572,9 +620,9 @@ bool RegExpOptimize::A11( UnboundedRegExpIteration * const & node ) */ bool RegExpOptimize::V1( UnboundedRegExpIteration * const & node ) { - // implemented in optimize( UnboundedRegExpIteration ) + // implemented in optimize( UnboundedRegExpIteration ) - return false; + return false; } /** @@ -584,74 +632,74 @@ bool RegExpOptimize::V1( UnboundedRegExpIteration * const & node ) */ bool RegExpOptimize::V2( UnboundedRegExpAlternation * const & node ) { - bool optimized = false; - - /* - * Bit tricky - * We need also to cover the cases like (a+b)* + a + b + c = (a+b)* + c - */ - - std::list<UnboundedRegExpElement*> iterElements; - // cache iter elements because of operator invalidation after erase - for( const auto & n : node->elements ) - { - UnboundedRegExpIteration* iter = dynamic_cast<UnboundedRegExpIteration*>( n ); - if( iter ) - iterElements.push_back( iter->element ); - } - - for( const auto & n : iterElements ) - { - // if alternation is inside, we need to make sure that every element of alternation is inside node->elements. if so, delete them all - UnboundedRegExpAlternation * tmpAlt = dynamic_cast<UnboundedRegExpAlternation*>( n ); - if( tmpAlt ) - { - bool every = true; - for( const auto & altElem : tmpAlt->elements ) - { - auto it = find_if( node->elements.begin( ), node->elements.end( ), [ altElem ]( UnboundedRegExpElement const * const & a ) -> bool { - return *a == *altElem; - }); - - if( it == node->elements.end( ) ) - every = false; - } - - if ( every == true ) - { - optimized = true; - - for( const auto & altElem : tmpAlt->elements ) - { - auto it = find_if( node->elements.begin( ), node->elements.end( ), [ altElem ]( UnboundedRegExpElement const * const & a ) -> bool { - return *a == *altElem; - }); - assert( it != node->elements.end( ) ); - - delete *it; - node->elements.erase( it ); - } - } - } - - // else - for( auto it = node->elements.begin( ); it != node->elements.end( ); ) - { - if( *n == **it ) - { - optimized = true; - - delete *it; - it = node->elements.erase( it ); - } - else - { - it ++; - } - } - } - - return optimized; + bool optimized = false; + + /* + * Bit tricky + * We need also to cover the cases like (a+b)* + a + b + c = (a+b)* + c + */ + + std::list<UnboundedRegExpElement*> iterElements; + // cache iter elements because of operator invalidation after erase + for( const auto & n : node->elements ) + { + UnboundedRegExpIteration* iter = dynamic_cast<UnboundedRegExpIteration*>( n ); + if( iter ) + iterElements.push_back( iter->element ); + } + + for( const auto & n : iterElements ) + { + // if alternation is inside, we need to make sure that every element of alternation is inside node->elements. if so, delete them all + UnboundedRegExpAlternation * tmpAlt = dynamic_cast<UnboundedRegExpAlternation*>( n ); + if( tmpAlt ) + { + bool every = true; + for( const auto & altElem : tmpAlt->elements ) + { + auto it = find_if( node->elements.begin( ), node->elements.end( ), [ altElem ]( UnboundedRegExpElement const * const & a ) -> bool { + return *a == *altElem; + }); + + if( it == node->elements.end( ) ) + every = false; + } + + if ( every == true ) + { + optimized = true; + + for( const auto & altElem : tmpAlt->elements ) + { + auto it = find_if( node->elements.begin( ), node->elements.end( ), [ altElem ]( UnboundedRegExpElement const * const & a ) -> bool { + return *a == *altElem; + }); + assert( it != node->elements.end( ) ); + + delete *it; + node->elements.erase( it ); + } + } + } + + // else + for( auto it = node->elements.begin( ); it != node->elements.end( ); ) + { + if( *n == **it ) + { + optimized = true; + + delete *it; + it = node->elements.erase( it ); + } + else + { + it ++; + } + } + } + + return optimized; } /** @@ -661,17 +709,17 @@ bool RegExpOptimize::V2( UnboundedRegExpAlternation * const & node ) */ bool RegExpOptimize::V3( UnboundedRegExpIteration * const & node ) { - UnboundedRegExpIteration* childIter = dynamic_cast<UnboundedRegExpIteration*>( node->element ); - if( childIter ) - { - node->element = childIter->element; - childIter->element = NULL; - delete childIter; + UnboundedRegExpIteration* childIter = dynamic_cast<UnboundedRegExpIteration*>( node->element ); + if( childIter ) + { + node->element = childIter->element; + childIter->element = NULL; + delete childIter; - return true; - } + return true; + } - return false; + return false; } /** @@ -681,25 +729,25 @@ bool RegExpOptimize::V3( UnboundedRegExpIteration * const & node ) */ bool RegExpOptimize::V4( UnboundedRegExpIteration * const & node ) { - // interpretation: if iteration's element is concat and every concat's element is iteration - UnboundedRegExpConcatenation* alt = dynamic_cast<UnboundedRegExpConcatenation*>( node->element ); - if( ! alt || ! all_of( alt->elements.begin( ), alt->elements.end( ), [] ( UnboundedRegExpElement const * const & a ) -> bool{ return dynamic_cast<UnboundedRegExpIteration const * const >( a ); } ) ) - return false; + // interpretation: if iteration's element is concat and every concat's element is iteration + UnboundedRegExpConcatenation* alt = dynamic_cast<UnboundedRegExpConcatenation*>( node->element ); + if( ! alt || ! all_of( alt->elements.begin( ), alt->elements.end( ), [] ( UnboundedRegExpElement const * const & a ) -> bool{ return dynamic_cast<UnboundedRegExpIteration const * const >( a ); } ) ) + return false; - UnboundedRegExpAlternation * newAlt = new UnboundedRegExpAlternation( ); + UnboundedRegExpAlternation * newAlt = new UnboundedRegExpAlternation( ); - for( const auto & n : alt->elements ) - { - UnboundedRegExpIteration * iter = dynamic_cast<UnboundedRegExpIteration*>( n ); - newAlt->elements.push_back( iter->element ); - iter->element = NULL; - } + for( const auto & n : alt->elements ) + { + UnboundedRegExpIteration * iter = dynamic_cast<UnboundedRegExpIteration*>( n ); + newAlt->elements.push_back( iter->element ); + iter->element = NULL; + } - node->element = optimize( newAlt ); - delete alt; - delete newAlt; + node->element = optimize( newAlt ); + delete alt; + delete newAlt; - return true; + return true; } /** @@ -709,150 +757,150 @@ bool RegExpOptimize::V4( UnboundedRegExpIteration * const & node ) */ bool RegExpOptimize::V5( UnboundedRegExpAlternation * const & node ) { - bool optimized = false; - - // reinterpretation: ax*y = ay+ax*xy - // so, if we find iter, a = everything that is before it (prefix) - // x = iter's content - // behind iter must be exactly iter's content - // y = rest (suffix) - // prefix.x*x.suffix + prefix.suffix = prefix.x*.suffix - - for( auto itA = node->elements.begin( ); itA != node->elements.end( ); ) - { - UnboundedRegExpConcatenation * concat = dynamic_cast<UnboundedRegExpConcatenation*>( * itA ); - if( ! concat ) - { - itA ++; - continue; - } - - for( auto itC = concat->elements.begin( ); itC != std::prev( concat->elements.end( ) ); ) - { - UnboundedRegExpIteration * iter = dynamic_cast<UnboundedRegExpIteration*>( *itC ); - if( ! iter ) - { - itC ++; - continue; - } - - // iteration's element must follow the iteration (x*x) - auto itStartY = std::next( itC ); //itStartY points to y in expression x*xy - - // if iter's element is concat - if( dynamic_cast<UnboundedRegExpConcatenation*>( iter->element ) ) - { - UnboundedRegExpConcatenation * iterConcat = dynamic_cast<UnboundedRegExpConcatenation*>( iter->element ); - - // std::cout << "....." << std::endl; - // std::cout << RegExp( concat ) << std::endl; - // std::cout << RegExp( iterConcat ) << std::endl; - // UnboundedRegExpConcatenation * tmp = new UnboundedRegExpConcatenation( ); - // tmp->elements.insert( tmp->elements.end( ), std::next( itC ), concat->elements.end( ) ); - // std::cout << RegExp( tmp) << std::endl; - - if( distance( iterConcat->elements.begin( ), iterConcat->elements.end( ) ) != distance( std::next( itC ), concat->elements.end( ) ) - || ! equal( iterConcat->elements.begin( ), iterConcat->elements.end( ), std::next( itC ), - [ ]( UnboundedRegExpElement const * const & a, UnboundedRegExpElement const * const & b ) -> bool{ return *a == *b; } ) ) - { - itC++; - continue; - } - advance( itStartY, (int)iterConcat->elements.size( ) ); - } - // else - else - { - if( * iter->element != ** std::next( itC ) ) - { - itC ++; - continue; - } - - advance( itStartY, 1 ); - } - - // store everything before iteration as "a" - UnboundedRegExpElement * regexpA; - if( concat->elements.begin( ) == itC ) - { - regexpA = new UnboundedRegExpEpsilon( ); - } - else - { - UnboundedRegExpConcatenation * tmpA = new UnboundedRegExpConcatenation( ); - tmpA->elements.insert( tmpA->elements.end( ), concat->elements.begin( ), itC ); - regexpA = optimize( tmpA ); - tmpA->elements.clear( ); - delete tmpA; - } - - // store everything behind iteration's followup element as "y" - UnboundedRegExpElement * regexpY; - if( itStartY == concat->elements.end( ) ) - { - regexpY = new UnboundedRegExpEpsilon( ); - } - else - { - UnboundedRegExpConcatenation* tmpY = new UnboundedRegExpConcatenation( ); - tmpY->elements.insert( tmpY->elements.end( ), itStartY, concat->elements.end( ) ); - regexpY = optimize( tmpY ); - tmpY->elements.clear( ); - delete tmpY; - } - - // concatenate "a" and "y" and see if they exist somewhere in parent alternation ( node->elements ) - UnboundedRegExpConcatenation* tmpAY = new UnboundedRegExpConcatenation( ); - tmpAY->elements.push_back( regexpA ); - tmpAY->elements.push_back( regexpY ); - UnboundedRegExpElement * regexpAY = optimize( tmpAY ); - tmpAY->elements.clear( ); - delete tmpAY; - - auto iterAY = find_if( node->elements.begin( ), node->elements.end( ), [ regexpAY ] ( UnboundedRegExpElement const * const & a ) -> bool{ return *a == *regexpAY; } ); - if( iterAY == node->elements.end( ) ) - { - itC ++; - continue; - } - - // if AY exists, then we can simply do this: - //iterator invalidated, need to backup concat node - UnboundedRegExpElement * tmpItA = *itA; - - delete *iterAY; - node->elements.erase( iterAY ); - - // iterator invalidated, need to recall before erase - itA = find_if( node->elements.begin( ), node->elements.end( ), [ tmpItA ]( UnboundedRegExpElement const * const & a ) -> bool { return *a == *tmpItA; } ); - - UnboundedRegExpConcatenation * tmpAltered = new UnboundedRegExpConcatenation( ); - tmpAltered->elements.push_back( regexpA ); - tmpAltered->elements.push_back( * itC ); - tmpAltered->elements.push_back( regexpY ); - UnboundedRegExpElement * regexpAltered = optimize( tmpAltered ); - - tmpAltered->elements.clear( ); - delete tmpAltered; - - delete regexpA; - delete regexpY; - delete regexpAY; - - delete *itA; - itA = node->elements.erase( itA ); - - node->elements.insert( itA, regexpAltered ); - - optimized = true; - break; - } - - itA ++; - } - - return optimized; + bool optimized = false; + + // reinterpretation: ax*y = ay+ax*xy + // so, if we find iter, a = everything that is before it (prefix) + // x = iter's content + // behind iter must be exactly iter's content + // y = rest (suffix) + // prefix.x*x.suffix + prefix.suffix = prefix.x*.suffix + + for( auto itA = node->elements.begin( ); itA != node->elements.end( ); ) + { + UnboundedRegExpConcatenation * concat = dynamic_cast<UnboundedRegExpConcatenation*>( * itA ); + if( ! concat ) + { + itA ++; + continue; + } + + for( auto itC = concat->elements.begin( ); itC != std::prev( concat->elements.end( ) ); ) + { + UnboundedRegExpIteration * iter = dynamic_cast<UnboundedRegExpIteration*>( *itC ); + if( ! iter ) + { + itC ++; + continue; + } + + // iteration's element must follow the iteration (x*x) + auto itStartY = std::next( itC ); //itStartY points to y in expression x*xy + + // if iter's element is concat + if( dynamic_cast<UnboundedRegExpConcatenation*>( iter->element ) ) + { + UnboundedRegExpConcatenation * iterConcat = dynamic_cast<UnboundedRegExpConcatenation*>( iter->element ); + + // std::cout << "....." << std::endl; + // std::cout << RegExp( concat ) << std::endl; + // std::cout << RegExp( iterConcat ) << std::endl; + // UnboundedRegExpConcatenation * tmp = new UnboundedRegExpConcatenation( ); + // tmp->elements.insert( tmp->elements.end( ), std::next( itC ), concat->elements.end( ) ); + // std::cout << RegExp( tmp) << std::endl; + + if( distance( iterConcat->elements.begin( ), iterConcat->elements.end( ) ) != distance( std::next( itC ), concat->elements.end( ) ) + || ! equal( iterConcat->elements.begin( ), iterConcat->elements.end( ), std::next( itC ), + [ ]( UnboundedRegExpElement const * const & a, UnboundedRegExpElement const * const & b ) -> bool{ return *a == *b; } ) ) + { + itC++; + continue; + } + advance( itStartY, (int)iterConcat->elements.size( ) ); + } + // else + else + { + if( * iter->element != ** std::next( itC ) ) + { + itC ++; + continue; + } + + advance( itStartY, 1 ); + } + + // store everything before iteration as "a" + UnboundedRegExpElement * regexpA; + if( concat->elements.begin( ) == itC ) + { + regexpA = new UnboundedRegExpEpsilon( ); + } + else + { + UnboundedRegExpConcatenation * tmpA = new UnboundedRegExpConcatenation( ); + tmpA->elements.insert( tmpA->elements.end( ), concat->elements.begin( ), itC ); + regexpA = optimize( tmpA ); + tmpA->elements.clear( ); + delete tmpA; + } + + // store everything behind iteration's followup element as "y" + UnboundedRegExpElement * regexpY; + if( itStartY == concat->elements.end( ) ) + { + regexpY = new UnboundedRegExpEpsilon( ); + } + else + { + UnboundedRegExpConcatenation* tmpY = new UnboundedRegExpConcatenation( ); + tmpY->elements.insert( tmpY->elements.end( ), itStartY, concat->elements.end( ) ); + regexpY = optimize( tmpY ); + tmpY->elements.clear( ); + delete tmpY; + } + + // concatenate "a" and "y" and see if they exist somewhere in parent alternation ( node->elements ) + UnboundedRegExpConcatenation* tmpAY = new UnboundedRegExpConcatenation( ); + tmpAY->elements.push_back( regexpA ); + tmpAY->elements.push_back( regexpY ); + UnboundedRegExpElement * regexpAY = optimize( tmpAY ); + tmpAY->elements.clear( ); + delete tmpAY; + + auto iterAY = find_if( node->elements.begin( ), node->elements.end( ), [ regexpAY ] ( UnboundedRegExpElement const * const & a ) -> bool{ return *a == *regexpAY; } ); + if( iterAY == node->elements.end( ) ) + { + itC ++; + continue; + } + + // if AY exists, then we can simply do this: + //iterator invalidated, need to backup concat node + UnboundedRegExpElement * tmpItA = *itA; + + delete *iterAY; + node->elements.erase( iterAY ); + + // iterator invalidated, need to recall before erase + itA = find_if( node->elements.begin( ), node->elements.end( ), [ tmpItA ]( UnboundedRegExpElement const * const & a ) -> bool { return *a == *tmpItA; } ); + + UnboundedRegExpConcatenation * tmpAltered = new UnboundedRegExpConcatenation( ); + tmpAltered->elements.push_back( regexpA ); + tmpAltered->elements.push_back( * itC ); + tmpAltered->elements.push_back( regexpY ); + UnboundedRegExpElement * regexpAltered = optimize( tmpAltered ); + + tmpAltered->elements.clear( ); + delete tmpAltered; + + delete regexpA; + delete regexpY; + delete regexpAY; + + delete *itA; + itA = node->elements.erase( itA ); + + node->elements.insert( itA, regexpAltered ); + + optimized = true; + break; + } + + itA ++; + } + + return optimized; } /** @@ -862,148 +910,148 @@ bool RegExpOptimize::V5( UnboundedRegExpAlternation * const & node ) */ bool RegExpOptimize::V6( UnboundedRegExpAlternation * const & node ) { - bool optimized = false; - - // reinterpretation: ax*y = ay+axx*y - // so, if we find iter, a = everything that is before it (prefix) - // x = iter's content - // before iter must be exactly iter's content - // y = rest (suffix) - // prefix.xx*.suffix + prefix.suffix = prefix.x*.suffix - - for( auto itA = node->elements.begin( ); itA != node->elements.end( ); ) - { - UnboundedRegExpConcatenation * concat = dynamic_cast<UnboundedRegExpConcatenation*>( * itA ); - if( ! concat ) - { - itA ++; - continue; - } - - for( auto itC = std::next( concat->elements.begin( ) ); itC != concat->elements.end( ); ) - { - UnboundedRegExpIteration * iter = dynamic_cast<UnboundedRegExpIteration*>( * itC ); - if( ! iter ) - { - itC ++; - continue; - } - - // iteration's element must preceed the iteration (xx*) - auto itStartX = itC; //itStartX points to first x in expression xx*, everything before is therefore prefix - regexp "a" - - // if iter's element is concat - if( dynamic_cast<UnboundedRegExpConcatenation*>( iter->element ) ) - { - UnboundedRegExpConcatenation * iterConcat = dynamic_cast<UnboundedRegExpConcatenation*>( iter->element ); - - if( distance( concat->elements.begin( ), itC ) < (int)iterConcat->elements.size( ) ) - { - itC ++; - continue; - } - advance( itStartX, - (int)(iterConcat->elements.size( ) ) ); - - if( distance( iterConcat->elements.begin( ), iterConcat->elements.end( ) ) != distance( itStartX, concat->elements.end( ) ) - || - ! equal( iterConcat->elements.begin( ), iterConcat->elements.end( ), itStartX, - []( UnboundedRegExpElement const * const & a, UnboundedRegExpElement const * const & b ) -> bool{ return *a == *b; } ) ) - { - itC++; - continue; - } - } - // else - else - { - if( * iter->element != ** std::prev( itC ) ) - { - itC ++; - continue; - } - - advance( itStartX, -1 ); - } - - // store everything before x as "a" - UnboundedRegExpElement * regexpA; - if( concat->elements.begin( ) == itStartX ) - { - regexpA = new UnboundedRegExpEpsilon( ); - } - else - { - UnboundedRegExpConcatenation* tmpA = new UnboundedRegExpConcatenation( ); - tmpA->elements.insert( tmpA->elements.end( ), concat->elements.begin( ), itStartX ); - regexpA = optimize( tmpA ); - tmpA->elements.clear( ); - delete tmpA; - } - - // store everything behind iteration's followup element as "y" - UnboundedRegExpElement * regexpY; - if( std::next( itC ) == concat->elements.end( ) ) - { - regexpY = new UnboundedRegExpEpsilon( ); - } - else - { - UnboundedRegExpConcatenation* tmpY = new UnboundedRegExpConcatenation( ); - tmpY->elements.insert( tmpY->elements.end( ), std::next( itC ), concat->elements.end( ) ); - regexpY = optimize( tmpY ); - tmpY->elements.clear( ); - delete tmpY; - } - - // concatenate "a" and "y" and see if they exist somewhere in parent alternation ( node->elements ) - UnboundedRegExpConcatenation* tmpAY = new UnboundedRegExpConcatenation( ); - tmpAY->elements.push_back( regexpA ); - tmpAY->elements.push_back( regexpY ); - UnboundedRegExpElement * regexpAY = optimize( tmpAY ); - tmpAY->elements.clear( ); - delete tmpAY; - - auto iterAY = find_if( node->elements.begin( ), node->elements.end( ), [ regexpAY ] ( UnboundedRegExpElement const * const & a ) -> bool{ return *a == *regexpAY; } ); - if( iterAY == node->elements.end( ) ) - { - itC ++; - continue; - } - - // if AY exists, then we can simply do this: - //iterator invalidated, need to backup concat node - UnboundedRegExpElement * tmpItA = *itA; - delete *iterAY; - node->elements.erase( iterAY ); - - // iterator invalidated, need to recall before erase - itA = find_if( node->elements.begin( ), node->elements.end( ), [ tmpItA ]( UnboundedRegExpElement const * const & a ) -> bool { return *a == *tmpItA; } ); - - UnboundedRegExpConcatenation * tmpAltered = new UnboundedRegExpConcatenation( ); - tmpAltered->elements.push_back( regexpA ); - tmpAltered->elements.push_back( * itC ); - tmpAltered->elements.push_back( regexpY ); - UnboundedRegExpElement * regexpAltered = optimize( tmpAltered ); - - tmpAltered->elements.clear( ); - delete tmpAltered; - - delete regexpA; - delete regexpY; - delete regexpAY; - - delete *itA; - itA = node->elements.erase( itA ); - - node->elements.insert( itA, regexpAltered ); - optimized = true; - break; - } - - itA ++; - } - - return optimized; + bool optimized = false; + + // reinterpretation: ax*y = ay+axx*y + // so, if we find iter, a = everything that is before it (prefix) + // x = iter's content + // before iter must be exactly iter's content + // y = rest (suffix) + // prefix.xx*.suffix + prefix.suffix = prefix.x*.suffix + + for( auto itA = node->elements.begin( ); itA != node->elements.end( ); ) + { + UnboundedRegExpConcatenation * concat = dynamic_cast<UnboundedRegExpConcatenation*>( * itA ); + if( ! concat ) + { + itA ++; + continue; + } + + for( auto itC = std::next( concat->elements.begin( ) ); itC != concat->elements.end( ); ) + { + UnboundedRegExpIteration * iter = dynamic_cast<UnboundedRegExpIteration*>( * itC ); + if( ! iter ) + { + itC ++; + continue; + } + + // iteration's element must preceed the iteration (xx*) + auto itStartX = itC; //itStartX points to first x in expression xx*, everything before is therefore prefix - regexp "a" + + // if iter's element is concat + if( dynamic_cast<UnboundedRegExpConcatenation*>( iter->element ) ) + { + UnboundedRegExpConcatenation * iterConcat = dynamic_cast<UnboundedRegExpConcatenation*>( iter->element ); + + if( distance( concat->elements.begin( ), itC ) < (int)iterConcat->elements.size( ) ) + { + itC ++; + continue; + } + advance( itStartX, - (int)(iterConcat->elements.size( ) ) ); + + if( distance( iterConcat->elements.begin( ), iterConcat->elements.end( ) ) != distance( itStartX, concat->elements.end( ) ) + || + ! equal( iterConcat->elements.begin( ), iterConcat->elements.end( ), itStartX, + []( UnboundedRegExpElement const * const & a, UnboundedRegExpElement const * const & b ) -> bool{ return *a == *b; } ) ) + { + itC++; + continue; + } + } + // else + else + { + if( * iter->element != ** std::prev( itC ) ) + { + itC ++; + continue; + } + + advance( itStartX, -1 ); + } + + // store everything before x as "a" + UnboundedRegExpElement * regexpA; + if( concat->elements.begin( ) == itStartX ) + { + regexpA = new UnboundedRegExpEpsilon( ); + } + else + { + UnboundedRegExpConcatenation* tmpA = new UnboundedRegExpConcatenation( ); + tmpA->elements.insert( tmpA->elements.end( ), concat->elements.begin( ), itStartX ); + regexpA = optimize( tmpA ); + tmpA->elements.clear( ); + delete tmpA; + } + + // store everything behind iteration's followup element as "y" + UnboundedRegExpElement * regexpY; + if( std::next( itC ) == concat->elements.end( ) ) + { + regexpY = new UnboundedRegExpEpsilon( ); + } + else + { + UnboundedRegExpConcatenation* tmpY = new UnboundedRegExpConcatenation( ); + tmpY->elements.insert( tmpY->elements.end( ), std::next( itC ), concat->elements.end( ) ); + regexpY = optimize( tmpY ); + tmpY->elements.clear( ); + delete tmpY; + } + + // concatenate "a" and "y" and see if they exist somewhere in parent alternation ( node->elements ) + UnboundedRegExpConcatenation* tmpAY = new UnboundedRegExpConcatenation( ); + tmpAY->elements.push_back( regexpA ); + tmpAY->elements.push_back( regexpY ); + UnboundedRegExpElement * regexpAY = optimize( tmpAY ); + tmpAY->elements.clear( ); + delete tmpAY; + + auto iterAY = find_if( node->elements.begin( ), node->elements.end( ), [ regexpAY ] ( UnboundedRegExpElement const * const & a ) -> bool{ return *a == *regexpAY; } ); + if( iterAY == node->elements.end( ) ) + { + itC ++; + continue; + } + + // if AY exists, then we can simply do this: + //iterator invalidated, need to backup concat node + UnboundedRegExpElement * tmpItA = *itA; + delete *iterAY; + node->elements.erase( iterAY ); + + // iterator invalidated, need to recall before erase + itA = find_if( node->elements.begin( ), node->elements.end( ), [ tmpItA ]( UnboundedRegExpElement const * const & a ) -> bool { return *a == *tmpItA; } ); + + UnboundedRegExpConcatenation * tmpAltered = new UnboundedRegExpConcatenation( ); + tmpAltered->elements.push_back( regexpA ); + tmpAltered->elements.push_back( * itC ); + tmpAltered->elements.push_back( regexpY ); + UnboundedRegExpElement * regexpAltered = optimize( tmpAltered ); + + tmpAltered->elements.clear( ); + delete tmpAltered; + + delete regexpA; + delete regexpY; + delete regexpAY; + + delete *itA; + itA = node->elements.erase( itA ); + + node->elements.insert( itA, regexpAltered ); + optimized = true; + break; + } + + itA ++; + } + + return optimized; } /** @@ -1013,80 +1061,80 @@ bool RegExpOptimize::V6( UnboundedRegExpAlternation * const & node ) */ bool RegExpOptimize::V8( UnboundedRegExpConcatenation * const & node ) { - bool optimized = false; - - // interpretation: if there is iteration in concatenation node, and element of iteration contains eps and is straight before this iteration, then this element can be omitted - - for( auto it = next( node->elements.begin( ) ); it != node->elements.end( ); ) - { - UnboundedRegExpIteration* iter = dynamic_cast<UnboundedRegExpIteration*>( * it ); - - if( ! iter ) - { - it ++; - continue; - } - - // if element of iteration is concatenation, we need to check this specially - UnboundedRegExpConcatenation * concat = dynamic_cast<UnboundedRegExpConcatenation*>( iter->element ); - - if( concat ) - { - // check if not out of bounds - if( distance( node->elements.begin( ), it ) < distance( concat->elements.begin(), concat->elements.end() ) ) - { - it ++; - continue; - } - - //FIXME: int cast - auto it2 = it; - advance( it2, - (int)concat->elements.size( ) ); - - if( concat->containsEmptyString( ) && - distance( concat->elements.begin( ), concat->elements.end( )) == distance ( it2, node->elements.end( ) ) && - equal( concat->elements.begin( ), concat->elements.end( ), it2, [] ( UnboundedRegExpElement const * const & a, UnboundedRegExpElement const * const & b ) -> bool { return *a == *b; } ) ) - { - optimized = true; - - for( auto delIt = it2 ; delIt != it ; delIt ++ ) - delete *delIt; - it = node->elements.erase( it2, it ); - } - else - { - it ++; - } - } - // else - else - { - if( it == node->elements.begin( ) ) - { - it++; - continue; - } - - auto prev = std::prev( it ); - - if( iter->element->containsEmptyString( ) && *( iter->element ) == **prev ) - { - delete * prev; - it = node->elements.erase( prev ); - optimized = true; - - // in case xxx*, we need to stay on the iter element, not to go behind it - if( it != node->elements.begin( ) ) - it = std::prev( it ); - } - else - { - it ++; - } - } - } - - return optimized; + bool optimized = false; + + // interpretation: if there is iteration in concatenation node, and element of iteration contains eps and is straight before this iteration, then this element can be omitted + + for( auto it = next( node->elements.begin( ) ); it != node->elements.end( ); ) + { + UnboundedRegExpIteration* iter = dynamic_cast<UnboundedRegExpIteration*>( * it ); + + if( ! iter ) + { + it ++; + continue; + } + + // if element of iteration is concatenation, we need to check this specially + UnboundedRegExpConcatenation * concat = dynamic_cast<UnboundedRegExpConcatenation*>( iter->element ); + + if( concat ) + { + // check if not out of bounds + if( distance( node->elements.begin( ), it ) < distance( concat->elements.begin(), concat->elements.end() ) ) + { + it ++; + continue; + } + + //FIXME: int cast + auto it2 = it; + advance( it2, - (int)concat->elements.size( ) ); + + if( concat->containsEmptyString( ) && + distance( concat->elements.begin( ), concat->elements.end( )) == distance ( it2, node->elements.end( ) ) && + equal( concat->elements.begin( ), concat->elements.end( ), it2, [] ( UnboundedRegExpElement const * const & a, UnboundedRegExpElement const * const & b ) -> bool { return *a == *b; } ) ) + { + optimized = true; + + for( auto delIt = it2 ; delIt != it ; delIt ++ ) + delete *delIt; + it = node->elements.erase( it2, it ); + } + else + { + it ++; + } + } + // else + else + { + if( it == node->elements.begin( ) ) + { + it++; + continue; + } + + auto prev = std::prev( it ); + + if( iter->element->containsEmptyString( ) && *( iter->element ) == **prev ) + { + delete * prev; + it = node->elements.erase( prev ); + optimized = true; + + // in case xxx*, we need to stay on the iter element, not to go behind it + if( it != node->elements.begin( ) ) + it = std::prev( it ); + } + else + { + it ++; + } + } + } + + return optimized; } /** @@ -1096,62 +1144,62 @@ bool RegExpOptimize::V8( UnboundedRegExpConcatenation * const & node ) */ bool RegExpOptimize::V9( UnboundedRegExpConcatenation * const & node ) { - bool optimized = false; - - // interpretation: if concat (C1) with iter && iteration's element is concat (C2), then: - // simultaneously iterate through C1 and C2. (axy)*axz=ax(yax)*z -> get ax that is same and relocate them... - - for( auto it = node->elements.begin( ) ; it != node->elements.end( ) ; ) - { - UnboundedRegExpIteration * iter = dynamic_cast<UnboundedRegExpIteration*>( * it ); - if ( ! iter ) - { - it++; - continue; - } - UnboundedRegExpConcatenation * concat = dynamic_cast<UnboundedRegExpConcatenation*>( iter->element ); - if( ! concat ) - { - it++; - continue; - } - - // find range from <it+1;sth> and <concat.begin;sth> that is equal - auto c1Iter = std::next( it ), c2Iter = concat->elements.begin( ); - while( c1Iter != node->elements.end() && c2Iter != concat->elements.end( ) && **c1Iter == ** c2Iter ) - { - c1Iter ++; - c2Iter ++; - } - - if( c1Iter == std::next( it ) ) - { - it ++; - continue; - } - - // std::cout << "xy" << std::endl; - // UnboundedRegExpConcatenation* tmp = new UnboundedRegExpConcatenation( ); - // tmp->elements.insert( tmp->elements.end( ), std::next( it ), c1Iter ); - // std::cout << RegExp( tmp ) << std::endl; - - // copy the range <it;sth>, delete it and go back to the iter node + bool optimized = false; + + // interpretation: if concat (C1) with iter && iteration's element is concat (C2), then: + // simultaneously iterate through C1 and C2. (axy)*axz=ax(yax)*z -> get ax that is same and relocate them... + + for( auto it = node->elements.begin( ) ; it != node->elements.end( ) ; ) + { + UnboundedRegExpIteration * iter = dynamic_cast<UnboundedRegExpIteration*>( * it ); + if ( ! iter ) + { + it++; + continue; + } + UnboundedRegExpConcatenation * concat = dynamic_cast<UnboundedRegExpConcatenation*>( iter->element ); + if( ! concat ) + { + it++; + continue; + } + + // find range from <it+1;sth> and <concat.begin;sth> that is equal + auto c1Iter = std::next( it ), c2Iter = concat->elements.begin( ); + while( c1Iter != node->elements.end() && c2Iter != concat->elements.end( ) && **c1Iter == ** c2Iter ) + { + c1Iter ++; + c2Iter ++; + } + + if( c1Iter == std::next( it ) ) + { + it ++; + continue; + } + + // std::cout << "xy" << std::endl; + // UnboundedRegExpConcatenation* tmp = new UnboundedRegExpConcatenation( ); + // tmp->elements.insert( tmp->elements.end( ), std::next( it ), c1Iter ); + // std::cout << RegExp( tmp ) << std::endl; + + // copy the range <it;sth>, delete it and go back to the iter node std::vector<UnboundedRegExpElement*> copyRange; - copyRange.insert( copyRange.end(), std::next( it ), c1Iter ); - it = node->elements.erase( std::next( it ), c1Iter ); - it = std::prev( it ); + copyRange.insert( copyRange.end(), std::next( it ), c1Iter ); + it = node->elements.erase( std::next( it ), c1Iter ); + it = std::prev( it ); - // insert that range before it position - node->elements.insert( it, copyRange.begin( ), copyRange.end( ) ); + // insert that range before it position + node->elements.insert( it, copyRange.begin( ), copyRange.end( ) ); - // alter the iteration's concat node - copyRange.clear( ); - copyRange.insert( copyRange.end(), concat->elements.begin( ), c2Iter ); - concat->elements.erase( concat->elements.begin( ), c2Iter ); - concat->elements.insert( concat->elements.end(), copyRange.begin( ), copyRange.end( ) ); - } + // alter the iteration's concat node + copyRange.clear( ); + copyRange.insert( copyRange.end(), concat->elements.begin( ), c2Iter ); + concat->elements.erase( concat->elements.begin( ), c2Iter ); + concat->elements.insert( concat->elements.end(), copyRange.begin( ), copyRange.end( ) ); + } - return optimized; + return optimized; } /** @@ -1161,25 +1209,25 @@ bool RegExpOptimize::V9( UnboundedRegExpConcatenation * const & node ) */ bool RegExpOptimize::V10( UnboundedRegExpIteration * const & node ) { - // interpretation: if iter's child is alternation where its every child is iteration, then they do not have to be iteration - UnboundedRegExpAlternation* alt = dynamic_cast<UnboundedRegExpAlternation*>( node->element ); - if( ! alt || ! all_of( alt->elements.begin( ), alt->elements.end( ), [] ( UnboundedRegExpElement const * const & a ) -> bool{ return dynamic_cast<UnboundedRegExpIteration const * const >( a ); } ) ) - return false; + // interpretation: if iter's child is alternation where its every child is iteration, then they do not have to be iteration + UnboundedRegExpAlternation* alt = dynamic_cast<UnboundedRegExpAlternation*>( node->element ); + if( ! alt || ! all_of( alt->elements.begin( ), alt->elements.end( ), [] ( UnboundedRegExpElement const * const & a ) -> bool{ return dynamic_cast<UnboundedRegExpIteration const * const >( a ); } ) ) + return false; - UnboundedRegExpAlternation * newAlt = new UnboundedRegExpAlternation( ); + UnboundedRegExpAlternation * newAlt = new UnboundedRegExpAlternation( ); - for( const auto & n : alt->elements ) - { - UnboundedRegExpIteration * iter = dynamic_cast<UnboundedRegExpIteration*>( n ); - newAlt->elements.push_back( iter->element ); - iter->element = NULL; - } + for( const auto & n : alt->elements ) + { + UnboundedRegExpIteration * iter = dynamic_cast<UnboundedRegExpIteration*>( n ); + newAlt->elements.push_back( iter->element ); + iter->element = NULL; + } - node->element = optimize( newAlt ); - delete alt; - delete newAlt; + node->element = optimize( newAlt ); + delete alt; + delete newAlt; - return true; + return true; } /** @@ -1189,20 +1237,20 @@ bool RegExpOptimize::V10( UnboundedRegExpIteration * const & node ) */ bool RegExpOptimize::X1( UnboundedRegExpAlternation * const & node ) { - // theorem: In regexp like a* + \e, \e is described twice, first in a*, second in \e. - // therefore we can delete the \e as it is redundant + // theorem: In regexp like a* + \e, \e is described twice, first in a*, second in \e. + // therefore we can delete the \e as it is redundant - auto iter = find_if( node->elements.begin( ), node->elements.end( ), [] (UnboundedRegExpElement const * const & a ) -> bool { return dynamic_cast<UnboundedRegExpIteration const * const>( a );} ); - auto eps = find_if( node->elements.begin( ), node->elements.end( ), [] (UnboundedRegExpElement const * const & a ) -> bool { return dynamic_cast<UnboundedRegExpEpsilon const * const>( a );} ); + auto iter = find_if( node->elements.begin( ), node->elements.end( ), [] (UnboundedRegExpElement const * const & a ) -> bool { return dynamic_cast<UnboundedRegExpIteration const * const>( a );} ); + auto eps = find_if( node->elements.begin( ), node->elements.end( ), [] (UnboundedRegExpElement const * const & a ) -> bool { return dynamic_cast<UnboundedRegExpEpsilon const * const>( a );} ); - if( iter != node->elements.end( ) && eps != node->elements.end( ) ) - { - delete *eps; - node->elements.erase( eps ); - return true; - } + if( iter != node->elements.end( ) && eps != node->elements.end( ) ) + { + delete *eps; + node->elements.erase( eps ); + return true; + } - return false; + return false; } } diff --git a/alib2algo/src/regexp/RegExpOptimize.h b/alib2algo/src/regexp/RegExpOptimize.h index afb794762d06822b1c70e821867dcb223f2dca05..0e97409eee8503cffd0375b00c9220d420a44008 100644 --- a/alib2algo/src/regexp/RegExpOptimize.h +++ b/alib2algo/src/regexp/RegExpOptimize.h @@ -58,6 +58,7 @@ class RegExpOptimize { public: regexp::UnboundedRegExp optimize( const regexp::UnboundedRegExp & regexp ); + void optimize( regexp::UnboundedRegExpElement & regexp ); private: regexp::UnboundedRegExpElement * optimize( regexp::UnboundedRegExpElement const * const & node ); regexp::UnboundedRegExpElement * optimize( regexp::UnboundedRegExpAlternation const * const & node );