macro_head.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 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 : */

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