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> ¯os) 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 : */
1.5.1-20070107