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

policy.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 
00035 // policy.h
00036 
00037 #ifndef _CTTL_POLICY_H_INCLUDED_
00038 #define _CTTL_POLICY_H_INCLUDED_
00039 
00040 #include "xtl_region_map.h"
00041 
00042 namespace cttl {
00043 
00044 using namespace cttl_impl;  
00045 
00047 const int flag_follow_space     = 1;
00048 
00050 const int flag_follow_region    = 2;
00051 
00053 const int flag_greedy           = 4;
00054 
00056 const int flag_cpp_comments     = 8;
00057 
00059 const int flag_follow_either    = flag_follow_space | flag_follow_region;
00060 
00065 class policy_mapped_space
00066 {
00067 protected:
00069     xtl_region_map m_region_map;
00070 
00071 public:
00078     typedef policy_default strict_policy_T;
00079 
00080 
00094     template< typename ExprT, typename UniverseT >
00095     size_t match( xtl_wrap< ExprT > derived_expr_, UniverseT& universe_ )
00096     {
00097         for( ;; ) {
00098             if ( derived_expr_.match( universe_ ) != UniverseT::string_T::npos ) {
00099                 if ( lower_bound( universe_.first.offset(), universe_ ) )
00100                     continue;
00101                 else
00102                     break;
00103             }
00104 
00105             if ( lower_bound( universe_.first.offset(), universe_ ) )
00106                 continue;
00107 
00108             break;
00109         }
00110 
00111         return universe_.first.offset();
00112     }
00113 
00126     template< typename UniverseT >
00127     bool lower_bound( size_t old_offset_, UniverseT& universe_ )
00128     {
00129         size_t new_offset = lower_bound( old_offset_, universe_.second.offset() );
00130         if ( new_offset != old_offset_ ) {
00131             universe_.first.offset( new_offset );
00132             return true;
00133         }
00134 
00135         return false;
00136     }
00137 
00144     size_t lower_bound( size_t offset_, size_t universe_length_ )
00145     {
00146         return m_region_map.find_not_region( offset_, universe_length_ );
00147     }
00148 
00152     template< typename StringT, typename CharT >
00153     void text_insert_go( node< StringT >& node_, CharT const* pchar_ )
00154     {
00155         text_insert_go( node_, StringT( pchar_ ) );
00156     }
00157 
00168     template< typename StringT >
00169     void text_insert_go( node< StringT >& node_, StringT const& str_ )
00170     {
00171         size_t str_length = str_.length();
00172 
00173         if ( !str_.length() )
00174             return; // nothing to do
00175 
00176         size_t insertion_offset = node_.offset();
00177 
00178         node_.parent().container().text().insert(
00179             insertion_offset,
00180             str_
00181             );
00182         
00183         m_region_map.adjust(
00184             insertion_offset,
00185             str_length
00186             );
00187         
00188         xtl_identity_insert_go< StringT > insert_go(
00189             insertion_offset,
00190             int( str_length )
00191             );
00192 
00193         size_t idx = 0;
00194         for ( idx = 0; idx < node_.parent().container().identity_vector().size(); ++idx )
00195             insert_go.adjust( node_.parent().container().identity_vector()[ idx ] );
00196 
00197         for ( idx = 0; idx < node_.parent().container().offset_stack().size(); ++idx )
00198             insert_go.adjust( node_.parent().container().offset_stack()[ idx ] );
00199     }
00200 
00212     template< typename StringT, typename PolicyT >
00213     void text_insert_go( node< StringT >& node_target_, const_edge< PolicyT, StringT > const& edge_source_ )
00214     {
00215         StringT const& str = edge_source_.parent().container().text();
00216         size_t source_from_offset_ = edge_source_.first.offset();   // a substring of the source string
00217         size_t source_to_offset_ = edge_source_.second.offset();
00218 
00219         size_t str_length = source_to_offset_ - source_from_offset_;
00220 
00221         if ( !str.length() )
00222             return; // nothing to do
00223 
00224         size_t insertion_offset = node_target_.offset();
00225 
00226         node_target_.parent().container().text().insert(
00227             insertion_offset,
00228             str,
00229             source_from_offset_,
00230             str_length
00231             );
00232         
00233         m_region_map.adjust(
00234             insertion_offset,
00235             str_length
00236             );
00237         
00238         xtl_identity_insert_go< StringT > insert_go(
00239             insertion_offset,
00240             int( str_length )
00241             );
00242 
00243         size_t idx = 0;
00244         for ( idx = 0; idx < node_target_.parent().container().identity_vector().size(); ++idx )
00245             insert_go.adjust( node_target_.parent().container().identity_vector()[ idx ] );
00246 
00247         for ( idx = 0; idx < node_target_.parent().container().offset_stack().size(); ++idx )
00248             insert_go.adjust( node_target_.parent().container().offset_stack()[ idx ] );
00249     }
00250     
00251 
00262     template< typename StringT, typename CharT >
00263     void text_insert_stay( node< StringT >& node_, CharT const* pchar_ )
00264     {
00265         text_insert_stay( node_, StringT( pchar_ ) );
00266     }
00267 
00278     template< typename StringT >
00279     void text_insert_stay( node< StringT >& node_, StringT const& str_ )
00280     {
00281         size_t str_length = str_.length();
00282 
00283         if ( !str_length )
00284             return; // nothing to do
00285 
00286         size_t insertion_offset = node_.offset();
00287 
00288         node_.parent().container().text().insert(
00289             insertion_offset,
00290             str_
00291             );
00292 
00293         m_region_map.adjust(
00294             insertion_offset,
00295             str_length
00296             );
00297         
00298         xtl_identity_insert_stay< StringT > insert_stay(
00299             insertion_offset,
00300             str_length
00301             );
00302 
00303         size_t idx = 0;
00304         for ( idx = 0; idx < node_.parent().container().identity_vector().size(); ++idx )
00305             insert_stay.adjust( node_.parent().container().identity_vector()[ idx ] );
00306 
00307         for ( idx = 0; idx < node_.parent().container().offset_stack().size(); ++idx )
00308             insert_stay.adjust( node_.parent().container().offset_stack()[ idx ] );
00309     }
00310 
00311 
00322     template< typename StringT, typename PolicyT >
00323     void text_insert_stay( node< StringT >& node_target_, const_edge< PolicyT, StringT > const& edge_source_ )
00324     {
00325         StringT const& str = edge_source_.parent().container().text();
00326         size_t source_from_offset_ = edge_source_.first.offset();   // a substring of the source string
00327         size_t source_to_offset_ = edge_source_.second.offset();
00328 
00329         size_t str_length = source_to_offset_ - source_from_offset_;
00330 
00331         if ( !str_length )
00332             return; // nothing to do
00333 
00334         size_t insertion_offset = node_target_.offset();
00335 
00336         node_target_.parent().container().text().insert(
00337             insertion_offset,
00338             str,
00339             source_from_offset_,
00340             str_length
00341             );
00342 
00343         m_region_map.adjust(
00344             insertion_offset,
00345             str_length
00346             );
00347         
00348         xtl_identity_insert_stay< StringT > insert_stay(
00349             insertion_offset,
00350             str_length
00351             );
00352 
00353         size_t idx = 0;
00354         for ( idx = 0; idx < node_target_.parent().container().identity_vector().size(); ++idx )
00355             insert_stay.adjust( node_target_.parent().container().identity_vector()[ idx ] );
00356 
00357         for ( idx = 0; idx < node_target_.parent().container().offset_stack().size(); ++idx )
00358             insert_stay.adjust( node_target_.parent().container().offset_stack()[ idx ] );
00359     }
00360 
00362     void region_clear()
00363     {
00364         m_region_map.clear();
00365     }
00366 
00368     void region_adjust( size_t after_offset_, int delta_offset_ )
00369     {
00370         m_region_map.adjust( after_offset_, delta_offset_ );
00371     }
00372 
00374     void region_insert( size_t first_offset_, size_t second_offset_ )
00375     {
00376         m_region_map.insert(
00377             first_offset_,
00378             second_offset_
00379             );
00380     }
00381 
00383     void region_erase( size_t first_offset_, size_t second_offset_ )
00384     {
00385         m_region_map.erase(
00386             first_offset_,
00387             second_offset_
00388             );
00389     }
00390 
00395     template< typename StringT >
00396     StringT region_difference( StringT const& str_, size_t first_offset_, size_t second_offset_ )
00397     {
00398         return m_region_map.text_difference(
00399             str_,
00400             first_offset_,
00401             second_offset_
00402             );
00403     }
00404 
00405 };  // class policy_mapped_space
00406 
00408 template< int White_spaceT = flag_follow_space >
00409 struct policy_space
00410 {
00411 };  // struct policy_space<>
00412 
00417 template<>
00418 struct policy_space< flag_follow_space > : public policy_default
00419 {
00420     template< typename UniverseT >
00421     size_t match( UniverseT& universe_ )
00422     {
00423         CTTL_TRACE_SILENT( true );
00424         typedef typename UniverseT::char_T char_T;
00425         size_t non_greedy_offset = universe_.first.offset();
00426         (
00427             true
00428             ^
00429             +(
00430                 symbol( char_T( ' ' ) )
00431                 |
00432                 symbol( char_T( '\n' ) )
00433                 |
00434                 symbol( char_T( '\r' ) )
00435                 |
00436                 symbol( char_T( '\t' ) )
00437                 |
00438                 symbol( char_T( '\v' ) )
00439                 |
00440                 symbol( char_T( '\f' ) )
00441             )
00442         ).match( universe_ );
00443         // policy_space is non-greedy:
00444         return non_greedy_offset;
00445     }
00446 };  // struct policy_space< flag_follow_space >
00447 
00458 template<>
00459 struct policy_space< flag_follow_region > : public policy_mapped_space
00460 {
00461     template< typename UniverseT >
00462     size_t match( UniverseT& universe_ )
00463     {
00464         size_t non_greedy_offset = universe_.first.offset();
00465         lower_bound( non_greedy_offset, universe_ );
00466         // policy_space is non-greedy:
00467         return non_greedy_offset;
00468     }
00469 };  // struct policy_space< flag_follow_region >
00470 
00471 
00477 template<>
00478 struct policy_space< flag_follow_space | flag_follow_region > : public policy_space< flag_follow_region >
00479 {
00480     template< typename UniverseT >
00481     size_t match( UniverseT& universe_ )
00482     {
00483         CTTL_TRACE_SILENT( true );
00484         typedef typename UniverseT::char_T char_T;
00485         size_t non_greedy_offset = universe_.first.offset();
00486         policy_mapped_space::match(
00487             true
00488             ^
00489             +(
00490                 symbol( char_T( ' ' ) )
00491                 |
00492                 symbol( char_T( '\n' ) )
00493                 |
00494                 symbol( char_T( '\r' ) )
00495                 |
00496                 symbol( char_T( '\t' ) )
00497                 |
00498                 symbol( char_T( '\v' ) )
00499                 |
00500                 symbol( char_T( '\f' ) )
00501             ),
00502             universe_
00503         );
00504         // policy_space is non-greedy:
00505         return non_greedy_offset;
00506     }
00507 };  // struct policy_space< flag_follow_space | flag_follow_region >
00508 
00509 
00511 template<>
00512 struct policy_space< flag_greedy | flag_follow_space > : public policy_space< flag_follow_space >
00513 {
00514     template< typename UniverseT >
00515     size_t match( UniverseT& universe_ )
00516     {
00517         CTTL_TRACE_SILENT( true );
00518         typedef typename UniverseT::char_T char_T;
00519         (
00520             true
00521             ^
00522             +(
00523                 symbol( char_T( ' ' ) )
00524                 |
00525                 symbol( char_T( '\n' ) )
00526                 |
00527                 symbol( char_T( '\r' ) )
00528                 |
00529                 symbol( char_T( '\t' ) )
00530                 |
00531                 symbol( char_T( '\v' ) )
00532                 |
00533                 symbol( char_T( '\f' ) )
00534             )
00535         ).match( universe_ );
00536         // greedy evaluation:
00537         return universe_.first.offset();
00538     }
00539 };  // struct policy_space< flag_greedy | flag_follow_space >
00540 
00541 
00543 template<>
00544 struct policy_space< flag_greedy > : public policy_space< flag_greedy | flag_follow_space >
00545 {
00546 };  // struct policy_space< flag_greedy >
00547 
00548 
00550 template<>
00551 struct policy_space< flag_greedy | flag_follow_region > : public policy_space< flag_follow_region >
00552 {
00553     template< typename UniverseT >
00554     size_t match( UniverseT& universe_ )
00555     {
00556         lower_bound( universe_.first.offset(), universe_ );
00557         // greedy evaluation:
00558         return universe_.first.offset();
00559     }
00560 };  // struct policy_space< flag_greedy | flag_follow_region >
00561 
00562 
00564 template<>
00565 struct policy_space< flag_greedy | flag_follow_space | flag_follow_region > : public policy_space< flag_follow_space | flag_follow_region >
00566 {
00567     template< typename UniverseT >
00568     size_t match( UniverseT& universe_ )
00569     {
00570         CTTL_TRACE_SILENT( true );
00571         typedef typename UniverseT::char_T char_T;
00572         policy_mapped_space::match(
00573             true
00574             ^
00575             +(
00576                 symbol( char_T( ' ' ) )
00577                 |
00578                 symbol( char_T( '\n' ) )
00579                 |
00580                 symbol( char_T( '\r' ) )
00581                 |
00582                 symbol( char_T( '\t' ) )
00583                 |
00584                 symbol( char_T( '\v' ) )
00585                 |
00586                 symbol( char_T( '\f' ) )
00587             ),
00588             universe_
00589         );
00590         // greedy evaluation:
00591         return universe_.first.offset();
00592     }
00593 };  // struct policy_space< flag_greedy | flag_follow_space | flag_follow_region >
00594 
00595 
00597 template<>
00598 struct policy_space< flag_cpp_comments > : public policy_default
00599 {
00600     template< typename UniverseT >
00601     static size_t match( UniverseT& universe_ )
00602     {
00603         CTTL_TRACE_SILENT( true );
00604         size_t non_greedy_offset = universe_.first.offset();
00605         (
00606             true ^ rule( policy_space< flag_cpp_comments >::space_and_comment )
00607 
00608         ).match( universe_ );
00609 
00610         // policy_space is non-greedy:
00611         return non_greedy_offset;
00612     }
00613 
00614     static size_t space_and_comment( const_edge< policy_default, CTTL_STD_STRING >& universe_ )
00615     {
00616         return (
00617             (
00618                 entity( isspace )
00619                 +
00620                 (
00621                     (
00622                         rule( policy_space< flag_cpp_comments >::comment )
00623                         +
00624                         rule( policy_space< flag_cpp_comments >::space_and_comment )
00625                     )
00626                     |
00627                     begin( true )
00628                 )
00629             )
00630             |
00631             (
00632                 rule( policy_space< flag_cpp_comments >::comment )
00633                 +
00634                 (
00635                     rule( policy_space< flag_cpp_comments >::space_and_comment )
00636                     |
00637                     begin( true )
00638                 )
00639             )
00640             |
00641             begin( true )
00642 
00643         ).match( universe_ );
00644     }
00645 
00646     static size_t comment( const_edge< policy_default, CTTL_STD_STRING >& universe_ )
00647     {
00648         return (
00649             begin( '/' )
00650             +
00651             (
00652                 ( symbol( '/' ) + symbol( '/' ) + !universe_.first( symbol( '\n' ) | end() ) )
00653                 |
00654                 ( symbol( '/' ) + symbol( '*' ) + !!( symbol( '*' ) + symbol( '/' ) ) )
00655             )
00656         ).match( universe_ );
00657     }
00658 
00659 };  // struct policy_space< flag_cpp_comments >
00660 
00661 
00663 template<>
00664 struct policy_space< flag_greedy | flag_cpp_comments > : public policy_space< flag_cpp_comments >
00665 {
00666     template< typename UniverseT >
00667     static size_t match( UniverseT& universe_ )
00668     {
00669         policy_space< flag_cpp_comments >::match( universe_ );
00670         return universe_.first.offset();
00671     }
00672 
00673 };
00674 
00675 }   // namespace cttl
00676 
00677 #endif // _CTTL_POLICY_H_INCLUDED_

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