Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

xtl_op_impl.h

Go to the documentation of this file.
00001 
00002 // Common Text Transformation Library
00003 // Copyright (C) 1997-2006 by Igor Kholodov. 
00004 //
00005 // This library is free software; you can redistribute it and/or
00006 // modify it under the terms of the GNU Lesser General Public
00007 // License as published by the Free Software Foundation; either
00008 // version 2.1 of the License, or (at your option) any later version.
00009 //
00010 // This library is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013 // Lesser General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU Lesser General Public
00016 // License along with this library; if not, write to the
00017 // Free Software Foundation, Inc.,
00018 // 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00019 //
00020 // mailto:cttl@users.sourceforge.net
00021 // http://sourceforge.net/projects/cttl/
00023 
00050 // xtl_op_impl.h
00051 
00052 #ifndef _CTTL_XTL_OP_IMPL_H_INCLUDED_
00053 #define _CTTL_XTL_OP_IMPL_H_INCLUDED_
00054 
00055 namespace cttl_impl {
00056 
00058 // Base implementation classes for overloaded operators
00060 
00071 template< typename ExprT >
00072 class xtl_op_base_unary {
00073 
00074 protected:
00076     ExprT m_expr;
00077 
00078 public:
00079     // compile-time
00080 
00082     xtl_op_base_unary( ExprT const& expr_ )
00083     : m_expr( expr_ )
00084     {
00085     }
00086 
00087 protected:
00111     template< typename UniverseT >
00112     size_t kleene_list( UniverseT& edge_, size_t upper_limit_ = 0 )
00113     {
00114 
00115         // if this offset stops progressing, we must bail out of infinite loop
00116         typename UniverseT::offset_manager_T iteration_offset( edge_.parent().container(), UniverseT::string_T::npos );
00117         typename UniverseT::offset_manager_T match_offset( edge_.parent().container(), UniverseT::string_T::npos );
00118 
00119         // statically captured offset to watch mutablility of the universe.
00120         // universe is considered mutated if saved_end_offset no longer matches the end of the universe.
00121         size_t saved_end_offset = edge_.second.offset();
00122 
00123         size_t cnt = 0;
00124         while ( ( match_offset = m_expr.match( edge_ ) ) != UniverseT::string_T::npos ) {
00125             // If universe is mutable and the user deleted matched fragment,
00126             // edge_.first.offset() is brought back, therefore, it will appear here
00127             // as an empty (epsilon) match. In such case, if universe has mutated,
00128             // the search should continue.
00129 
00130             // Check if the universe has mutated:
00131             if ( saved_end_offset == edge_.second.offset() ) {
00132                 if ( iteration_offset == edge_.first.offset() ) {
00133                     CTTL_TRACE_TEXT( 'i', "kleene_list: iteration made no progress: bailing out" );
00134                     break;  // second, third, etc., iteration hasn't made any progress: bail out
00135                 }
00136 
00137                 ++cnt;
00138 
00139                 if ( match_offset == edge_.first.offset() ) {
00140                     // second, third, etc., iteration succeeded on an empty substring,
00141                     // do not count it as a match, bail out of the loop:
00142                     CTTL_TRACE_TEXT( 'i', "kleene_list: epsilon match: bailing out" );
00143                     break;
00144                 }
00145 
00146             } else {
00147                 ++cnt;
00148                 saved_end_offset = edge_.second.offset();
00149             }
00150 
00151             if ( upper_limit_ && ( cnt == upper_limit_ ) ) {
00152                 CTTL_TRACE_TEXT( 'i', "kleene_list: user-specified match limit: bailing out" );
00153                 break;
00154             }
00155 
00156             iteration_offset = edge_.first.offset();
00157         }
00158         return cnt;
00159     }
00160 
00161 };  // xtl_op_base_unary
00162 
00163 
00180 template< typename Left_exprT, typename Right_exprT >
00181 class xtl_op_base_binary {
00182 
00183 protected:
00185     Left_exprT m_expr_lhs;
00186 
00188     Right_exprT m_expr_rhs;
00189 
00190 public:
00191 
00192     // compile-time
00193 
00213     xtl_op_base_binary( Left_exprT const& lhs_expr_, Right_exprT const& rhs_expr_ )
00214     : m_expr_lhs( lhs_expr_ ), m_expr_rhs( rhs_expr_ )
00215     {
00216     }
00217 
00218 };  // xtl_op_base_binary
00219 
00220 
00222 // Implementation classes for unary operators
00224 
00236 template< typename ExprT >
00237 struct xtl_opunarbang : public xtl_op_base_unary< ExprT > {
00238 
00239     // compile-time
00240 
00242     xtl_opunarbang( ExprT const& expr_ )
00243     : xtl_op_base_unary< ExprT >( expr_ )
00244     {
00245     }
00246 
00247     // run-time
00248 
00265     template< typename UniverseT >
00266     size_t match( UniverseT& edge_ )
00267     {
00268         CTTL_TRACE_LEVEL_MATCH( '!' );
00269         return this->m_expr.find( edge_ );
00270     }
00271     
00291     template< typename UniverseT >
00292     size_t find( UniverseT& edge_ )
00293     {
00294         CTTL_TRACE_LEVEL_FIND( '!' );
00295         return this->m_expr.bang_find( edge_ );
00296     }
00297     
00318     template< typename UniverseT >
00319     size_t bang_find( UniverseT& edge_ )
00320     {
00321         CTTL_TRACE_LEVEL_BANG( '!' );
00322         return this->m_expr.bang_find( edge_ );
00323     }
00324 
00325 };  // xtl_opunarbang
00326 
00327 
00339 template< typename ExprT >
00340 class xtl_opunarstar : public xtl_op_base_unary< ExprT > {
00341 
00342 protected:
00343 
00345     size_t m_upper_limit;
00346 
00347 public:
00348     // compile-time
00349 
00359     xtl_opunarstar( ExprT const& expr_, size_t upper_limit_ = 0 )
00360     : xtl_op_base_unary< ExprT >( expr_ ), m_upper_limit( upper_limit_ )
00361     {
00362     }
00363 
00364     // run-time
00365 
00390     template< typename UniverseT >
00391     size_t match( UniverseT& edge_ )
00392     {
00393         // [R,R,R,...]_ kleene star
00394         CTTL_TRACE_LEVEL_MATCH( '*' );
00395         typename UniverseT::offset_manager_T saved_first_offset( edge_.parent().container(), edge_.first.offset() );
00396 
00397         // statically captured offset to watch mutablility of the universe.
00398         // universe is considered mutated if saved_end_offset no longer matches the end of the universe.
00399         size_t saved_end_offset = edge_.second.offset();
00400         typename UniverseT::offset_manager_T match_offset( edge_.parent().container(), this->m_expr.match( edge_ ) );
00401 
00402         if ( match_offset != UniverseT::string_T::npos ) {
00403             // If universe is mutable and the user deleted matched fragment,
00404             // edge_.first.offset() is brought back, therefore, it will appear here
00405             // as an empty (epsilon) match. In such case, if universe has mutated,
00406             // the search should continue.
00407 
00408             // Check if the universe has mutated:
00409             if ( saved_end_offset == edge_.second.offset() ) {
00410                 if ( saved_first_offset == edge_.first.offset() ) {
00411                     // one match aleady found, no universe progress was made.
00412                     // No more match attemts necessary, we are done:
00413                     return match_offset;
00414                 }
00415             }
00416 
00417             if ( m_upper_limit ) {
00418                 // user wants to use upper limit on the number of matches
00419                 // minus one accounts for the expression already found
00420 
00421                 if ( m_upper_limit == 1 ) {
00422                     // one is a special case: if upper limit is one, then
00423                     // there is no need to search for more instances
00424                     return match_offset;
00425                 }
00426 
00427                 // it is sufficient to find only
00428                 // zero to (m_upper_limit - 1) matches:
00429                 kleene_list( edge_, m_upper_limit - 1 );
00430 
00431             } else
00432                 // user doesn't care how many matches are found:
00433                 kleene_list( edge_ );
00434 
00435         } else {
00436             // success offset is at the current position
00437             //assert( saved_first_offset == edge_.first.offset() );
00438             return saved_first_offset;
00439         }
00440 
00441         return match_offset;
00442     }
00443     
00468     template< typename UniverseT >
00469     size_t find( UniverseT& edge_ )
00470     {
00471         // [!R,R,R,...]_ kleene star
00472         CTTL_TRACE_LEVEL_FIND( '*' );
00473         typename UniverseT::offset_manager_T saved_first_offset( edge_.parent().container(), edge_.first.offset() );
00474 
00475         // statically captured offset to watch mutablility of the universe.
00476         // universe is considered mutated if saved_end_offset no
00477         // longer matches the end of the universe.
00478         size_t saved_end_offset = edge_.second.offset();
00479         typename UniverseT::offset_manager_T match_offset( edge_.parent().container(), this->m_expr.find( edge_ ) );
00480 
00481         if ( match_offset != UniverseT::string_T::npos ) {
00482             // If universe is mutable and the user deleted matched fragment,
00483             // edge_.first.offset() is brought back, therefore, it will appear here
00484             // as an empty (epsilon) match. In such case, if universe has mutated,
00485             // the search should go on.
00486             // Check if the universe mutated:
00487             if ( saved_end_offset == edge_.second.offset() ) {
00488                 if ( saved_first_offset == edge_.first.offset() ) {
00489                     // one match aleady found, no universe progress was made.
00490                     // No more match attemts necessary, we are done:
00491                     return match_offset;
00492                 }
00493             }
00494 
00495             if ( m_upper_limit ) {
00496                 // user wants to use upper limit on the number of matches
00497                 // minus one accounts for the expression already found
00498 
00499                 if ( m_upper_limit == 1 ) {
00500                     // one is a special case: if upper limit is one, then
00501                     // there is no need to search for more instances
00502                     return match_offset;
00503                 }
00504 
00505                 // it is sufficient to find
00506                 // zero to (m_upper_limit - 1) more matches:
00507                 kleene_list( edge_, m_upper_limit - 1 );
00508 
00509             } else
00510                 // user doesn't care how many matches are found:
00511                 kleene_list( edge_ );
00512 
00513         } else {
00514             // success offset is at the current position
00515             //assert( saved_first_offset == edge_.first.offset() );
00516             return saved_first_offset;
00517         }
00518 
00519         return match_offset;
00520     }
00521     
00547     template< typename UniverseT >
00548     size_t bang_find( UniverseT& edge_ )
00549     {
00550         // [!!R,R,R,...]_ kleene star
00551         CTTL_TRACE_LEVEL_BANG( '*' );
00552         typename UniverseT::offset_manager_T saved_first_offset( edge_.parent().container(), edge_.first.offset() );
00553         // statically captured offset to watch mutablility of the universe.
00554         // universe is considered mutated if saved_end_offset no
00555         // longer matches the end of the universe.
00556         size_t saved_end_offset = edge_.second.offset();
00557         typename UniverseT::offset_manager_T match_offset( edge_.parent().container(), this->m_expr.bang_find( edge_ ) );
00558 
00559         if ( match_offset != UniverseT::string_T::npos ) {
00560             // If universe is mutable and the user deleted matched fragment,
00561             // edge_.first.offset() is brought back, therefore, it will appear here
00562             // as an empty (epsilon) match. In such case, if universe has mutated,
00563             // the search should go on.
00564             
00565             // Check if the universe mutated:
00566             if ( saved_end_offset == edge_.second.offset() ) {
00567                 if ( saved_first_offset == edge_.first.offset() ) {
00568                     // one match aleady found, no universe progress was made.
00569                     // No more match attemts necessary, we are done:
00570                     return match_offset;
00571                 }
00572             }
00573 
00574             if ( m_upper_limit ) {
00575                 // user wants to use upper limit on the number of matches
00576                 // minus one accounts for the expression already found
00577 
00578                 if ( m_upper_limit == 1 ) {
00579                     // one is a special case: if upper limit is one, then
00580                     // there is no need to search for more instances
00581                     return match_offset;
00582                 }
00583 
00584                 // it is sufficient to find
00585                 // zero to (m_upper_limit - 1) more matches:
00586                 kleene_list( edge_, m_upper_limit - 1 );
00587 
00588             } else
00589                 // user doesn't care how many matches are found:
00590                 kleene_list( edge_ );
00591 
00592         } else {
00593             // success offset is at the current position
00594             //assert( saved_first_offset == edge_.first.offset() );
00595             return saved_first_offset;
00596         }
00597 
00598         return match_offset;
00599     }
00600 
00601 };  // xtl_opunarstar
00602 
00603 
00615 template< typename ExprT >
00616 class xtl_opunarminus : public xtl_op_base_unary< ExprT > {
00617 
00618 public:
00619     // compile-time
00620 
00627     xtl_opunarminus( ExprT const& expr_ )
00628     : xtl_op_base_unary< ExprT >( expr_ )
00629     {
00630     }
00631 
00632     // run-time
00633 
00654     template< typename UniverseT >
00655     size_t match( UniverseT& edge_ )
00656     {
00657         // -R_ logical not
00658         CTTL_TRACE_LEVEL_MATCH( '-' );
00659         typename UniverseT::offset_manager_T saved_first_offset( edge_.parent().container(), edge_.first.offset() );
00660         size_t match_offset = this->m_expr.match( edge_ );
00661 
00662         if ( match_offset != UniverseT::string_T::npos ) {
00663             // encapsulated expression succeeded, we fail:
00664             // restore universe
00665             edge_.first.offset( saved_first_offset );
00666             CTTL_TRACE_RESULT( false, '-' );
00667             return UniverseT::string_T::npos;
00668         }
00669 
00670         // success offset is at the current position
00671         //assert( saved_first_offset == edge_.first.offset() );
00672         return saved_first_offset;
00673     }
00674     
00675 
00696     template< typename UniverseT >
00697     size_t find( UniverseT& edge_ )
00698     {
00699         // -!R_ logical not
00700         CTTL_TRACE_LEVEL_FIND( '-' );
00701         typename UniverseT::offset_manager_T saved_first_offset( edge_.parent().container(), edge_.first.offset() );
00702         size_t match_offset = this->m_expr.find( edge_ );
00703 
00704         if ( match_offset != UniverseT::string_T::npos ) {
00705             // encapsulated expression succeeded, we fail:
00706             // restore universe
00707             edge_.first.offset( saved_first_offset );
00708             CTTL_TRACE_RESULT( false, '-' );
00709             return UniverseT::string_T::npos;
00710         }
00711 
00712         // success offset is at the current position
00713         //assert( saved_first_offset == edge_.first.offset() );
00714         return saved_first_offset;
00715     }
00716     
00717 
00739     template< typename UniverseT >
00740     size_t bang_find( UniverseT& edge_ )
00741     {
00742         // -!!R_ logical not
00743         CTTL_TRACE_LEVEL_BANG( '-' );
00744         typename UniverseT::offset_manager_T saved_first_offset( edge_.parent().container(), edge_.first.offset() );
00745         size_t match_offset = this->m_expr.bang_find( edge_ );
00746 
00747         if ( match_offset != UniverseT::string_T::npos ) {
00748             // encapsulated expression succeeded, we fail:
00749             // restore universe
00750             edge_.first.offset( saved_first_offset );
00751             CTTL_TRACE_RESULT( false, '-' );
00752             return UniverseT::string_T::npos;
00753         }
00754 
00755         // success offset is at the current position
00756         //assert( saved_first_offset == edge_.first.offset() );
00757         return saved_first_offset;
00758     }
00759 
00760 };  // xtl_opunarminus
00761 
00762 
00779 template< typename ExprT >
00780 class xtl_opunarplus : public xtl_op_base_unary< ExprT > {
00781 
00782 protected:
00784     size_t m_upper_limit;
00785 
00787     size_t m_lower_limit;
00788 
00807     template< typename UniverseT >
00808     size_t unarplus( UniverseT& edge_, size_t saved_end_offset_, size_t first_match_offset_ )
00809     {
00810         typename UniverseT::offset_manager_T match_offset( edge_.parent().container(), first_match_offset_ );
00811         
00812         if ( match_offset != UniverseT::string_T::npos ) {
00813             // If universe is mutable and the user deleted matched fragment,
00814             // edge_.first.offset() is brought back, therefore, it will appear here
00815             // as an empty (epsilon) match. In such case, if universe has mutated,
00816             // the search should continue.
00817             // Check if the universe has mutated:
00818             if ( saved_end_offset_ == edge_.second.offset() ) {
00819                 if ( match_offset == edge_.first.offset() ) {
00820                     // one match aleady found, no universe progress was made.
00821                     // No more match attemts necessary, we are done:
00822                     if ( !m_upper_limit )
00823                         return match_offset;
00824 
00825                     if ( ( m_lower_limit <= 1 ) && ( 1 <= m_upper_limit ) )
00826                         return match_offset;
00827 
00828                     CTTL_TRACE_TEXT_RESULT( false, '+', "kleene plus: too few matches (one epsilon found)" );
00829                     return UniverseT::string_T::npos;
00830                 }
00831             }
00832 
00833             if ( m_upper_limit ) {
00834                 if ( m_upper_limit == 1 )
00835                     // case: expr + m_upper_limit, where m_upper_limit == 1
00836                     return match_offset;
00837 
00838                 // user wants to use upper limit on the number of matches
00839                 // plus one accounts for the expression already found
00840                 if ( m_lower_limit ) {
00841                     // case: expr + pair( m_lower_limit, m_upper_limit )
00842                     size_t cnt = kleene_list( edge_, m_upper_limit ) + 1;
00843                     if ( cnt > m_upper_limit ) {
00844                         CTTL_TRACE_TEXT_RESULT( false, '+', "kleene plus: too many matches" );
00845                         return UniverseT::string_T::npos;
00846 
00847                     }
00848 
00849                     if ( cnt < m_lower_limit ) {
00850                         // user also wants to use lower limit on the number of matches
00851                         CTTL_TRACE_TEXT_RESULT( false, '+', "kleene plus: too few matches" );
00852                         return UniverseT::string_T::npos;
00853                     }
00854 
00855                 } else {
00856                     // case: expr + m_upper_limit, where m_upper_limit > 1
00857                     // it is sufficient to find up to (m_upper_limit - 1) more matches:
00858                     kleene_list( edge_, m_upper_limit - 1 );
00859                 }
00860 
00861             } else
00862                 // case: +expr
00863                 // user doesn't care how many matches are found:
00864                 kleene_list( edge_ );
00865 
00866             return match_offset;
00867         }
00868 
00869         CTTL_TRACE_RESULT( false, '+' );
00870         return UniverseT::string_T::npos;
00871     }
00872 
00873 public:
00874 
00875     // compile-time
00876 
00889     xtl_opunarplus( ExprT const& expr_, size_t upper_limit_ = 0, size_t lower_limit_ = 0 )
00890     : xtl_op_base_unary< ExprT >( expr_ ), m_upper_limit( upper_limit_ ), m_lower_limit( lower_limit_ )
00891     {
00892     }
00893 
00894 
00895     // run-time
00896 
00922     template< typename UniverseT >
00923     size_t match( UniverseT& edge_ )
00924     {
00925         // [R,R,R,...]_ kleene plus
00926         CTTL_TRACE_LEVEL_MATCH( '+' );
00927         size_t saved_end_offset = edge_.second.offset();
00928         return unarplus( edge_, saved_end_offset, this->m_expr.match( edge_ ) );
00929     }
00930     
00931 
00957     template< typename UniverseT >
00958     size_t find( UniverseT& edge_ )
00959     {
00960         // [!R,R,R,...]_ kleene plus
00961         CTTL_TRACE_LEVEL_FIND( '+' );
00962         size_t saved_end_offset = edge_.second.offset();
00963         return unarplus( edge_, saved_end_offset, this->m_expr.find( edge_ ) );
00964     }
00965     
00966 
00992     template< typename UniverseT >
00993     size_t bang_find( UniverseT& edge_ )
00994     {
00995         // [!!R,R,R,...]_ kleene plus
00996         CTTL_TRACE_LEVEL_BANG( '+' );
00997         size_t saved_end_offset = edge_.second.offset();
00998         return unarplus( edge_, saved_end_offset, this->m_expr.bang_find( edge_ ) );
00999     }
01000 
01001 };  // xtl_opunarplus
01002 
01003 
01016 template< typename ExprT >
01017 struct xtl_entity : public xtl_op_base_unary< ExprT > {
01018 
01019     // compile-time
01020 
01027     xtl_entity( ExprT const& expr_ )
01028     : xtl_op_base_unary< ExprT >( expr_ )
01029     {
01030     }
01031 
01032     // run-time
01033 
01058     template< typename UniverseT >
01059     size_t match( UniverseT& edge_ )
01060     {
01061         CTTL_TRACE_LEVEL_MATCH( 'E' );
01062         typename UniverseT::offset_manager_T match_offset( edge_.parent().container(), this->m_expr.match( edge_ ) );
01063         if ( ( match_offset != UniverseT::string_T::npos ) && ( match_offset != edge_.first.offset() ) )
01064             return match_offset;
01065 
01066         return UniverseT::string_T::npos;
01067     }
01068     
01069 
01094     template< typename UniverseT >
01095     size_t find( UniverseT& edge_ )
01096     {
01097         CTTL_TRACE_LEVEL_FIND( 'E' );
01098         typename UniverseT::offset_manager_T match_offset( edge_.parent().container(), this->m_expr.find( edge_ ) );
01099         if ( ( match_offset != UniverseT::string_T::npos ) && ( match_offset != edge_.first.offset() ) )
01100             return match_offset;
01101 
01102         return UniverseT::string_T::npos;
01103     }
01104     
01105 
01130     template< typename UniverseT >
01131     size_t bang_find( UniverseT& edge_ )
01132     {
01133         CTTL_TRACE_LEVEL_BANG( 'E' );
01134         typename UniverseT::offset_manager_T match_offset( edge_.parent().container(), this->m_expr.bang_find( edge_ ) );
01135         if ( ( match_offset != UniverseT::string_T::npos ) && ( match_offset != edge_.first.offset() ) )
01136             return match_offset;
01137 
01138         return UniverseT::string_T::npos;
01139     }
01140 
01141 };  // xtl_entity
01142 
01143 
01145 // Implementation classes for binary operators
01147 
01165 template< typename Left_exprT, typename Right_exprT >
01166 struct xtl_opbinplus : public xtl_op_base_binary< Left_exprT, Right_exprT > {
01167 
01168     // compile-time
01169 
01189     xtl_opbinplus( Left_exprT const& lhs_expr_, Right_exprT const& rhs_expr_ )
01190     : xtl_op_base_binary< Left_exprT, Right_exprT >( lhs_expr_, rhs_expr_ )
01191     {
01192     }
01193 
01194     // run-time
01195 
01220     template< typename UniverseT >
01221     size_t match( UniverseT& edge_ )
01222     {
01223         // L+R_ relaxed sequence
01224         // if L succeeds, and R fails, universe needs to be restored
01225         CTTL_TRACE_LEVEL_MATCH( ';' );
01226         typename UniverseT::offset_manager_T saved_first_offset( edge_.parent().container(), edge_.first.offset() );
01227         typename UniverseT::offset_manager_T match_lhs_offset( edge_.parent().container(), this->m_expr_lhs.match( edge_ ) );
01228         
01229         if (
01230             ( match_lhs_offset != UniverseT::string_T::npos )
01231             &&
01232             ( this->m_expr_rhs.match( edge_ ) != UniverseT::string_T::npos )
01233             )
01234                 return match_lhs_offset;
01235 
01236         // restore universe
01237         edge_.first.offset( saved_first_offset );
01238         return UniverseT::string_T::npos;
01239     }
01240 
01241 
01266     template< typename UniverseT >
01267     size_t find( UniverseT& edge_ )
01268     {
01269         // !L+R_
01270         CTTL_TRACE_LEVEL_FIND( ';' );
01271         typename UniverseT::offset_manager_T saved_first_offset( edge_.parent().container(), edge_.first.offset() );
01272         typename UniverseT::offset_manager_T match_lhs_offset( edge_.parent().container(), this->m_expr_lhs.find( edge_ ) );
01273 
01274         if (
01275             ( match_lhs_offset != UniverseT::string_T::npos )
01276             &&
01277             ( this->m_expr_rhs.match( edge_ ) != UniverseT::string_T::npos )
01278             )
01279                 return match_lhs_offset;
01280 
01281         edge_.first.offset( saved_first_offset );       // restore universe
01282         return UniverseT::string_T::npos;
01283     }
01284     
01285 
01310     template< typename UniverseT >
01311     size_t bang_find( UniverseT& edge_ )
01312     {
01313         // !!L+R_
01314         CTTL_TRACE_LEVEL_BANG( ';' );
01315         typename UniverseT::offset_manager_T saved_first_offset( edge_.parent().container(), edge_.first.offset() );
01316         typename UniverseT::offset_manager_T match_lhs_offset( edge_.parent().container(), UniverseT::string_T::npos );
01317         // if this offset stops progressing, we must bail out of infinite loop:
01318         typename UniverseT::offset_manager_T iteration_offset( edge_.parent().container(), UniverseT::string_T::npos );
01319 
01320         while ( ( match_lhs_offset = this->m_expr_lhs.bang_find( edge_ ) ) != UniverseT::string_T::npos ) {
01321             if ( this->m_expr_rhs.match( edge_ ) != UniverseT::string_T::npos )
01322                 return match_lhs_offset;
01323 
01324             if ( iteration_offset == edge_.first.offset() ) {
01325                 CTTL_TRACE_TEXT( '+', "!!expr + expr: iteration has not made any progress: bailing out" );
01326                 break;  // second, third, etc., iteration hasn't made any progress: bail out
01327             }
01328 
01329             iteration_offset = edge_.first.offset();
01330         }
01331 
01332         // restore universe
01333         edge_.first.offset( saved_first_offset );
01334         return UniverseT::string_T::npos;
01335     }
01336 
01337 };  // xtl_opbinplus
01338 
01339 
01357 template< typename Left_exprT, typename Right_exprT >
01358 struct xtl_opbinpipe : public xtl_op_base_binary< Left_exprT, Right_exprT > {
01359     // implements behavior of binary expr | expr operator
01360 
01361     // compile-time
01362 
01382     xtl_opbinpipe( Left_exprT const& lhs_expr_, Right_exprT const& rhs_expr_ )
01383     : xtl_op_base_binary< Left_exprT, Right_exprT >( lhs_expr_, rhs_expr_ )
01384     {
01385     }
01386 
01387     // run-time
01388 
01413     template< typename UniverseT >
01414     size_t match( UniverseT& edge_ )
01415     {
01416         // (L|R)_ logical "if L; else R;"
01417         // first-of( L, R )_
01418         CTTL_TRACE_LEVEL_MATCH( '|' );
01419         size_t match_offset = this->m_expr_lhs.match( edge_ );
01420         if ( match_offset != UniverseT::string_T::npos )
01421             return match_offset;
01422 
01423         match_offset = this->m_expr_rhs.match( edge_ );
01424         if ( match_offset != UniverseT::string_T::npos )
01425             return match_offset;
01426 
01427         CTTL_TRACE_RESULT( false, '|' );
01428         return UniverseT::string_T::npos;
01429     }
01430     
01431 
01456     template< typename UniverseT >
01457     size_t find( UniverseT& edge_ )
01458     {
01459         // ( !L | !R )_
01460         // first-of( !L, !R )_
01461         CTTL_TRACE_LEVEL_FIND( '|' );
01462         size_t match_offset = this->m_expr_lhs.find( edge_ );
01463         if ( match_offset != UniverseT::string_T::npos )
01464             return match_offset;
01465 
01466         match_offset = this->m_expr_rhs.find( edge_ );
01467         if ( match_offset != UniverseT::string_T::npos )
01468             return match_offset;
01469 
01470         CTTL_TRACE_RESULT( false, '|' );
01471         return UniverseT::string_T::npos;
01472     }
01473     
01474 
01499     template< typename UniverseT >
01500     size_t bang_find( UniverseT& edge_ )
01501     {
01502         // ( !!L | !!R )_
01503         // first-of( !!L, !!R )_
01504         CTTL_TRACE_LEVEL_BANG( '|' );
01505         size_t match_offset = this->m_expr_lhs.bang_find( edge_ );
01506         if ( match_offset != UniverseT::string_T::npos )
01507             return match_offset;
01508 
01509         match_offset = this->m_expr_rhs.bang_find( edge_ );
01510         if ( match_offset != UniverseT::string_T::npos )
01511             return match_offset;
01512 
01513         CTTL_TRACE_RESULT( false, '|' );
01514         return UniverseT::string_T::npos;
01515     }
01516 
01517 };  // xtl_opbinpipe
01518 
01519 
01537 template< typename Left_exprT, typename Right_exprT >
01538 struct xtl_opbin2pipe : public xtl_op_base_binary< Left_exprT, Right_exprT > {
01539 
01540     // compile-time
01541 
01561     xtl_opbin2pipe( Left_exprT const& lhs_expr_, Right_exprT const& rhs_expr_ )
01562     : xtl_op_base_binary< Left_exprT, Right_exprT >( lhs_expr_, rhs_expr_ )
01563     {
01564     }
01565 
01566     // run-time
01567 
01592     template< typename UniverseT >
01593     size_t match( UniverseT& edge_ )
01594     {
01595         // ( L || R )_
01596         // first-of( nearest-of( !L, !R ), longest-of( !L, !R ) )_
01597         CTTL_TRACE_LEVEL_MATCH( '|' );
01598 
01599         xtl_edge_offset_manager< UniverseT > saved_lhs_edge( edge_ );
01600 
01601         // position of the left side of the universe after LHS succeeds:
01602         typename UniverseT::offset_manager_T match_lhs_offset( edge_.parent().container(), this->m_expr_lhs.match( edge_ ) );
01603         if ( match_lhs_offset != UniverseT::string_T::npos )
01604             // LHS succeeded
01605             // save current position and restart search from the same position
01606             saved_lhs_edge.swap( edge_ );
01607 
01608         // position of the right side of the universe after RHS expression succeeds:
01609         typename UniverseT::offset_manager_T match_rhs_offset( edge_.parent().container(), this->m_expr_rhs.match( edge_ ) );
01610         if ( match_rhs_offset != UniverseT::string_T::npos ) {
01611             // RHS succeeded
01612             if ( match_lhs_offset == UniverseT::string_T::npos )
01613                 // F,T case
01614                 return match_rhs_offset;
01615 
01616             // T,T case
01617             // find longest-of( L, R ) )_
01618             if (
01619                 ( match_lhs_offset == match_rhs_offset )
01620                 &&
01621                 ( /*lhs_length*/saved_lhs_edge.first - match_lhs_offset < /*rhs_length*/edge_.first.offset() - match_rhs_offset )
01622                 )
01623                 // RHS is longer
01624                 return match_rhs_offset;
01625 
01626             // find nearest-of( L, R )
01627             else if ( match_rhs_offset < match_lhs_offset )
01628                 // RHS is closer
01629                 return match_rhs_offset;
01630 
01631             // LHS is closer or longer, or has exactly the same size and location
01632         }
01633 
01634         if ( match_lhs_offset != UniverseT::string_T::npos ) {
01635             // LHS succeeded
01636             // T,F case
01637             saved_lhs_edge.restore( edge_ );
01638             return match_lhs_offset;
01639         }
01640 
01641         // F,F case
01642         // note that because both sides have failed, they already restored original universe
01643         CTTL_TRACE_TEXT_RESULT( false, '|', "||" );
01644         return UniverseT::string_T::npos;
01645     }   // match()
01646     
01647     
01672     template< typename UniverseT >
01673     size_t find( UniverseT& edge_ )
01674     {
01675         // ( !L || !R )_
01676         // first-of( nearest-of( !L, !R ), longest-of( !L, !R ) )_
01677         CTTL_TRACE_LEVEL_FIND( '|' );
01678 
01679         xtl_edge_offset_manager< UniverseT > saved_lhs_edge( edge_ );
01680 
01681         // position of the left side of the universe after LHS succeeds:
01682         typename UniverseT::offset_manager_T match_lhs_offset( edge_.parent().container(), this->m_expr_lhs.find( edge_ ) );
01683         if ( match_lhs_offset != UniverseT::string_T::npos )
01684             // LHS succeeded
01685             // save current position and restart search from the same position
01686             saved_lhs_edge.swap( edge_ );
01687 
01688         // position of the right side of the universe after RHS expression succeeds:
01689         typename UniverseT::offset_manager_T match_rhs_offset( edge_.parent().container(), this->m_expr_rhs.find( edge_ ) );
01690         if ( match_rhs_offset != UniverseT::string_T::npos ) {
01691             // RHS succeeded
01692             if ( match_lhs_offset == UniverseT::string_T::npos )
01693                 // F,T case
01694                 return match_rhs_offset;
01695 
01696             // T,T case
01697             // find longest-of( !L, !R ) )_
01698             if (
01699                 ( match_lhs_offset == match_rhs_offset )
01700                 &&
01701                 ( /*lhs_length*/saved_lhs_edge.first - match_lhs_offset < /*rhs_length*/edge_.first.offset() - match_rhs_offset )
01702                 )
01703                 // RHS is longer
01704                 return match_rhs_offset;
01705 
01706             // find nearest-of( !L, !R )
01707             else if ( match_rhs_offset < match_lhs_offset )
01708                 // RHS is closer
01709                 return match_rhs_offset;
01710 
01711             // LHS is closer or longer, or has exactly the same size and location.
01712             // if so, LHS is the answer
01713         }
01714 
01715         if ( match_lhs_offset != UniverseT::string_T::npos ) {
01716             // LHS succeeded
01717             // T,F case
01718             saved_lhs_edge.restore( edge_ );
01719             return match_lhs_offset;
01720         }
01721 
01722         // F,F case
01723         // note that because both sides have failed, they already restored original universe
01724         CTTL_TRACE_TEXT_RESULT( false, '|', "||" );
01725         return UniverseT::string_T::npos;
01726 
01727     }   // find()
01728     
01729 
01754     template< typename UniverseT >
01755     size_t bang_find( UniverseT& edge_ )
01756     {
01757         // ( !!L || !!R )_
01758         // first-of( nearest-of( !!L, !!R ), longest-of( !!L, !!R ) )_
01759         CTTL_TRACE_LEVEL_BANG( '|' );
01760         xtl_edge_offset_manager< UniverseT > saved_lhs_edge( edge_ );
01761 
01762         // position of the left side of the universe after LHS succeeds:
01763         typename UniverseT::offset_manager_T match_lhs_offset( edge_.parent().container(), this->m_expr_lhs.bang_find( edge_ ) );
01764         if ( match_lhs_offset != UniverseT::string_T::npos )
01765             // LHS succeeded
01766             // save current position and restart search from the same position
01767             saved_lhs_edge.swap( edge_ );
01768 
01769         // position of the right side of the universe after RHS expression succeeds:
01770         typename UniverseT::offset_manager_T match_rhs_offset( edge_.parent().container(), this->m_expr_rhs.bang_find( edge_ ) );
01771         if ( match_rhs_offset != UniverseT::string_T::npos ) {
01772             // RHS succeeded
01773             if ( match_lhs_offset == UniverseT::string_T::npos )
01774                 // F,T case
01775                 return match_rhs_offset;
01776 
01777             // T,T case
01778             // longest-of( !!L, !!R ) )_
01779             if (
01780                 ( match_lhs_offset == match_rhs_offset )
01781                 &&
01782                 ( /*lhs_length*/saved_lhs_edge.first - match_lhs_offset < /*rhs_length*/edge_.first.offset() - match_rhs_offset )
01783                 )
01784                 // RHS is longer
01785                 return match_rhs_offset;
01786 
01787             // nearest-of( !!L, !!R )
01788             else if ( match_rhs_offset < match_lhs_offset )
01789                 // RHS is closer
01790                 return match_rhs_offset;
01791 
01792             // LHS is closer or longer, or has exactly the same size and location.
01793             // if so, LHS is the answer
01794         }
01795 
01796         if ( match_lhs_offset != UniverseT::string_T::npos ) {
01797             // LHS succeeded
01798             // T,F case
01799             saved_lhs_edge.restore( edge_ );
01800             return match_lhs_offset;
01801         }
01802 
01803         // F,F case
01804         // note that because both sides have failed, they already restored original universe
01805         CTTL_TRACE_TEXT_RESULT( false, '|', "||" );
01806         return UniverseT::string_T::npos;
01807 
01808     }   // bang_find()
01809 
01810 };  // xtl_opbin2pipe
01811 
01812 
01830 template< typename Left_exprT, typename Right_exprT >
01831 struct xtl_opbinconcat : public xtl_op_base_binary< Left_exprT, Right_exprT > {
01832 
01833     // compile-time
01834 
01854     xtl_opbinconcat( Left_exprT const& lhs_expr_, Right_exprT const& rhs_expr_ )
01855     : xtl_op_base_binary< Left_exprT, Right_exprT >( lhs_expr_, rhs_expr_ )
01856     {
01857     }
01858 
01859 
01860     // run-time
01861 
01886     template< typename UniverseT >
01887     size_t match( UniverseT& edge_ )
01888     {
01889         // L^R_ strict sequence
01890         // if L succeeds, and R fails, universe needs to be restored
01891         CTTL_TRACE_LEVEL_MATCH( '^' );
01892         typename UniverseT::offset_manager_T saved_first_offset( edge_.parent().container(), edge_.first.offset() );
01893         // saved_lhs_offset is required because LHS and RHS can be the same object:
01894         typename UniverseT::offset_manager_T match_lhs_offset( edge_.parent().container(), this->m_expr_lhs.match( edge_ ) );
01895 
01896         if ( match_lhs_offset != UniverseT::string_T::npos ) {
01897             typename UniverseT::strict_edge_T strict_universe( edge_ );
01898             if ( this->m_expr_rhs.match( strict_universe ) != UniverseT::string_T::npos )
01899                 return match_lhs_offset;
01900         }
01901 
01902         edge_.first.offset( saved_first_offset );       // restore universe
01903         CTTL_TRACE_RESULT( false, '^' );
01904         return UniverseT::string_T::npos;
01905     }
01906     
01907 
01932     template< typename UniverseT >
01933     size_t find( UniverseT& edge_ )
01934     {
01935         // !L^R_
01936         CTTL_TRACE_LEVEL_FIND( '^' );
01937         typename UniverseT::offset_manager_T saved_first_offset( edge_.parent().container(), edge_.first.offset() );
01938         // saved_lhs_offset is required because LHS and RHS can be the same object:
01939         typename UniverseT::offset_manager_T match_lhs_offset( edge_.parent().container(), this->m_expr_lhs.find( edge_ ) );
01940 
01941         if ( match_lhs_offset != UniverseT::string_T::npos ) {
01942             typename UniverseT::strict_edge_T strict_universe( edge_ );
01943             if ( this->m_expr_rhs.match( strict_universe ) != UniverseT::string_T::npos )
01944                 return match_lhs_offset;
01945         }
01946 
01947         edge_.first.offset( saved_first_offset );       // restore universe
01948         CTTL_TRACE_RESULT( false, '^' );
01949         return UniverseT::string_T::npos;
01950     }
01951     
01952 
01977     template< typename UniverseT >
01978     size_t bang_find( UniverseT& edge_ )
01979     {
01980         // !!L^R_
01981         CTTL_TRACE_LEVEL_BANG( '^' );
01982         typename UniverseT::offset_manager_T saved_first_offset( edge_.parent().container(), edge_.first.offset() );
01983         typename UniverseT::offset_manager_T match_lhs_offset( edge_.parent().container(), UniverseT::string_T::npos );
01984         // if this offset stops progressing, we must bail out of infinite loop:
01985         typename UniverseT::offset_manager_T iteration_offset( edge_.parent().container(), UniverseT::string_T::npos );
01986 
01987         while ( ( match_lhs_offset = this->m_expr_lhs.bang_find( edge_ ) ) != UniverseT::string_T::npos ) {
01988             typename UniverseT::strict_edge_T strict_universe( edge_ );
01989             if ( this->m_expr_rhs.match( strict_universe ) != UniverseT::string_T::npos )
01990                 return match_lhs_offset;
01991 
01992             if ( iteration_offset == edge_.first.offset() ) {
01993                 CTTL_TRACE_TEXT( '^', "!!expr ^ expr: iteration has not made any progress: bailing out" );
01994                 break;  // second, third, etc., iteration hasn't made any progress: bail out
01995             }
01996 
01997             iteration_offset = edge_.first.offset();
01998         }
01999 
02000         edge_.first.offset( saved_first_offset );       // restore universe
02001         CTTL_TRACE_RESULT( false, '^' );
02002         return UniverseT::string_T::npos;
02003     }
02004 
02005 };  // xtl_opbinconcat
02006 
02007 
02025 template< typename Left_exprT, typename Right_exprT >
02026 struct xtl_opbinminus : public xtl_op_base_binary< Left_exprT, Right_exprT > {
02027 
02028     // compile-time
02029 
02049     xtl_opbinminus( Left_exprT const& lhs_expr_, Right_exprT const& rhs_expr_ )
02050     : xtl_op_base_binary< Left_exprT, Right_exprT >( lhs_expr_, rhs_expr_ )
02051     {
02052     }
02053 
02054 
02055     // run-time
02056 
02081     template< typename UniverseT >
02082     size_t match( UniverseT& edge_ )
02083     {
02084         // L-R_ strict set-difference
02085         // if L succeeds, and R fails, universe needs to be restored
02086         CTTL_TRACE_LEVEL_MATCH( '-' );
02087         typename UniverseT::offset_manager_T saved_first_offset( edge_.parent().container(), edge_.first.offset() );
02088         xtl_edge_offset_manager< UniverseT > saved_lhs_edge( edge_ );   // preserve current universe
02089 
02090         // position of the left side of the universe after LHS succeeds:
02091         typename UniverseT::offset_manager_T match_lhs_offset( edge_.parent().container(), this->m_expr_lhs.match( edge_ ) );
02092         if ( match_lhs_offset != UniverseT::string_T::npos ) {
02093             saved_lhs_edge.save( edge_ );                   // preserve LHS edge
02094             edge_.second.offset( edge_.first.offset() );    // restrict RHS universe
02095             edge_.first.offset( match_lhs_offset );
02096             typename UniverseT::strict_edge_T strict_universe( edge_ );
02097             if ( this->m_expr_rhs.match( strict_universe ) == UniverseT::string_T::npos ) {
02098                 // RHS did not match, we succeed:
02099                 saved_lhs_edge.restore( edge_ );        // restore LHS edge
02100                 return match_lhs_offset;
02101             }
02102         }
02103 
02104         // RHS matched, we fail:
02105         edge_.first.offset( saved_first_offset );       // restore universe
02106         edge_.second.offset( saved_lhs_edge.second );
02107         CTTL_TRACE_RESULT( false, '-' );
02108         return UniverseT::string_T::npos;
02109     }
02110     
02111 
02136     template< typename UniverseT >
02137     size_t find( UniverseT& edge_ )
02138     {
02139         // !L-R_
02140         CTTL_TRACE_LEVEL_FIND( '-' );
02141         typename UniverseT::offset_manager_T saved_first_offset( edge_.parent().container(), edge_.first.offset() );
02142         xtl_edge_offset_manager< UniverseT > saved_lhs_edge( edge_ );   // preserve current universe
02143 
02144         // position of the left side of the universe after LHS succeeds:
02145         typename UniverseT::offset_manager_T match_lhs_offset( edge_.parent().container(), this->m_expr_lhs.find( edge_ ) );
02146         if ( match_lhs_offset != UniverseT::string_T::npos ) {
02147             saved_lhs_edge.save( edge_ );                   // preserve LHS edge
02148             edge_.second.offset( edge_.first.offset() );    // restrict RHS universe
02149             edge_.first.offset( match_lhs_offset );
02150             typename UniverseT::strict_edge_T strict_universe( edge_ );
02151             if ( this->m_expr_rhs.match( strict_universe ) == UniverseT::string_T::npos ) {
02152                 // RHS did not match, we succeed:
02153                 saved_lhs_edge.restore( edge_ );            // restore LHS edge
02154                 return match_lhs_offset;
02155             }
02156         }
02157 
02158         // RHS matched, we fail:
02159         edge_.first.offset( saved_first_offset );       // restore universe
02160         edge_.second.offset( saved_lhs_edge.second );
02161         CTTL_TRACE_RESULT( false, '-' );
02162         return UniverseT::string_T::npos;
02163     }
02164 
02165 
02190     template< typename UniverseT >
02191     size_t bang_find( UniverseT& edge_ )
02192     {
02193         // !!(L_-R)
02194         CTTL_TRACE_LEVEL_BANG( '-' );
02195         typename UniverseT::offset_manager_T saved_first_offset( edge_.parent().container(), edge_.first.offset() );
02196         typename UniverseT::offset_manager_T match_lhs_offset( edge_.parent().container(), UniverseT::string_T::npos );
02197         xtl_edge_offset_manager< UniverseT > saved_lhs_edge( edge_ );   // preserve current universe
02198         // if this offset stops progressing, we must bail out of infinite loop:
02199         typename UniverseT::offset_manager_T iteration_offset( edge_.parent().container(), UniverseT::string_T::npos );
02200 
02201         while ( ( match_lhs_offset = this->m_expr_lhs.bang_find( edge_ ) ) != UniverseT::string_T::npos ) {
02202             saved_lhs_edge.save( edge_ );                   // preserve LHS edge
02203             edge_.second.offset( edge_.first.offset() );    // restrict RHS universe
02204             edge_.first.offset( match_lhs_offset );
02205             typename UniverseT::strict_edge_T strict_universe( edge_ );
02206             if ( this->m_expr_rhs.match( strict_universe ) == UniverseT::string_T::npos ) {
02207                 // RHS did not match, we succeed:
02208                 saved_lhs_edge.restore( edge_ );            // restore LHS edge
02209                 return match_lhs_offset;
02210             }
02211 
02212             // RHS matched, continue searching:
02213             saved_lhs_edge.restore( edge_ );                // restore LHS edge
02214 
02215             if ( iteration_offset == edge_.first.offset() ) {
02216                 CTTL_TRACE_TEXT( '-', "!!expr - expr: iteration has not made any progress: bailing out" );
02217                 break;  // second, third, etc., iteration hasn't made any progress: bail out
02218             }
02219 
02220             iteration_offset = edge_.first.offset();
02221         }
02222 
02223         edge_.first.offset( saved_first_offset );       // restore universe
02224         CTTL_TRACE_RESULT( false, '-' );
02225         return UniverseT::string_T::npos;
02226     }
02227 
02228 };  // xtl_opbinminus
02229 
02230 
02248 template< typename Left_exprT, typename Right_exprT >
02249 struct xtl_opbinand : public xtl_op_base_binary< Left_exprT, Right_exprT > {
02250 
02251     // compile-time
02252 
02272     xtl_opbinand( Left_exprT const& lhs_expr_, Right_exprT const& rhs_expr_ )
02273     : xtl_op_base_binary< Left_exprT, Right_exprT >( lhs_expr_, rhs_expr_ )
02274     {
02275     }
02276 
02277 
02278     // run-time
02279 
02304     template< typename UniverseT >
02305     size_t match( UniverseT& edge_ )
02306     {
02307         // L&R_ strict set-intersection
02308         // if L succeeds, and R fails, universe needs to be restored
02309         CTTL_TRACE_LEVEL_MATCH( '&' );
02310         typename UniverseT::offset_manager_T saved_first_offset( edge_.parent().container(), edge_.first.offset() );
02311         xtl_edge_offset_manager< UniverseT > saved_lhs_edge( edge_ );   // preserve current universe
02312 
02313         // position of the left side of the universe after LHS succeeds:
02314         typename UniverseT::offset_manager_T match_lhs_offset( edge_.parent().container(), this->m_expr_lhs.match( edge_ ) );
02315         if ( match_lhs_offset != UniverseT::string_T::npos ) {
02316             saved_lhs_edge.save( edge_ );                   // preserve LHS edge
02317             edge_.second.offset( edge_.first.offset() );    // restrict RHS universe
02318             edge_.first.offset( match_lhs_offset );
02319             typename UniverseT::strict_edge_T strict_universe( edge_ );
02320             if ( this->m_expr_rhs.match( strict_universe ) != UniverseT::string_T::npos ) {
02321                 // LHS & RHS intersection succeeded
02322                 saved_lhs_edge.restore( edge_ );        // restore LHS edge
02323                 return match_lhs_offset;
02324             }
02325         }
02326 
02327         edge_.first.offset( saved_first_offset );       // restore universe
02328         edge_.second.offset( saved_lhs_edge.second );
02329         CTTL_TRACE_RESULT( false, '&' );
02330         return UniverseT::string_T::npos;
02331     }
02332     
02333 
02358     template< typename UniverseT >
02359     size_t find( UniverseT& edge_ )
02360     {
02361         // !L&R_
02362         CTTL_TRACE_LEVEL_FIND( '&' );
02363         typename UniverseT::offset_manager_T saved_first_offset( edge_.parent().container(), edge_.first.offset() );
02364         xtl_edge_offset_manager< UniverseT > saved_lhs_edge( edge_ );   // preserve current universe
02365 
02366         // position of the left side of the universe after LHS succeeds:
02367         typename UniverseT::offset_manager_T match_lhs_offset( edge_.parent().container(), this->m_expr_lhs.find( edge_ ) );
02368         if ( match_lhs_offset != UniverseT::string_T::npos ) {
02369             saved_lhs_edge.save( edge_ );                   // preserve LHS edge
02370             edge_.second.offset( edge_.first.offset() );    // restrict RHS universe
02371             edge_.first.offset( match_lhs_offset );
02372             typename UniverseT::strict_edge_T strict_universe( edge_ );
02373             if ( this->m_expr_rhs.match( strict_universe ) != UniverseT::string_T::npos ) {
02374                 // LHS & RHS intersection succeeded
02375                 saved_lhs_edge.restore( edge_ );            // restore LHS edge
02376                 return match_lhs_offset;
02377             }
02378         }
02379 
02380         edge_.first.offset( saved_first_offset );       // restore universe
02381         edge_.second.offset( saved_lhs_edge.second );
02382         CTTL_TRACE_RESULT( false, '&' );
02383         return UniverseT::string_T::npos;
02384     }
02385     
02386 
02411     template< typename UniverseT >
02412     size_t bang_find( UniverseT& edge_ )
02413     {
02414         // !!L&R_
02415         CTTL_TRACE_LEVEL_BANG( '&' );
02416         typename UniverseT::offset_manager_T saved_first_offset( edge_.parent().container(), edge_.first.offset() );
02417         xtl_edge_offset_manager< UniverseT > saved_lhs_edge( edge_ );   // preserve current universe
02418         // if this offset stops progressing, we must bail out of infinite loop:
02419         typename UniverseT::offset_manager_T iteration_offset( edge_.parent().container(), UniverseT::string_T::npos );
02420 
02421         typename UniverseT::offset_manager_T match_lhs_offset( edge_.parent().container(), UniverseT::string_T::npos );
02422         while ( ( match_lhs_offset = this->m_expr_lhs.bang_find( edge_ ) ) != UniverseT::string_T::npos ) {
02423             saved_lhs_edge.save( edge_ );                   // preserve LHS edge
02424             edge_.second.offset( edge_.first.offset() );    // restrict RHS universe
02425             edge_.first.offset( match_lhs_offset );
02426             typename UniverseT::strict_edge_T strict_universe( edge_ );
02427             if ( this->m_expr_rhs.match( strict_universe ) != UniverseT::string_T::npos ) {
02428                 // LHS & RHS intersection succeeded
02429                 saved_lhs_edge.restore( edge_ );            // restore LHS edge
02430                 return match_lhs_offset;
02431             }
02432 
02433             // RHS did not match, continue searching:
02434             saved_lhs_edge.restore( edge_ );                // restore LHS edge
02435 
02436             if ( iteration_offset == edge_.first.offset() ) {
02437                 CTTL_TRACE_TEXT( '&', "!!expr & expr: iteration has not made any progress: bailing out" );
02438                 break;  // second, third, etc., iteration hasn't made any progress: bail out
02439             }
02440 
02441             iteration_offset = edge_.first.offset();
02442         }
02443 
02444         edge_.first.offset( saved_first_offset );       // restore universe
02445         CTTL_TRACE_RESULT( false, '&' );
02446         return UniverseT::string_T::npos;
02447     }
02448 
02449 };  // xtl_opbinand
02450 
02452 // Typedefs for metaphors support
02454 
02456 typedef xtl_wrap< xtl_opbinplus< relaxed_bool_T, xtl_wrap< xtl_opunarbang< xtl_wrap< xtl_position_eof > > > > >
02457 universe_T;
02458 
02459 }   // namespace cttl_impl
02460 
02461 #endif // _CTTL_XTL_OP_IMPL_H_INCLUDED_

Generated on Thu Nov 2 17:44:06 2006 for Common Text Transformation Library by  doxygen 1.3.9.1