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/equality.hh>
00036 #include <lestes/std/source_location.hh>
00037 #include <lestes/lang/cplus/lex/macro.hh>
00038 #include <lestes/lang/cplus/lex/macro.m.hh>
00039 #include <lestes/lang/cplus/lex/pp_token.hh>
00040 #include <lestes/lang/cplus/lex/token_value.hh>
00041 #include <lestes/lang/cplus/lex/token_input.hh>
00042 #include <lestes/lang/cplus/lex/token_sequence.hh>
00043 #include <lestes/lang/cplus/lex/macro_item.hh>
00044 #include <lestes/lang/cplus/lex/macro_head.hh>
00045 #include <lestes/lang/cplus/lex/macro_body.hh>
00046 #include <lestes/lang/cplus/lex/macro_arguments.hh>
00047
00048 #include <iostream>
00049
00050 package(lestes);
00051 package(lang);
00052 package(cplus);
00053 package(lex);
00054
00055 using namespace ::std;
00056
00057
00058
00059
00060
00061 macro::macro():
00062 state(BEGIN),
00063 location(),
00064 name(),
00065 funlike(false),
00066 predefined(false),
00067 head(macro_head::create()),
00068 body(macro_body::create())
00069 {
00070 }
00071
00072
00073
00074
00075
00076
00077 bool macro::parse_head(const ptr<token_input> &input)
00078 {
00079 ptr<pp_token> t = input->peek_front();
00080
00081 if (t->type_get() != pp_token::TOK_LEFT_PAR) {
00082 funlike = false;
00083
00084 return true;
00085 }
00086
00087
00088 input->read_front();
00089
00090 funlike = true;
00091
00092 return head->parse(input);
00093 }
00094
00095
00096
00097
00098
00099
00100 bool macro::parse_body(const ptr<token_input> &input)
00101 {
00102 return funlike ? body->parse(input,head) : body->parse(input);
00103 }
00104
00105
00106
00107
00108
00109
00110 bool macro::parse_name(const ptr<token_input> &input)
00111 {
00112 ptr<pp_token> t = input->read_front_skip_ws();
00113
00114
00115 location = t->location_get();
00116
00117 if (t->type_get() == pp_token::TOK_LINE_END) {
00118
00119 report << definition_expects_macro_name << location;
00120 return false;
00121 }
00122
00123 if (t->is_alternative()) {
00124
00125 report << macro_name_alt_operator << t->spelling_get() << location;
00126 return false;
00127 }
00128
00129 if (!t->is_name()) {
00130
00131 report << macro_name_identifier << location;
00132 return false;
00133 }
00134
00135 name = t->value_get();
00136
00137 if (is_equal(name,token_value::create("defined"))) {
00138
00139 report << defined_invalid_macro_name << location;
00140 return false;
00141 }
00142
00143 return true;
00144 }
00145
00146
00147
00148
00149
00150
00151
00152 bool macro::parse(const ptr<token_input> &input)
00153 {
00154 lassert(state == BEGIN);
00155
00156 if (!parse_name(input)) {
00157 state = DEAD;
00158 return false;
00159 }
00160 if (!parse_head(input)) {
00161 state = DEAD;
00162 return false;
00163 }
00164 if (!parse_body(input)) {
00165 state = DEAD;
00166 return false;
00167 }
00168 state = PARSED;
00169 return true;
00170 }
00171
00172
00173
00174
00175
00176
00177 ptr<source_location> macro::location_get(void) const
00178 {
00179 return location;
00180 }
00181
00182
00183
00184
00185
00186
00187 ptr<token_value> macro::name_get(void) const
00188 {
00189 lassert(state == PARSED);
00190 return name;
00191 }
00192
00193
00194
00195
00196
00197
00198 bool macro::predefined_get(void) const
00199 {
00200 lassert(state == PARSED);
00201 return predefined;
00202 }
00203
00204
00205
00206
00207
00208
00209 bool macro::funlike_get(void) const
00210 {
00211 lassert(state == PARSED);
00212 return funlike;
00213 }
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223 ptr<token_sequence> macro::expand(const ptr<pp_token> &a_name, const ptr<token_input> &input,
00224 const ptr<macro_storage> ¯os)
00225 {
00226 ptr<source_location> loc = a_name->location_get();
00227
00228 if (funlike_get()) {
00229 ptr<pp_token> tok = input->peek_front();
00230 lassert(tok->type_get() == pp_token::TOK_LEFT_PAR);
00231
00232 ptr<macro_arguments> mas = macro_arguments::create();
00233 if (!mas->parse(input)) {
00234
00235 report << unterminated_argument_list << name->content_get() << loc;
00236 return NULL;
00237 }
00238
00239 if (!mas->check(head->length())) {
00240
00241 report << invalid_argument_count << name->content_get() << mas->length() << loc;
00242 return NULL;
00243 }
00244
00245
00246 return body->expand(loc,mas,macros);
00247 }
00248
00249 return body->expand(loc);
00250 }
00251
00252
00253
00254
00255
00256
00257 bool macro::equals(const ptr<macro> &other) const
00258 {
00259 if (!other) return false;
00260
00261 if (!is_equal(head,other->head)) return false;
00262
00263 if (!is_equal(body,other->body)) return false;
00264 return true;
00265 }
00266
00267
00268
00269
00270 void macro::gc_mark(void)
00271 {
00272 location.gc_mark();
00273 name.gc_mark();
00274 head.gc_mark();
00275 body.gc_mark();
00276 ::lestes::std::object::gc_mark();
00277 }
00278
00279
00280
00281
00282
00283
00284 ptr<macro> macro::create(void)
00285 {
00286 return new macro();
00287 }
00288
00289 end_package(lex);
00290 end_package(cplus);
00291 end_package(lang);
00292 end_package(lestes);
00293