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 parameter list. 00030 00031 Definition of macro_head class representing list of macro parameters. 00032 \author pt 00033 */ 00034 #include <lestes/common.hh> 00035 #include <lestes/lang/cplus/lex/macro_head.hh> 00036 #include <lestes/lang/cplus/lex/macro_head.m.hh> 00037 #include <lestes/lang/cplus/lex/token_value.hh> 00038 #include <lestes/lang/cplus/lex/token_sequence.hh> 00039 #include <lestes/lang/cplus/lex/pp_token.hh> 00040 00041 #include <iostream> 00042 00043 package(lestes); 00044 package(lang); 00045 package(cplus); 00046 package(lex); 00047 00048 using namespace ::std; 00049 00050 /*! 00051 Constructs empty parameter list. 00052 \post state == BEGIN 00053 \post length() == 0 00054 \post pars->size() == 0 00055 */ 00056 macro_head::macro_head(void): 00057 state(BEGIN), 00058 pars(pars_type::create()) 00059 { 00060 } 00061 00062 /*! 00063 Parses macro parameter list. 00064 \pre state == BEGIN 00065 \pre input != NULL 00066 \param input The source for tokens, starting after left parenthesis. 00067 \return false In case of duplicate parameters or unterminated parameter list. 00068 */ 00069 bool macro_head::parse(const ptr<token_input> &input) 00070 { 00071 lassert(state_get() == BEGIN); 00072 lassert(input); 00073 00074 ptr<pp_token> t; 00075 pp_token_type ptt; 00076 00077 t = input->read_front_skip_ws(); 00078 00079 // function like macro with no parameters 00080 if (t->type_get() == pp_token::TOK_RIGHT_PAR) { 00081 state = PARSED; 00082 return true; 00083 } 00084 00085 // first parameter is handled separately 00086 if (!t->is_name()) { 00087 // expected macro parameter name identifier 00088 report << expected_macro_parameter << t->location_get(); 00089 state = DEAD; 00090 return false; 00091 } 00092 00093 // first cannot be duplicate 00094 add_param(t->value_get()); 00095 00096 // read until terminating `)' 00097 while (t = input->read_front_skip_ws(), (ptt = t->type_get()) != pp_token::TOK_RIGHT_PAR) { 00098 00099 if (ptt != pp_token::TOK_COMMA) { 00100 if (ptt == pp_token::TOK_LINE_END) { 00101 // unterminated macro parameter list 00102 report << expected_right_par << t->location_get(); 00103 } else if (t->is_name()) { 00104 // macro parameters must be comma separated 00105 report << expected_comma << t->location_get(); 00106 } else { 00107 // invalid token in macro parameter list 00108 report << expected_comma_right_par << t->spelling_get() << t->location_get(); 00109 } 00110 state = DEAD; 00111 return false; 00112 } 00113 00114 t = input->read_front_skip_ws(); 00115 if (!t->is_name()) { 00116 // expected parameter name identifier 00117 report << expected_macro_parameter << t->location_get(); 00118 state = DEAD; 00119 return false; 00120 } 00121 00122 if (!add_param(t->value_get())) { 00123 // duplicate macro parameter 00124 report << duplicate_macro_parameter << t->spelling_get() << t->location_get(); 00125 state = DEAD; 00126 return false; 00127 } 00128 } 00129 00130 state = PARSED; 00131 return true; 00132 } 00133 00134 /*! 00135 Adds parameter to list. 00136 \pre a_value != NULL 00137 \param a_value Value to be added as parameter. 00138 \return false If the value was already present in the list. 00139 */ 00140 bool macro_head::add_param(const ptr<token_value> &a_value) 00141 { 00142 lassert(a_value); 00143 if (pars->insert(make_pair(a_value,pars->size())).second == false) return false; 00144 return true; 00145 } 00146 00147 /*! 00148 Returns index of parameter in list. 00149 \pre state == PARSED 00150 \pre a_value != NULL 00151 \return The index of the parameter, length() if parameter is not present. 00152 */ 00153 ulint macro_head::index_of(const ptr<token_value> &a_value) const 00154 { 00155 lassert(state_get() == PARSED); 00156 lassert(a_value); 00157 pars_type::const_iterator it = pars->find(a_value); 00158 if (it == pars->end()) return pars->size(); 00159 return (*it).second; 00160 } 00161 00162 /*! 00163 Returns length of the parameter list, which is also a special return value in index_of method. 00164 \pre state == PARSED 00165 \return Length of the parameter list. 00166 */ 00167 ulint macro_head::length(void) const 00168 { 00169 lassert(state_get() == PARSED); 00170 return pars->size(); 00171 } 00172 00173 /*! 00174 Returns internal state of the object. 00175 \return The internal state of the object. 00176 */ 00177 macro_head::state_type macro_head::state_get(void) const 00178 { 00179 return state; 00180 } 00181 00182 /*! 00183 Tests equality to other macro head. 00184 \param other The macro head to compare with. 00185 \return true If both parameter lists have the same length and spelling. 00186 */ 00187 bool macro_head::equals(const ptr<macro_head> &other) const 00188 { 00189 ::std::cerr << "macro_head::equals\n"; 00190 if (!other || state != other->state_get()) return false; 00191 ::std::cerr << "state ok\n"; 00192 if (state != PARSED) return true; 00193 ulint len = length(); 00194 if (len != other->length()) return false; 00195 ::std::cerr << "length ok\n"; 00196 00197 for (pars_type::iterator it = pars->begin(); it != pars->end(); ++it) { 00198 ptr<token_value> tv = (*it).first; 00199 ulint idx = (*it).second; 00200 00201 if (other->index_of(tv) != idx) return false; 00202 ::std::cerr << "par " << idx << " ok\n"; 00203 } 00204 00205 return true; 00206 } 00207 00208 /*! 00209 Marks the object. 00210 */ 00211 void macro_head::gc_mark(void) 00212 { 00213 pars.gc_mark(); 00214 ::lestes::std::object::gc_mark(); 00215 } 00216 00217 /*! 00218 Returns empty macro head. 00219 \post state == BEGIN 00220 \return A new empty instance of macro head. 00221 */ 00222 ptr<macro_head> macro_head::create(void) 00223 { 00224 return new macro_head(); 00225 } 00226 00227 end_package(lex); 00228 end_package(cplus); 00229 end_package(lang); 00230 end_package(lestes); 00231 /* vim: set ft=lestes : */
1.5.1-20070107