#include <macro_body.hh>
Inheritance diagram for lestes::lang::cplus::lex::macro_body:

Public Types | |
| enum | state_type { BEGIN, PARSED, DEAD } |
| type of internal state More... | |
Public Member Functions | |
| bool | parse (const ptr< token_input > &input) |
| parses object-like macro body | |
| bool | parse (const ptr< token_input > &input, const ptr< macro_head > &head) |
| parses function-like macro body | |
| ptr< token_sequence > | expand (const ptr< source_location > &loc) |
| expands object-like macro | |
| ptr< token_sequence > | expand (const ptr< source_location > &loc, const ptr< macro_arguments > &mas, const ptr< macro_storage > ¯os) |
| expands function-like macro | |
| state_type | state_get (void) const |
| returns internal state | |
| bool | equals (const ptr< macro_body > &other) const |
| tests equality | |
Static Public Member Functions | |
| static ptr< macro_body > | create (void) |
| returns empty expansion list | |
Protected Member Functions | |
| macro_body (void) | |
| creates empty expansion list | |
| virtual void | gc_mark (void) |
| Marks the object. | |
Private Types | |
| typedef ::lestes::std::vector< srp< macro_item > > | items_type |
| type of list for storing the expansion items | |
Private Attributes | |
| state_type | state |
| internal state of the object | |
| srp< items_type > | items |
| the list of expansion items | |
Definition at line 61 of file macro_body.hh.
typedef ::lestes::std::vector< srp<macro_item> > lestes::lang::cplus::lex::macro_body::items_type [private] |
type of internal state
Definition at line 64 of file macro_body.hh.
00064 { BEGIN, PARSED, DEAD } state_type;
| lestes::lang::cplus::lex::macro_body::macro_body | ( | void | ) | [protected] |
creates empty expansion list
Constructs empty expansion list.
items->size() == 0
Definition at line 59 of file macro_body.cc.
Referenced by create().
00059 : 00060 state(BEGIN), 00061 items(items_type::create()) 00062 { 00063 }
| bool lestes::lang::cplus::lex::macro_body::parse | ( | const ptr< token_input > & | input | ) |
parses object-like macro body
Parses object-like macro replacement list and stores values into self. The input is parsed including the TOK_LINE_END even in case it is ill-formed.
| input | The source for tokens, starting at the beginning of the replacement list. |
Definition at line 227 of file macro_body.cc.
References BEGIN, lestes::lang::cplus::lex::token_sequence::create(), lestes::lang::cplus::lex::macro_item::create_concat(), lestes::lang::cplus::lex::macro_item::create_literal(), DEAD, lestes::lang::cplus::lex::hash_hash_at_beginning, lestes::lang::cplus::lex::hash_hash_at_end, items, lassert, lassert2, PARSED, lestes::report, state, lestes::lang::cplus::lex::pp_token::TOK_HASH_HASH, and lestes::lang::cplus::lex::pp_token::TOK_LINE_END.
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 // check whether the ## is not at the beginning 00243 if (fstate == BEGIN) { 00244 // ## at the beginning of expansion list 00245 report << hash_hash_at_beginning << t->location_get(); 00246 // discard tokens till end of line 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 // flush the literal 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 // macro with no content has no macro items 00268 break; 00269 case CONCAT: 00270 // ## at the end of the expansion list 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 // flush the literal 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 // start new literal 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 }
| bool lestes::lang::cplus::lex::macro_body::parse | ( | const ptr< token_input > & | input, | |
| const ptr< macro_head > & | head | |||
| ) |
parses function-like macro body
Parses function like macro replacement list and stores values into self.
| input | The source for tokens, starting after parameter list. |
Definition at line 71 of file macro_body.cc.
References BEGIN, lestes::lang::cplus::lex::token_sequence::create(), lestes::lang::cplus::lex::macro_item::create_concat(), lestes::lang::cplus::lex::macro_item::create_copy(), lestes::lang::cplus::lex::macro_item::create_expansion(), lestes::lang::cplus::lex::macro_item::create_literal(), lestes::lang::cplus::lex::macro_item::create_str(), DEAD, lestes::lang::cplus::lex::macro_item::EXPANSION, lestes::lang::cplus::lex::hash_hash_at_beginning, lestes::lang::cplus::lex::hash_hash_at_end, lestes::lang::cplus::lex::hash_without_parameter, items, lassert, lassert2, PARSED, lestes::report, state, lestes::lang::cplus::lex::pp_token::TOK_BLANK, lestes::lang::cplus::lex::pp_token::TOK_HASH, lestes::lang::cplus::lex::pp_token::TOK_HASH_HASH, and lestes::lang::cplus::lex::pp_token::TOK_LINE_END.
00072 { 00073 lassert(state == BEGIN); 00074 // state of parser 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 // TODO pt ::std::cerr << "fstate = " << fstate["blenscXQ"] << '\n'; 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 // if idx is invalid 00099 if (idx == head->length()) { 00100 // ordinary identifier is a part of a literal 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 // no expansion after concatenation 00109 items->push_back(macro_item::create_copy(idx)); 00110 fstate = NONEXPAND; 00111 } else { 00112 if (fstate == LITERAL) { 00113 // flush the literal 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 // flush the literal 00123 items->push_back(macro_item::create_literal(literal)); 00124 } 00125 00126 literal = token_sequence::create(); 00127 // save the hash 00128 literal->add_back(t); 00129 t = input->read_front(); 00130 00131 if (t->type_get() == pp_token::TOK_BLANK) { 00132 // add the blank 00133 literal->add_back(t); 00134 // get the parameter 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 // # operator without parameter 00141 report << hash_without_parameter << t->location_get(); 00142 // need cleanup till the end of line 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 // ## at the beginning of expansion list 00154 report << hash_hash_at_beginning << t->location_get(); 00155 goto error_cleanup; 00156 case LITERAL: 00157 // check whether there is EXPAND preceding 00158 if (!(items->size() && literal->length() == 1 && literal->peek_front() == pp_token::TOK_BLANK && 00159 items->back()->action_get() == macro_item::EXPANSION)) break; 00160 // fall through 00161 case EXPAND: 00162 { 00163 // update preceding expansion 00164 ptr<macro_item> mbi = items->back(); 00165 items->pop_back(); 00166 // update to avoid expansion 00167 items->push_back(macro_item::create_copy(mbi->index_get())); 00168 } 00169 break; 00170 case STRINGIFY: 00171 case CONCAT: 00172 // okay 00173 break; 00174 case END: 00175 default: 00176 lassert2(false,"You should never get here"); 00177 break; 00178 } 00179 if (fstate == LITERAL) { 00180 // flush the literal 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 // ## at the end of the expansion list 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 // flush the literal 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 // discard tokens till end of line 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 }
| ptr< token_sequence > lestes::lang::cplus::lex::macro_body::expand | ( | const ptr< source_location > & | loc | ) |
expands object-like macro
Expand this object-like macro body.
| loc | The location of the expansion. |
Definition at line 305 of file macro_body.cc.
References lestes::lang::cplus::lex::macro_item::CONCAT, lestes::lang::cplus::lex::token_sequence::create(), lestes::lang::cplus::lex::concat::instance(), items, lassert, lassert2, lestes::lang::cplus::lex::macro_item::LITERAL, PARSED, and state.
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 // concatenating with ## literal 00322 current = mi->value_get(); 00323 } else { 00324 concat = true; 00325 // signal first round 00326 current = NULL; 00327 } 00328 break; 00329 case macro_item::LITERAL: 00330 // assign because current is NULL or empty 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 // if there is token for the right side 00341 if (current && current->skip_front_ws()) { 00342 00343 // TODO pt remove ::std::cerr << "WILL run concat on " << current << ::std::endl; 00344 00345 // concat is always after tokens 00346 ptr<pp_token> left = result->read_back_skip_ws(); 00347 // whitespace already cleared 00348 ptr<pp_token> right = current->read_front(); 00349 00350 // errors are handled transparently inside concatenate 00351 result->append(concat::instance()->process(left,right)); 00352 // add the rest of the right part 00353 result->append(current); 00354 00355 concat = false; 00356 } 00357 } else { 00358 // no pending concatenation 00359 result->append(current); 00360 } 00361 } 00362 00363 // concatenation shall not be at the end 00364 lassert(concat != true); 00365 // TODO clone(taboo macros, loc) 00366 return result->clone(loc); 00367 }
| ptr< token_sequence > lestes::lang::cplus::lex::macro_body::expand | ( | const ptr< source_location > & | loc, | |
| const ptr< macro_arguments > & | mas, | |||
| const ptr< macro_storage > & | macros | |||
| ) |
expands function-like macro
Expands this function-like macro body.
pt Add location setting.
NULL in case of error.
Definition at line 379 of file macro_body.cc.
References lestes::lang::cplus::lex::macro_item::CONCAT, lestes::lang::cplus::lex::macro_item::COPY, lestes::lang::cplus::lex::token_sequence::create(), lestes::lang::cplus::lex::macro_item::EXPANSION, lestes::lang::cplus::lex::concat::instance(), items, lassert, lassert2, lestes::lang::cplus::lex::macro_item::LITERAL, PARSED, state, and lestes::lang::cplus::lex::macro_item::STR.
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 // concatenating with ## literal 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 // if there is token for the right side 00427 if (current && current->skip_front_ws()) { 00428 00429 // TODO pt remove ::std::cerr << "WILL run () concat on " << current << ::std::endl; 00430 00431 // check back token 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 // errors are handled transparently inside concatenate 00437 result->append(concat::instance()->process(left,right)); 00438 // add the rest of the right part 00439 result->append(current); 00440 00441 concat = false; 00442 } 00443 } else { 00444 // no pending concatenation 00445 result->append(current); 00446 } 00447 00448 } 00449 00450 if (concat) { 00451 // check back token 00452 ptr<pp_token> left = 00453 result->skip_back_ws() ? result->read_back() : ptr<pp_token>(NULL); 00454 // check front token 00455 ptr<pp_token> right = 00456 current->skip_front_ws() ? current->read_front() : ptr<pp_token>(NULL); 00457 00458 // errors are handled transparently inside concatenate 00459 result->append(concat::instance()->process(left,right)); 00460 // add the rest of the right part 00461 result->append(current); 00462 00463 concat = false; 00464 } 00465 00466 return result->clone(loc); 00467 }
| macro_body::state_type lestes::lang::cplus::lex::macro_body::state_get | ( | void | ) | const |
| bool lestes::lang::cplus::lex::macro_body::equals | ( | const ptr< macro_body > & | other | ) | const |
tests equality
Tests equality.
| other | The macro body to compare with. |
Definition at line 483 of file macro_body.cc.
References lestes::is_equal(), items, PARSED, and state.
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 }
| ptr< macro_body > lestes::lang::cplus::lex::macro_body::create | ( | void | ) | [static] |
returns empty expansion list
Returns empty expansion list.
Definition at line 520 of file macro_body.cc.
References macro_body().
00521 { 00522 return new macro_body(); 00523 }
| void lestes::lang::cplus::lex::macro_body::gc_mark | ( | void | ) | [protected, virtual] |
Marks the object.
Marks the object.
Reimplemented from lestes::std::mem::keystone.
Definition at line 509 of file macro_body.cc.
References lestes::std::mem::keystone::gc_mark(), and items.
00510 { 00511 items.gc_mark(); 00512 ::lestes::std::object::gc_mark(); 00513 }
internal state of the object
Definition at line 89 of file macro_body.hh.
Referenced by equals(), expand(), parse(), and state_get().
srp<items_type> lestes::lang::cplus::lex::macro_body::items [private] |
1.5.1-20070107