00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00023
00035
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;
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();
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;
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;
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();
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;
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 };
00406
00408 template< int White_spaceT = flag_follow_space >
00409 struct policy_space
00410 {
00411 };
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
00444 return non_greedy_offset;
00445 }
00446 };
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
00467 return non_greedy_offset;
00468 }
00469 };
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
00505 return non_greedy_offset;
00506 }
00507 };
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
00537 return universe_.first.offset();
00538 }
00539 };
00540
00541
00543 template<>
00544 struct policy_space< flag_greedy > : public policy_space< flag_greedy | flag_follow_space >
00545 {
00546 };
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
00558 return universe_.first.offset();
00559 }
00560 };
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
00591 return universe_.first.offset();
00592 }
00593 };
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
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 };
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 }
00676
00677 #endif // _CTTL_POLICY_H_INCLUDED_