00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include <lestes/lang/cplus/lex/preprocessor.hh>
00029 #include <lestes/lang/cplus/syn/errors.m.hh>
00030 #include <lestes/lang/cplus/syn/hinter.hh>
00031 #include <lestes/lang/cplus/syn/manager.hh>
00032 #include <lestes/lang/cplus/syn/prefixer.hh>
00033 #include <lestes/lang/cplus/syn/syn.hh>
00034 #include <lestes/lang/cplus/syn/token.hh>
00035 #include <lestes/msg/logger.hh>
00036 #include <lestes/std/list.hh>
00037 #include <lestes/std/objectize_macros.hh>
00038 #include <lestes/std/source_location.hh>
00039 #include <stack>
00040 #include <map>
00041 #include <set>
00042 #include <iostream>
00043
00044 package(lestes);
00045 package(lang);
00046 package(cplus);
00047 package(syn);
00048
00049 typedef list< srp<bison_token> > token_list_type;
00050 typedef token_list_type::iterator token_list_iterator;
00051 typedef list< srp<action> > action_list_type;
00052
00053 end_package(syn);
00054 end_package(cplus);
00055 end_package(lang);
00056 package(std);
00057
00058 specialize_objectize_nodump( ::lestes::lang::cplus::syn::token_list_iterator );
00059
00060 end_package(std);
00061 package(lang);
00062 package(cplus);
00063 package(syn);
00064
00065 declare_logger( ml );
00066 initialize_logger( ml, "manager", syn_logger );
00067
00068 initialize_event( manager::spawn_event );
00069 initialize_event( manager::close_event );
00070 initialize_event( manager::start_event );
00071 initialize_event( manager::commit_event );
00072 initialize_event( manager::rollback_event );
00073
00074 typedef list<token_list_iterator> iter_list_type;
00075
00076 class streamer : public ::lestes::std::object {
00077 public:
00078 virtual ptr<bison_token> first() abstract;
00079 virtual ptr<bison_token> next() abstract;
00080 };
00081
00082 class source_streamer : public streamer {
00083 private:
00084 static ptr<source_streamer> the_instance;
00085 protected:
00086 source_streamer() : streamer()
00087 {}
00088 public:
00089 static ptr<source_streamer> instance()
00090 {
00091
00092 lassert2( !the_instance, "We only allow calling this method once." );
00093 if (!the_instance)
00094 the_instance = new source_streamer();
00095 return the_instance;
00096 }
00097 virtual ptr<bison_token> first()
00098 {
00099 return bison_madeup_token::create(
00100 source_location::zero(), bison_token::TOK_START_PROGRAM );
00101 }
00102 virtual ptr<bison_token> next()
00103 {
00104 return prefixer::yylex();
00105 }
00106 };
00107
00108 ptr<source_streamer> source_streamer::the_instance;
00109
00110 class pack_streamer : public streamer {
00111 private:
00112 bool eof_sent;
00113 srp<bison_pack_token> tokpack;
00114 token_list_type::iterator it;
00115 protected:
00116 pack_streamer( ptr<bison_pack_token> tp )
00117 : eof_sent(false), tokpack(checked(tp))
00118 {}
00119 void gc_mark()
00120 {
00121 tokpack.gc_mark();
00122 streamer::gc_mark();
00123 }
00124 public:
00125 static ptr<pack_streamer> create( ptr<bison_pack_token> tp )
00126 {
00127 return new pack_streamer(tp);
00128 }
00129 virtual ptr<bison_token> first()
00130 {
00131 it = tokpack->pack_get()->begin();
00132 return tokpack;
00133 }
00134 virtual ptr<bison_token> next()
00135 {
00136 lassert2( !eof_sent, "Token requested, but EOF already sent." );
00137 if (it != tokpack->pack_get()->end())
00138 return *it++;
00139 eof_sent = true;
00140 lassert2( tokpack->end_location_get(),
00141 "The pack (token) does not have its end_location set." );
00142 return bison_madeup_token::create( tokpack->end_location_get(), bison_token::TOK_EOF );
00143 }
00144 };
00145
00146 class transaction : public ::lestes::std::object {
00147 protected:
00148
00149 srp<action_list_type> undo_list;
00150 const token_list_iterator start_pos;
00151
00152 transaction( const token_list_iterator & spos ) : start_pos(spos)
00153 {
00154 undo_list = action_list_type::create();
00155 }
00156 void gc_mark()
00157 {
00158 undo_list.gc_mark();
00159 object::gc_mark();
00160 }
00161 public:
00162 static ptr<transaction> create( const token_list_iterator & spos )
00163 {
00164 return new transaction(spos);
00165 }
00166 const token_list_iterator start_pos_get() const
00167 {
00168 return start_pos;
00169 }
00170
00171 ulint undo()
00172 {
00173 ulint result = 0;
00174 for (action_list_type::reverse_iterator it = undo_list->rbegin();
00175 it != undo_list->rend();
00176 ++it, ++result )
00177 (*it)->run();
00178 return result;
00179 }
00180
00181 void submit_undo( ptr<transaction> enclosing_tx )
00182 {
00183 lassert( enclosing_tx );
00184 enclosing_tx->undo_list->splice( enclosing_tx->undo_list->end(), *undo_list );
00185 }
00186
00187 void add_undo_action( ptr<action> action )
00188 {
00189 lassert( action );
00190 undo_list->push_back( action );
00191 }
00192 };
00193
00194 class undo_delete_token : public action {
00195 protected:
00196 srp<token_list_type> token_list;
00197 const token_list_iterator position;
00198
00199 undo_delete_token( ptr<token_list_type> a_list, const token_list_iterator &pos )
00200 : token_list(a_list), position(pos)
00201 {}
00202 public:
00203 static ptr<undo_delete_token> create( ptr<token_list_type> a_list,
00204 const token_list_iterator &pos )
00205 {
00206 return new undo_delete_token( a_list, pos );
00207 }
00208 virtual void run()
00209 {
00210 token_list->erase(position);
00211 }
00212 };
00213
00214
00215 class undo_unpack : public undo_delete_token {
00216 protected:
00217 srp<token_list_type> pack;
00218 undo_unpack( ptr<token_list_type> a_list, const token_list_iterator &pos,
00219 ptr<token_list_type> a_pack ) : undo_delete_token( a_list, pos ), pack(a_pack)
00220 {}
00221 void gc_mark()
00222 {
00223 pack.gc_mark();
00224 undo_delete_token::gc_mark();
00225 }
00226 public:
00227 static ptr<undo_unpack> create( ptr<token_list_type> a_list, const token_list_iterator &pos,
00228 ptr<token_list_type> a_pack )
00229 {
00230 return new undo_unpack( a_list, pos, a_pack );
00231 }
00232 virtual void run()
00233 {
00234 token_list->splice( position, *pack );
00235 }
00236 };
00237
00238 class one_manager : public ::lestes::std::object {
00239 private:
00240 srp<streamer> src;
00241 srp<bison_token> last_token;
00242 protected:
00243 bool run_hinter;
00244 bool failing;
00245 srp<token_list_type> token_list;
00246 token_list_iterator token_list_pos;
00247
00248 srp< list< srp<transaction> > > open_transactions;
00249 protected:
00250 one_manager( const ptr<streamer> & );
00251 void gc_mark()
00252 {
00253 src.gc_mark();
00254 last_token.gc_mark();
00255 token_list.gc_mark();
00256 open_transactions.gc_mark();
00257 object::gc_mark();
00258 }
00259
00260 void find_closing( int closing, int opening, const ptr<source_location> & loc );
00261
00262
00263 static ::std::set<int> error_stmt_end_set;
00264 public:
00265 static ptr<one_manager> create( const ptr<streamer> & a_src )
00266 {
00267 return new one_manager(a_src);
00268 }
00269
00270 static void init();
00271
00272 ptr<bison_token> yylex();
00273 ptr<bison_token> prev_yylex();
00274 ptr<bison_token> peek();
00275 void back_up();
00276 void start( int );
00277 void commit( int );
00278 void rollback();
00279 ptr<bison_pack_token> pack( int, const ptr<source_location> & );
00280 void unpack();
00281 bool in_disambiguation() const;
00282 void install_undo_action( ptr<action> a );
00283 bool failing_get() const;
00284 void failing_set_true();
00285 };
00286
00287 ::std::set<int> one_manager::error_stmt_end_set;
00288
00289 void one_manager::init()
00290 {
00291 error_stmt_end_set.insert( bison_token::TOK_BREAK );
00292 error_stmt_end_set.insert( bison_token::TOK_CATCH );
00293 error_stmt_end_set.insert( bison_token::TOK_CONTINUE );
00294 error_stmt_end_set.insert( bison_token::TOK_DO );
00295 error_stmt_end_set.insert( bison_token::TOK_ELSE );
00296 error_stmt_end_set.insert( bison_token::TOK_FOR );
00297 error_stmt_end_set.insert( bison_token::TOK_GOTO );
00298 error_stmt_end_set.insert( bison_token::TOK_IF );
00299 error_stmt_end_set.insert( bison_token::TOK_RETURN );
00300 error_stmt_end_set.insert( bison_token::TOK_SWITCH );
00301 error_stmt_end_set.insert( bison_token::TOK_TRY );
00302 error_stmt_end_set.insert( bison_token::TOK_WHILE );
00303 error_stmt_end_set.insert( bison_token::TOK_SEMICOLON );
00304 error_stmt_end_set.insert( bison_token::TOK_EOF );
00305 error_stmt_end_set.insert( bison_token::TOK_LEFT_BRACE );
00306 error_stmt_end_set.insert( bison_token::TOK_RIGHT_BRACE );
00307 }
00308
00309
00310
00311
00312
00313 one_manager::one_manager( const ptr<streamer> & s )
00314 {
00315 src = s;
00316 last_token = NULL;
00317 run_hinter = true;
00318 failing = false;
00319 token_list = token_list_type::create();
00320 token_list->push_back( s->first() );
00321 token_list_pos = token_list->begin();
00322 open_transactions = list< srp<transaction> >::create();
00323 }
00324
00325 bool one_manager::in_disambiguation() const
00326 {
00327 return !open_transactions->empty();
00328 }
00329
00330 ptr<bison_token> one_manager::yylex()
00331 {
00332 ptr<bison_token> t = peek();
00333
00334 if (!in_disambiguation() && token_list_pos != token_list->begin())
00335 token_list->pop_front();
00336 ++token_list_pos;
00337
00338
00339
00340 if (run_hinter && t->type_get() == bison_token::TOK_IDENT)
00341 t = hinter::hint( t, peek() );
00342 last_token = t;
00343 return t;
00344 }
00345
00346 ptr<bison_token> one_manager::prev_yylex()
00347 {
00348 lassert2( last_token, "yylex() was not called previously." );
00349 return last_token;
00350 }
00351
00352 ptr<bison_token> one_manager::peek()
00353 {
00354 ptr<bison_token> t;
00355 if (token_list_pos == token_list->end()) {
00356 t = src->next();
00357 token_list_pos = token_list->insert( token_list_pos, t );
00358 } else
00359 t = *token_list_pos;
00360 return t;
00361 }
00362
00363 void one_manager::back_up()
00364 {
00365
00366
00367 lassert( token_list_pos != token_list->begin() );
00368
00369 lassert( open_transactions->empty() ||
00370 token_list_pos != open_transactions->back()->start_pos_get() );
00371
00372 --token_list_pos;
00373
00374 llog(ml) << "backing up " << ptr<bison_token>(*token_list_pos) << "\n";
00375 }
00376
00377 void one_manager::start( int type )
00378 {
00379 lassert( type > bison_token::_START_FIRST && type < bison_token::_START_LAST );
00380
00381 ptr<bison_token> t = bison_madeup_token::create( peek()->location_get(), type );
00382 token_list_pos = token_list->insert( token_list_pos, t );
00383 open_transactions->push_back( transaction::create(token_list_pos) );
00384 llog(ml) << "starting with " << t << "\n";
00385
00386 manager::start_event->trigger();
00387 }
00388
00389 void one_manager::commit( int type )
00390 {
00391 lassert( in_disambiguation() );
00392 lassert( type > bison_token::_PAD_FIRST && type < bison_token::_PAD_LAST );
00393
00394 ptr<transaction> this_tx = open_transactions->back();
00395 open_transactions->pop_back();
00396
00397 token_list_pos = this_tx->start_pos_get();
00398
00399
00400 ptr<bison_token> pad = bison_madeup_token::create( (*token_list_pos)->location_get(), type );
00401
00402 llog(ml) << "committing " << pad << " over " <<
00403 ptr<bison_token>(*this_tx->start_pos_get()) << "\n";
00404
00405
00406 *token_list_pos = pad;
00407
00408
00409 if (in_disambiguation()) {
00410 ptr<transaction> prev_tx = open_transactions->back();
00411 prev_tx->add_undo_action( undo_delete_token::create( token_list, token_list_pos ) );
00412 this_tx->submit_undo( prev_tx );
00413 }
00414
00415 manager::commit_event->trigger();
00416 }
00417
00418 void one_manager::rollback()
00419 {
00420 lassert( in_disambiguation() );
00421
00422 ptr<transaction> this_tx = open_transactions->back();
00423 open_transactions->pop_back();
00424
00425 llog(ml) << "rolling back " << ptr<bison_token>(*this_tx->start_pos_get());
00426 ulint count = this_tx->undo();
00427 token_list_pos = token_list->erase( this_tx->start_pos_get() );
00428
00429 llog_plain(ml) << " (" << count << " undo actions)\n";
00430
00431 manager::rollback_event->trigger();
00432 }
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447 ptr<bison_pack_token> one_manager::pack( int pack_type, const ptr<source_location> & start_loc )
00448 {
00449 lassert( pack_type > bison_token::_PACK_FIRST && pack_type < bison_token::_PACK_LAST );
00450
00451 bool run_hinter_old = run_hinter;
00452 run_hinter = false;
00453
00454 start( bison_token::TOK_START_TO_BE_DISCARDED );
00455
00456 yylex();
00457 switch (pack_type) {
00458 case bison_token::TOK_PACK_BODY:
00459 find_closing( bison_token::TOK_RIGHT_BRACE,
00460 bison_token::TOK_LEFT_BRACE, start_loc );
00461 break;
00462 case bison_token::TOK_PACK_ERROR_COND:
00463 find_closing( bison_token::TOK_RIGHT_PAR,
00464 bison_token::TOK_LEFT_PAR, start_loc );
00465 break;
00466 case bison_token::TOK_PACK_ERROR_FOR_COND:
00467 find_closing( bison_token::TOK_SEMICOLON,
00468 bison_token::TOK_SEMICOLON, start_loc );
00469 break;
00470 case bison_token::TOK_PACK_ERROR_STMT:
00471
00472 while (error_stmt_end_set.find( yylex()->type_get() ) == error_stmt_end_set.end())
00473 ;
00474
00475 if (prev_yylex()->type_get() == bison_token::TOK_SEMICOLON)
00476 yylex();
00477 break;
00478 default:
00479 lassert2( false, "This type of packing is not implemented yet." );
00480 }
00481
00482 token_list_iterator to = token_list_pos;
00483 commit( bison_token::TOK_PAD_TO_BE_DISCARDED );
00484 token_list_iterator from = token_list_pos;
00485
00486
00487 ++from;
00488 --to;
00489
00490
00491
00492
00493 ptr<bison_pack_token> pack_tok = bison_pack_token::create(
00494 (*from)->location_get(), pack_type, (*to)->location_get() );
00495
00496 ptr<token_list_type> the_pack = pack_tok->pack_get();
00497 the_pack->splice( the_pack->end(), *token_list, from, to );
00498
00499 ptr<action> unpack = undo_unpack::create( token_list, to, the_pack );
00500 if (in_disambiguation())
00501 open_transactions->back()->add_undo_action( unpack );
00502
00503 llog(ml) << "replacing " << ptr<bison_token>(*token_list_pos) <<
00504 " with " << ptr<bison_token>(pack_tok) << "\n";
00505 *token_list_pos = pack_tok;
00506
00507 run_hinter = run_hinter_old;
00508
00509 return pack_tok;
00510 }
00511
00512 void one_manager::unpack()
00513 {
00514 const ptr<bison_token> & next_tok = *token_list_pos;
00515 lassert( next_tok->type_get() > bison_token::_PACK_FIRST &&
00516 next_tok->type_get() < bison_token::_PACK_LAST );
00517 llog(ml) << "unpacking " << next_tok << "\n";
00518
00519 const ptr<bison_pack_token> & pack_tok = next_tok.dncast<bison_pack_token>();
00520
00521
00522 token_list_iterator pos_after_pack = token_list_pos;
00523 ++pos_after_pack;
00524 token_list->splice( pos_after_pack, *(pack_tok->pack_get()) );
00525
00526 token_list_pos = token_list->erase( token_list_pos );
00527 }
00528
00529 void one_manager::install_undo_action( ptr<action> a )
00530 {
00531 lassert( in_disambiguation() );
00532 open_transactions->back()->add_undo_action(a);
00533 }
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560 void one_manager::find_closing( int closing, int opening, const ptr<source_location> & loc )
00561 {
00562 lassert( loc );
00563 typedef list< srp<bison_token> > stack_type;
00564 ptr<stack_type> st = stack_type::create();
00565 while (true) {
00566 ptr<bison_token> t = yylex();
00567 int ttype = t->type_get();
00568 if (ttype == bison_token::TOK_EOF) {
00569
00570 if (st->empty())
00571 report << unmatched_open << loc;
00572 else
00573 report << unmatched_open << st->back()->location_get();
00574
00575 failing_set_true();
00576 break;
00577 }
00578 if (ttype == closing) {
00579 if (st->empty())
00580 break;
00581 else
00582 st->pop_back();
00583 } else if (ttype == opening)
00584 st->push_back( t );
00585 }
00586 }
00587
00588 bool one_manager::failing_get() const
00589 {
00590 return failing;
00591 }
00592
00593 void one_manager::failing_set_true()
00594 {
00595 failing = true;
00596 }
00597
00598 typedef list< srp<one_manager> > mgr_stack_type;
00599 static ptr<mgr_stack_type> mgr_stack;
00600
00601 void manager::init()
00602 {
00603 mgr_stack = mgr_stack_type::create();
00604 mgr_stack->push_back( one_manager::create( source_streamer::instance() ) );
00605
00606 one_manager::init();
00607 }
00608
00609 void manager::spawn( ptr<bison_pack_token> t )
00610 {
00611 mgr_stack->push_back( one_manager::create( pack_streamer::create(t) ) );
00612 spawn_event->trigger();
00613 }
00614
00615 void manager::close()
00616 {
00617 mgr_stack->pop_back();
00618 lassert( !mgr_stack->empty() );
00619 close_event->trigger();
00620 }
00621
00622 ptr<bison_token> manager::yylex()
00623 {
00624 lassert( !mgr_stack->empty() );
00625 return mgr_stack->back()->yylex();
00626 }
00627
00628 ptr<bison_token> manager::prev_yylex()
00629 {
00630 lassert( !mgr_stack->empty() );
00631 return mgr_stack->back()->prev_yylex();
00632 }
00633
00634 ptr<bison_token> manager::peek()
00635 {
00636 lassert( !mgr_stack->empty() );
00637 return mgr_stack->back()->peek();
00638 }
00639
00640 void manager::back_up()
00641 {
00642 lassert( !mgr_stack->empty() );
00643 mgr_stack->back()->back_up();
00644 }
00645
00646 void manager::start( int type )
00647 {
00648 lassert( !mgr_stack->empty() );
00649 mgr_stack->back()->start( type );
00650 }
00651
00652 void manager::commit( int type )
00653 {
00654 lassert( !mgr_stack->empty() );
00655 mgr_stack->back()->commit( type );
00656 }
00657
00658 void manager::rollback()
00659 {
00660 lassert( !mgr_stack->empty() );
00661 mgr_stack->back()->rollback();
00662 }
00663
00664 ptr<bison_pack_token> manager::pack( int pack_type, const ptr<source_location> & start_loc )
00665 {
00666 lassert( !mgr_stack->empty() );
00667 return mgr_stack->back()->pack( pack_type, start_loc );
00668 }
00669
00670 void manager::unpack()
00671 {
00672 lassert( !mgr_stack->empty() );
00673 mgr_stack->back()->unpack();
00674 }
00675
00676 bool manager::in_disambiguation()
00677 {
00678 lassert( !mgr_stack->empty() );
00679 return mgr_stack->back()->in_disambiguation();
00680 }
00681
00682 void manager::install_undo_action( ptr<action> a )
00683 {
00684 lassert( !mgr_stack->empty() );
00685 mgr_stack->back()->install_undo_action(a);
00686 }
00687
00688 bool manager::failing_get()
00689 {
00690 lassert( !mgr_stack->empty() );
00691 return mgr_stack->back()->failing_get();
00692 }
00693
00694 void manager::failing_set_true()
00695 {
00696 lassert( !mgr_stack->empty() );
00697 return mgr_stack->back()->failing_set_true();
00698 }
00699
00700 end_package(syn);
00701 end_package(cplus);
00702 end_package(lang);
00703 end_package(lestes);