macro_argument.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 Macro argument.
00030   
00031   Definition of macro_argument class representing preprocessor macro argument.
00032   \author pt
00033 */
00034 #include <lestes/common.hh>
00035 #include <lestes/std/source_location.hh>
00036 #include <lestes/lang/cplus/lex/macro_argument.hh>
00037 #include <lestes/lang/cplus/lex/pp_token.hh>
00038 #include <lestes/lang/cplus/lex/token_sequence.hh>
00039 #include <lestes/lang/cplus/lex/token_value.hh>
00040 #include <lestes/lang/cplus/lex/stringifier.hh>
00041 
00042 package(lestes);
00043 package(lang);
00044 package(cplus);
00045 package(lex);
00046 
00047 /*!
00048   Creates empty macro argument.
00049   \post state == BEGIN
00050   \post nonexpanded == NULL
00051   \post expanded == NULL
00052   \post stringified == NULL
00053 */
00054 macro_argument::macro_argument(void):
00055         state(BEGIN),
00056         nonexpanded(NULL),
00057         expanded(NULL),
00058         stringified(NULL)
00059 {
00060 }
00061 
00062 /*!
00063   Parses single argument of macro. Front and back whitespace is discarded, newlines are converted to spaces.
00064   Value is stored into nonexpanded.
00065   \pre parse() was not called yet.
00066   \post state == DEAD || nonexpanded == contents of front part of input
00067   \param input  The source for arguments, parsed tokens (including terminating ones) are removed.
00068   \param first true If the argument is first in the argument list.
00069   \return macro_argument::LAST  When top level right parenthesis was encountered.
00070   \return macro_argument::EMPTY  When first argument was empty.
00071   \return macro_argument::CONTINUE  When top level comma was encountered. 
00072   \return macro_argument::ERROR  For end of file inside input.
00073 */
00074 macro_argument::result_type macro_argument::parse(const ptr<token_input> &input, bool first)
00075 {
00076         lassert(state == BEGIN);
00077         
00078         nonexpanded = token_sequence::create();
00079         result_type result = CONTINUE;
00080         ulint depth = 1;
00081 
00082         input->skip_front_ws();
00083         ptr<pp_token> t;
00084         pp_token_type ptt;
00085 
00086         ptr<pp_token> blank;
00087         
00088         while (input->peek_front()->type_get() == pp_token::TOK_LINE_END) {
00089                 input->read_front();
00090         }
00091         
00092         do {
00093                 t = input->read_front();
00094                 ptt = t->type_get();
00095 
00096                 switch (ptt) {
00097                         case pp_token::TOK_TERMINATOR:
00098                                 state = DEAD;
00099                                 return ERROR;
00100                         case pp_token::TOK_LEFT_PAR:
00101                                 depth++;
00102                                 break;
00103                         case pp_token::TOK_RIGHT_PAR:
00104                                 depth--;
00105                                 if (depth != 0) break;
00106                                 result = nonexpanded->length() == 0 && first ? EMPTY : LAST;
00107 
00108                                 state = PARSED;
00109                                 return result;
00110                         case pp_token::TOK_COMMA:
00111                                 if (depth != 1) break;
00112 
00113                                 state = PARSED;
00114                                 return result;
00115                         case pp_token::TOK_LINE_END:
00116                                 if (blank) continue;
00117                                 blank = pp_token::create(t->location_get(),pp_token::TOK_BLANK);
00118                                 break;
00119                         case pp_token::TOK_BLANK:
00120                                 if (blank) continue;
00121                                 blank = t;
00122                                 break;
00123                         default:
00124                                 break;
00125                 }
00126                 if (blank) {
00127                         nonexpanded->add_back(blank);
00128                         blank = NULL;
00129                 }
00130                 nonexpanded->add_back(t);
00131         } while (true);
00132 }
00133 
00134 /*!
00135   Returns internal state of the object.
00136   \return  The internal state of the object.
00137 */
00138 macro_argument::state_type macro_argument::state_get(void) const
00139 {
00140         return state;
00141 }
00142 
00143 /*!
00144   Returns the nonexpanded macro argument.
00145   \pre parse() != ERROR
00146   \return The nonexpanded token sequence.
00147 */  
00148 ptr<token_sequence> macro_argument::nonexpanded_get(void) const
00149 {
00150         lassert(state == PARSED);
00151         return nonexpanded->clone();
00152 }
00153 
00154 /*!
00155   Returns the completely expanded macro argument. Expansion is performed only once.
00156   \pre parse() != ERROR
00157   \return The completely expanded token sequence.
00158 */
00159 ptr<token_sequence> macro_argument::expanded_get(const ptr<macro_storage> &macros)
00160 {
00161         lassert(state == PARSED);
00162         if (!expanded) {
00163                 expanded = nonexpanded->clone();
00164                 expanded = expanded->expand_all(macros);
00165         }
00166         return expanded->clone();
00167 }
00168 
00169 /*!
00170   Returns stringified macro argument. Stringification is performed only once.
00171   \pre parse() != ERROR
00172   \return Token sequence containing single token with value equal to the stringified token sequence.
00173 */
00174 ptr<token_sequence> macro_argument::stringified_get(void)
00175 {
00176         lassert(state == PARSED);
00177         if (!stringified) {
00178                 ptr<pp_token> t = stringifier::instance()->process(nonexpanded->clone());
00179                 stringified = token_sequence::create();
00180                 stringified->add_back(t);
00181         }
00182         return stringified->clone();
00183 }
00184 
00185 /*!
00186   Tests equality to other macro argument. Only the nonexpanded sequences are compared.
00187   \param other  The macro argument to compare with.
00188   \return true  If both the objects are equal.
00189 */ 
00190 bool macro_argument::equals(const ptr<macro_argument> &other) const
00191 {
00192         if (!other || state_get() != other->state_get()) return false;
00193         if (state != PARSED) return true;
00194         
00195         // compare nonexpanded
00196         return is_equal(nonexpanded_get(),other->nonexpanded_get());
00197 }
00198 
00199 /*!
00200   Marks the object.
00201 */
00202 void macro_argument::gc_mark(void)
00203 {
00204         nonexpanded.gc_mark();
00205         expanded.gc_mark();
00206         stringified.gc_mark();
00207 	::lestes::std::object::gc_mark();
00208 }
00209 
00210 /*!
00211   Returns new empty macro argument.
00212   \post state == BEGIN
00213   \post nonexpanded == NULL
00214   \post expanded == NULL
00215   \post stringified == NULL
00216   \return New instance of the object.
00217 */
00218 ptr<macro_argument> macro_argument::create(void)
00219 {
00220         return new macro_argument();
00221 }
00222 
00223 end_package(lex);
00224 end_package(cplus);
00225 end_package(lang);
00226 end_package(lestes);
00227 /* vim: set ft=lestes : */

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