macro.cc

Go to the documentation of this file.
00001 /*
00002    The lestes compiler suite
00003    Copyright (C) 2002, 2003, 2004, 2005 Miroslav Tichy
00004    Copyright (C) 2002, 2003, 2004, 2005 Petr Zika
00005    Copyright (C) 2002, 2003, 2004, 2005 Vojtech Hala
00006    Copyright (C) 2002, 2003, 2004, 2005 Jiri Kosina
00007    Copyright (C) 2002, 2003, 2004, 2005 Pavel Sanda
00008    Copyright (C) 2002, 2003, 2004, 2005 Jan Zouhar
00009    Copyright (C) 2002, 2003, 2004, 2005 Rudolf Thomas
00010 
00011    This program is free software; you can redistribute it and/or modify
00012    it under the terms of the GNU General Public License as published by
00013    the Free Software Foundation; version 2 of the License.
00014 
00015    This program is distributed in the hope that it will be useful,
00016    but WITHOUT ANY WARRANTY; without even the implied warranty of
00017    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018    GNU General Public License for more details.
00019 
00020    See the full text of the GNU General Public License version 2, and
00021    the limitations in the file doc/LICENSE.
00022 
00023    By accepting the license the licensee waives any and all claims
00024    against the copyright holder(s) related in whole or in part to the
00025    work, its use, and/or the inability to use it.
00026  
00027  */
00028 /*! \file
00029   \brief Preprocessor macro.
00030   
00031   Definition of macro class representing preprocessor macro.
00032   \author pt
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   Creates new empty macro object.
00059   \post state == BEGIN
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   Parses macro parameter list, sets funlike and stores parameters into self.
00074   \param input  The source for tokens, starting after macro name.
00075   \return false  In case of duplicate parameters or unterminated parameter list.
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                 // no parameters
00084                 return true;
00085         }
00086         
00087         // discard the left par
00088         input->read_front();
00089         
00090         funlike = true;
00091 
00092         return head->parse(input);
00093 }
00094 
00095 /*!
00096   Parses macro replacement list and stores values into self.  
00097   \param input  The source for tokens, starting at the beginning of the replacement list.
00098   \return false  If the replacement list was ill-formed.
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   Parses macro name and stores into self.
00107   \param input  The source for tokens, starting before macro name.
00108   \return false  In case of parse error.
00109 */
00110 bool macro::parse_name(const ptr<token_input> &input)
00111 {
00112         ptr<pp_token> t = input->read_front_skip_ws();
00113 
00114         // the location of the macro will be the name in the definition
00115         location = t->location_get();
00116 
00117         if (t->type_get() == pp_token::TOK_LINE_END) {
00118                 // no macro name at all
00119                 report << definition_expects_macro_name << location;
00120                 return false;
00121         }
00122 
00123         if (t->is_alternative()) {
00124                 // C++ operator alternative spelling are not identifiers
00125                 report << macro_name_alt_operator << t->spelling_get() << location;
00126                 return false;
00127         }
00128         
00129         if (!t->is_name()) {
00130                 // macro name must be an identifier
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                 // defined is reserved as macro name
00139                 report << defined_invalid_macro_name << location;
00140                 return false;
00141         }
00142         
00143         return true;
00144 }
00145 
00146 /*!
00147   Parses macro definition and stores data into self.
00148   \pre state == BEGIN 
00149   \param input  The source for tokens, starting before macro name.
00150   \return false  In case of parse error.
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   Returns the location of definition.
00174   \pre state == PARSED
00175   \return  The location of the macro name in the #define.
00176 */
00177 ptr<source_location> macro::location_get(void) const 
00178 {
00179         return location;
00180 }
00181 
00182 /*!
00183   Returns the name of the macro.
00184   \pre state == PARSED 
00185   \return The name of the macro.
00186 */
00187 ptr<token_value> macro::name_get(void) const
00188 {
00189         lassert(state == PARSED);
00190         return name;
00191 }
00192 
00193 /*!
00194   Returns predefined flag.
00195   \pre state == PARSED 
00196   \return true  If the macro is predefined.
00197 */
00198 bool macro::predefined_get(void) const
00199 {
00200         lassert(state == PARSED);
00201         return predefined;
00202 }
00203 
00204 /*!
00205   Returns whether the macro is function-like.
00206   \pre state == PARSED
00207   \return true  If the macro is function-like.
00208 */
00209 bool macro::funlike_get(void) const
00210 {
00211         lassert(state == PARSED);
00212         return funlike;
00213 }
00214 
00215 /*!
00216   Expands this macro, if the call matches the definition, taking possible arguments from input.
00217   \param input  The source of possible arguments, starting at macro name.
00218   \param loc  The location of the macro expansion.
00219   \return The sequence containing the token denoting the name if the call did not match.
00220   \return The expanded, but not rescanned sequence if the call matched the definition.
00221   \return NULL in case of nested error.
00222 */
00223 ptr<token_sequence> macro::expand(const ptr<pp_token> &a_name, const ptr<token_input> &input,
00224                 const ptr<macro_storage> &macros)
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                         // missing terminating `)'
00235                         report << unterminated_argument_list << name->content_get() << loc;
00236                         return NULL;
00237                 }
00238 
00239                 if (!mas->check(head->length())) {
00240                         // argument count is different from parameter count
00241                         report << invalid_argument_count << name->content_get() << mas->length() << loc;
00242                         return NULL;
00243                 }
00244 
00245                 // expand function-like
00246                 return body->expand(loc,mas,macros);
00247         }
00248         // expand object-like
00249         return body->expand(loc);
00250 }
00251 
00252 /*!
00253   Returns whether macro definitions are equal.
00254   \param other  The macro to compare with.
00255   \return true  If the definition is equal to other.
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   Marks the object.
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   Returns empty macro.
00281   \post state == BEGIN
00282   \return A new empty instance of macro.
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 /* vim: set ft=lestes : */

Generated on Mon Feb 12 18:22:40 2007 for lestes by doxygen 1.5.1-20070107