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
00029
00030
00031
00032
00033
00034 #include <lestes/common.hh>
00035 #include <lestes/std/source_location.hh>
00036 #include <lestes/lang/cplus/lex/macro_body.hh>
00037 #include <lestes/lang/cplus/lex/macro_body.m.hh>
00038 #include <lestes/lang/cplus/lex/macro_head.hh>
00039 #include <lestes/lang/cplus/lex/macro_item.hh>
00040 #include <lestes/lang/cplus/lex/token_sequence.hh>
00041 #include <lestes/lang/cplus/lex/pp_token.hh>
00042 #include <lestes/lang/cplus/lex/token_value.hh>
00043 #include <lestes/lang/cplus/lex/macro_argument.hh>
00044 #include <lestes/lang/cplus/lex/macro_arguments.hh>
00045 #include <lestes/lang/cplus/lex/concat.hh>
00046
00047 package(lestes);
00048 package(lang);
00049 package(cplus);
00050 package(lex);
00051
00052 using namespace ::std;
00053
00054
00055
00056
00057
00058
00059 macro_body::macro_body(void):
00060 state(BEGIN),
00061 items(items_type::create())
00062 {
00063 }
00064
00065
00066
00067
00068
00069
00070
00071 bool macro_body::parse(const ptr<token_input> &input, const ptr<macro_head> &head)
00072 {
00073 lassert(state == BEGIN);
00074
00075 enum {
00076 BEGIN,
00077 LITERAL,
00078 EXPAND,
00079 NONEXPAND,
00080 STRINGIFY,
00081 CONCAT,
00082 NEWLINE,
00083 END
00084 } fstate = BEGIN;
00085 ptr<pp_token> t;
00086 ptr<token_sequence> literal;
00087 ulint idx;
00088
00089 do {
00090
00091 if (fstate == BEGIN)
00092 t = input->read_front_skip_ws();
00093 else
00094 t = input->read_front();
00095
00096 if (t->is_name()) {
00097 idx = head->index_of(t->value_get());
00098
00099 if (idx == head->length()) {
00100
00101 if (fstate != LITERAL) {
00102 literal = token_sequence::create();
00103 fstate = LITERAL;
00104 }
00105 literal->add_back(t);
00106 } else {
00107 if (fstate == CONCAT) {
00108
00109 items->push_back(macro_item::create_copy(idx));
00110 fstate = NONEXPAND;
00111 } else {
00112 if (fstate == LITERAL) {
00113
00114 items->push_back(macro_item::create_literal(literal));
00115 }
00116 items->push_back(macro_item::create_expansion(idx));
00117 fstate = EXPAND;
00118 }
00119 }
00120 } else if (t->type_get() == pp_token::TOK_HASH) {
00121 if (fstate == LITERAL) {
00122
00123 items->push_back(macro_item::create_literal(literal));
00124 }
00125
00126 literal = token_sequence::create();
00127
00128 literal->add_back(t);
00129 t = input->read_front();
00130
00131 if (t->type_get() == pp_token::TOK_BLANK) {
00132
00133 literal->add_back(t);
00134
00135 t = input->read_front_skip_ws();
00136 }
00137
00138 if (!t->is_name() ||
00139 (idx = head->index_of(t->value_get())) == head->length()) {
00140
00141 report << hash_without_parameter << t->location_get();
00142
00143 if (t->type_get() != pp_token::TOK_LINE_END) goto error_cleanup;
00144 state = DEAD;
00145 return false;
00146 }
00147 items->push_back(macro_item::create_str(idx,literal));
00148
00149 fstate = STRINGIFY;
00150 } else if (t->type_get() == pp_token::TOK_HASH_HASH) {
00151 switch (fstate) {
00152 case BEGIN:
00153
00154 report << hash_hash_at_beginning << t->location_get();
00155 goto error_cleanup;
00156 case LITERAL:
00157
00158 if (!(items->size() && literal->length() == 1 && literal->peek_front() == pp_token::TOK_BLANK &&
00159 items->back()->action_get() == macro_item::EXPANSION)) break;
00160
00161 case EXPAND:
00162 {
00163
00164 ptr<macro_item> mbi = items->back();
00165 items->pop_back();
00166
00167 items->push_back(macro_item::create_copy(mbi->index_get()));
00168 }
00169 break;
00170 case STRINGIFY:
00171 case CONCAT:
00172
00173 break;
00174 case END:
00175 default:
00176 lassert2(false,"You should never get here");
00177 break;
00178 }
00179 if (fstate == LITERAL) {
00180
00181 items->push_back(macro_item::create_literal(literal));
00182 }
00183
00184 literal = token_sequence::create();
00185 literal->add_back(t);
00186
00187 items->push_back(macro_item::create_concat(literal));
00188 fstate = CONCAT;
00189 } else if (t->type_get() == pp_token::TOK_LINE_END) {
00190 if (fstate == CONCAT) {
00191
00192 report << hash_hash_at_end << t->location_get();
00193 state = DEAD;
00194 return false;
00195 }
00196 if (fstate == LITERAL && literal->skip_back_ws()) {
00197
00198 items->push_back(macro_item::create_literal(literal));
00199 }
00200 fstate = END;
00201 } else {
00202 if (fstate != LITERAL) {
00203 literal = token_sequence::create();
00204 fstate = LITERAL;
00205 }
00206 literal->add_back(t);
00207 }
00208 } while (fstate != END);
00209 state = PARSED;
00210 return true;
00211 error_cleanup:
00212
00213 do {
00214 t = input->read_front_skip_ws();
00215 } while (t->type_get() != pp_token::TOK_LINE_END);
00216 state = DEAD;
00217 return false;
00218 }
00219
00220
00221
00222
00223
00224
00225
00226
00227 bool macro_body::parse(const ptr<token_input> &input)
00228 {
00229 lassert(state == BEGIN);
00230
00231 ptr<token_sequence> literal;
00232 enum { BEGIN, LITERAL, CONCAT, END } fstate = BEGIN;
00233 ptr<pp_token> t;
00234
00235 do {
00236 if (fstate == BEGIN)
00237 t = input->read_front_skip_ws();
00238 else
00239 t = input->read_front();
00240
00241 if (t->type_get() == pp_token::TOK_HASH_HASH) {
00242
00243 if (fstate == BEGIN) {
00244
00245 report << hash_hash_at_beginning << t->location_get();
00246
00247 do {
00248 t = input->read_front_skip_ws();
00249 } while (t->type_get() != pp_token::TOK_LINE_END);
00250 state = DEAD;
00251 return false;
00252 }
00253
00254 if (fstate == LITERAL) {
00255
00256 items->push_back(macro_item::create_literal(literal));
00257 }
00258
00259 literal = token_sequence::create();
00260 literal->add_back(t);
00261
00262 items->push_back(macro_item::create_concat(literal));
00263 fstate = CONCAT;
00264 } else if (t->type_get() == pp_token::TOK_LINE_END) {
00265 switch (fstate) {
00266 case BEGIN:
00267
00268 break;
00269 case CONCAT:
00270
00271 report << hash_hash_at_end << t->location_get();
00272 state = DEAD;
00273 return false;
00274 case LITERAL:
00275 if (literal->skip_back_ws()) {
00276
00277 items->push_back(macro_item::create_literal(literal));
00278 }
00279 break;
00280 case END:
00281 default:
00282 lassert2(false,"You should never get here");
00283 break;
00284 }
00285 fstate = END;
00286 } else {
00287 if (fstate != LITERAL) {
00288
00289 literal = token_sequence::create();
00290 fstate = LITERAL;
00291 }
00292 literal->add_back(t);
00293 }
00294 } while (fstate != END);
00295 state = PARSED;
00296 return true;
00297 }
00298
00299
00300
00301
00302
00303
00304
00305 ptr<token_sequence> macro_body::expand(const ptr<source_location> &loc)
00306 {
00307 lassert(state == PARSED);
00308
00309 ptr<token_sequence> result = token_sequence::create();
00310 ptr<token_sequence> current;
00311 bool concat = false;
00312 items_type::iterator it = items->begin();
00313 items_type::iterator last = items->end();
00314
00315 for ( ; it != last; ++it) {
00316 ptr<macro_item> mi = *it;
00317
00318 switch (mi->action_get()) {
00319 case macro_item::CONCAT:
00320 if (concat) {
00321
00322 current = mi->value_get();
00323 } else {
00324 concat = true;
00325
00326 current = NULL;
00327 }
00328 break;
00329 case macro_item::LITERAL:
00330
00331 current = mi->value_get();
00332 break;
00333 default:
00334 lassert2(false,"You should never get here");
00335 break;
00336 }
00337
00338 if (concat) {
00339
00340
00341 if (current && current->skip_front_ws()) {
00342
00343
00344
00345
00346 ptr<pp_token> left = result->read_back_skip_ws();
00347
00348 ptr<pp_token> right = current->read_front();
00349
00350
00351 result->append(concat::instance()->process(left,right));
00352
00353 result->append(current);
00354
00355 concat = false;
00356 }
00357 } else {
00358
00359 result->append(current);
00360 }
00361 }
00362
00363
00364 lassert(concat != true);
00365
00366 return result->clone(loc);
00367 }
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379 ptr<token_sequence> macro_body::expand(const ptr<source_location> &loc,
00380 const ptr<macro_arguments> &mas, const ptr<macro_storage> ¯os)
00381 {
00382 lassert(state == PARSED);
00383
00384 ptr<token_sequence> result = token_sequence::create();
00385 ptr<token_sequence> current;
00386 ptr<pp_token> left;
00387 bool concat = false;
00388 items_type::iterator it = items->begin();
00389 items_type::iterator last = items->end();
00390
00391 for ( ; it != last; ++it) {
00392 ptr<macro_item> mi = *it;
00393 ptr<macro_argument> ma;
00394
00395 switch (mi->action_get()) {
00396 case macro_item::CONCAT:
00397 if (concat) {
00398
00399 current = mi->value_get();
00400 } else {
00401 concat = true;
00402 current = NULL;
00403 }
00404 break;
00405 case macro_item::LITERAL:
00406 current = mi->value_get();
00407 break;
00408 case macro_item::EXPANSION:
00409 ma = mas->argument_get(mi->index_get());
00410 current = ma->expanded_get(macros);
00411 break;
00412 case macro_item::COPY:
00413 ma = mas->argument_get(mi->index_get());
00414 current = ma->nonexpanded_get();
00415 break;
00416 case macro_item::STR:
00417 ma = mas->argument_get(mi->index_get());
00418 current = ma->stringified_get();
00419 break;
00420 default:
00421 lassert2(false,"You should never get here");
00422 break;
00423 }
00424
00425 if (concat) {
00426
00427 if (current && current->skip_front_ws()) {
00428
00429
00430
00431
00432 ptr<pp_token> left =
00433 result->skip_back_ws() ? result->read_back() : ptr<pp_token>(NULL);
00434 ptr<pp_token> right = current->read_front();
00435
00436
00437 result->append(concat::instance()->process(left,right));
00438
00439 result->append(current);
00440
00441 concat = false;
00442 }
00443 } else {
00444
00445 result->append(current);
00446 }
00447
00448 }
00449
00450 if (concat) {
00451
00452 ptr<pp_token> left =
00453 result->skip_back_ws() ? result->read_back() : ptr<pp_token>(NULL);
00454
00455 ptr<pp_token> right =
00456 current->skip_front_ws() ? current->read_front() : ptr<pp_token>(NULL);
00457
00458
00459 result->append(concat::instance()->process(left,right));
00460
00461 result->append(current);
00462
00463 concat = false;
00464 }
00465
00466 return result->clone(loc);
00467 }
00468
00469
00470
00471
00472
00473 macro_body::state_type macro_body::state_get(void) const
00474 {
00475 return state;
00476 }
00477
00478
00479
00480
00481
00482
00483 bool macro_body::equals(const ptr<macro_body> &other) const
00484 {
00485 if (!other || state != other->state_get()) return false;
00486
00487 if (state != PARSED) return true;
00488
00489 if (items->size() != other->items->size()) return false;
00490
00491 items_type::iterator it = items->begin();
00492 items_type::iterator last = items->end();
00493
00494 items_type::iterator ot = other->items->begin();
00495
00496 for ( ; it != last; ++it, ++ot) {
00497 ptr<macro_item> mi = *it;
00498 ptr<macro_item> oi = *ot;
00499
00500 if (!is_equal(mi,oi)) return false;
00501 }
00502
00503 return true;
00504 }
00505
00506
00507
00508
00509 void macro_body::gc_mark(void)
00510 {
00511 items.gc_mark();
00512 ::lestes::std::object::gc_mark();
00513 }
00514
00515
00516
00517
00518
00519
00520 ptr<macro_body> macro_body::create(void)
00521 {
00522 return new macro_body();
00523 }
00524
00525 end_package(lex);
00526 end_package(cplus);
00527 end_package(lang);
00528 end_package(lestes);
00529