token_sequence.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 Token sequence.
00030 
00031         Definition of token_sequence class representing sequence of tokens.
00032         \author pt
00033 */
00034 #include <lestes/common.hh>
00035 #include <lestes/std/source_location.hh>
00036 #include <lestes/std/file_info.hh>
00037 #include <lestes/lang/cplus/lex/token_sequence.hh>
00038 #include <lestes/lang/cplus/lex/pp_token.hh>
00039 #include <lestes/lang/cplus/lex/pp_token.hh>
00040 #include <lestes/lang/cplus/lex/taboo_macros.hh>
00041 #include <lestes/lang/cplus/lex/macro.hh>
00042 #include <lestes/lang/cplus/lex/macro_storage.hh>
00043 #include <lestes/lang/cplus/lex/token_value.hh>
00044 
00045 #include <iterator>
00046 #include <iostream>
00047 
00048 package(lestes);
00049 package(lang);
00050 package(cplus);
00051 package(lex);
00052 
00053 using namespace ::std;
00054 
00055 /*!
00056   Constructs new empty sequence.
00057   \post length() == 0
00058 */
00059 token_sequence::token_sequence(void):
00060         sequence(sequence_type::create())
00061 {
00062 }
00063 
00064 /*!
00065   Reads front token, does no transformation.
00066   \return  The first token in the sequence.
00067 */
00068 ptr<pp_token> token_sequence::read(void)
00069 {
00070         if (length() == 0) return pp_token::terminator();
00071         ptr<pp_token> t = sequence->front();
00072         sequence->pop_front();
00073         return t;
00074 }
00075 
00076 /*!
00077   Returns front token, which is kept in the sequence.
00078   \return  The first token in the sequence, or TOK_TERMINATOR.
00079 */
00080 ptr<pp_token> token_sequence::peek_front(void)
00081 {
00082         if (length() != 0) return sequence->front();
00083         return pp_token::terminator();
00084 }
00085         
00086 /*!
00087   Returns back token, which is kept in the sequence.
00088   \return  The last token in the sequence, or TOK_TERMINATOR.
00089 */
00090 ptr<pp_token> token_sequence::peek_back(void)
00091 {
00092         if (length() == 0) return pp_token::terminator();
00093         return sequence->back();
00094 }
00095 
00096 /*!
00097   Reads front token, squeezing multiple blanks into one.
00098   \return  The first token in the sequence.
00099 */
00100 ptr<pp_token> token_sequence::read_front(void)
00101 {
00102         ulint len = length();
00103         if (!len) return pp_token::terminator();
00104         
00105         ptr<pp_token> t = sequence->front();
00106         sequence->pop_front();
00107         len--;
00108         
00109         if (t->type_get() == pp_token::TOK_BLANK) {
00110                 ptr<pp_token> u;
00111                 while (len--) {
00112                         u = sequence->front();
00113                         if (u->type_get() != pp_token::TOK_BLANK) break;
00114                         sequence->pop_front();
00115                 }
00116         }
00117         
00118         return t;
00119 }
00120 
00121 /*!
00122   Reads front token, skipping front whitespace, but not newline.
00123   \return  The first non-whitespace token in the sequence, or TOK_TERMINATOR.
00124 */
00125 ptr<pp_token> token_sequence::read_front_skip_ws(void)
00126 {
00127         ptr<pp_token> t;
00128         ulint len = length();
00129         
00130         while (len--) {
00131                 t = sequence->front();
00132                 sequence->pop_front();
00133                 if (t->type_get() != pp_token::TOK_BLANK)
00134                         return t;
00135         }
00136         
00137         return pp_token::terminator();
00138 }
00139 
00140 /*!
00141   Reads back token, squeezing blanks.
00142   \return The last token in the sequence, or TOK_TERMINATOR.
00143 */
00144 ptr<pp_token> token_sequence::read_back(void)
00145 {
00146         ulint len = length();
00147         
00148         if (!len) return pp_token::terminator();
00149         
00150         ptr<pp_token> t = sequence->back();
00151         sequence->pop_back();
00152         len--;
00153         
00154         if (t->type_get() == pp_token::TOK_BLANK) {
00155                 ptr<pp_token> u;
00156                 while (len--) {
00157                         u = sequence->back();
00158                         if (u->type_get() != pp_token::TOK_BLANK) break;
00159                         sequence->pop_back();
00160                 }
00161         }
00162         
00163         return t;
00164 }
00165 
00166 /*!
00167   Reads back token, skipping back whitespace.
00168   \pre The sequence contains non-whitespace tokens.
00169   \return The last non-whitespace token in the sequence.
00170 */
00171 ptr<pp_token> token_sequence::read_back_skip_ws(void)
00172 {
00173         ptr<pp_token> t;
00174         ulint len = length();
00175         
00176         while (len--) {
00177                 t = sequence->back();
00178                 sequence->pop_back();
00179                 if (t->type_get() != pp_token::TOK_BLANK)
00180                         return t;
00181         }
00182         
00183         return pp_token::terminator();
00184 }
00185 
00186 /*!
00187   Skips front whitespace.
00188   \return true  If there are some tokens left in the sequence.
00189 */
00190 bool token_sequence::skip_front_ws(void)
00191 {
00192         sequence_type::size_type len = sequence->size();
00193         while (len && sequence->front()->type_get() == pp_token::TOK_BLANK) {
00194                 sequence->pop_front();
00195                 len--;
00196         }
00197         return len;
00198 }
00199 
00200 /*!
00201   Skips back whitespace.
00202   \return true  If there are some tokens left in the sequence.
00203 */
00204 bool token_sequence::skip_back_ws(void)
00205 {
00206         sequence_type::size_type len = sequence->size();
00207         while (len && sequence->back()->type_get() == pp_token::TOK_BLANK) {
00208                 sequence->pop_back();
00209                 len--;
00210         }
00211         return len;
00212 }
00213 
00214 /*!
00215   Adds token to back of the sequence.
00216   \pre a_token != NULL
00217   \param a_token  The token to add.
00218 */
00219 void token_sequence::add_back(const ptr<pp_token> &a_token)
00220 {
00221         lassert(a_token);
00222         sequence->push_back(a_token);
00223 }
00224 
00225 /*!
00226   Expands macros within sequence. The sequence is discarded.
00227   \pre macros != NULL
00228   \post length() == 0
00229   \param macros  The macros for expansion.
00230   \return The expanded tokens in a new sequence.
00231 */
00232 ptr<token_sequence> token_sequence::expand_all(const ptr<macro_storage> &macros)
00233 {
00234         lassert(macros);
00235 
00236         ptr<token_sequence> result = token_sequence::create();
00237 
00238         if (!length()) return result;
00239         
00240         ptr<pp_token> t = sequence->front();
00241         pp_token_type ptt = t->type_get();
00242 
00243         ptr<macro> mac;
00244         ptr<token_sequence> expanded;
00245         
00246         while (length()) {
00247                 t = sequence->front();
00248                 sequence->pop_front();
00249                 
00250                 ptt = t->type_get();
00251                 
00252                 // check whether the token is defined as macro
00253                 // whether the macro is allowed in the context of the token
00254                 // and whether a funlike macro is called with '('
00255                 if (t->is_name() &&
00256                          (mac = macros->lookup(t->value_get())) &&
00257                          !t->taboo_get()->contains(mac) &&
00258                          (!mac->funlike_get() || peek_front()->type_get() == pp_token::TOK_LEFT_PAR)) {
00259 
00260                         ptr<token_sequence> expanded = mac->expand(t,this,macros);
00261 
00262                         expanded->taboo_extend(t->taboo_get()->extend(mac),macros);
00263 
00264                         // prepend in O(1) to allow rescanning
00265                         prepend(expanded);
00266                 } else {
00267                         result->add_back(t);
00268                 }
00269         }
00270         return result;
00271 }
00272 
00273 /*!
00274   Extends taboo set for possibly expandable tokens in sequence by a macro.
00275   \pre a_macro != NULL
00276   \pre macros != NULL
00277   \param a_macro  The macro to add to the taboo set.
00278   \param macros  The defined macros.
00279 */
00280 void token_sequence::taboo_extend(const ptr<taboo_macros> &tm, const ptr<macro_storage> &macros)
00281 {
00282         lassert(tm);
00283         lassert(macros);
00284 
00285         ptr<pp_token> t;
00286         
00287         for (sequence_type::iterator it = sequence->begin(),
00288                   end = sequence->end(); it != end; ++it) {
00289                 t = *it;
00290                 
00291                 // extend only currently defined macros
00292                 if (t->is_name() &&
00293                          macros->lookup(t->value_get())) {
00294                         // extend taboo for token by mac
00295                         
00296                         *it = t->clone(tm);
00297                 }
00298         }
00299 }
00300 
00301 /*!
00302   Returns copy of the sequence.
00303   \post is_equal(returned,this)
00304   \return New sequence with equal values.
00305 */
00306 ptr<token_sequence> token_sequence::clone(void) const
00307 {
00308         ptr<token_sequence> nju = token_sequence::create();
00309         copy(sequence->begin(),sequence->end(),back_inserter(*(nju->sequence)));
00310         return nju;
00311 }
00312 
00313 /*!
00314   Returns a copy of the sequence with new location.
00315   \pre a_location != NULL
00316   \param a_location  The location for the copied tokens.
00317   \return The copy of the sequence.
00318 */
00319 ptr<token_sequence> token_sequence::clone(const ptr<source_location> &a_location) const
00320 {
00321         lassert(a_location);
00322         
00323         ptr<pp_token> t;
00324         ptr<token_sequence> nju = token_sequence::create();
00325 
00326         sequence_type::iterator it = sequence->begin();
00327         sequence_type::iterator end = sequence->end();
00328         
00329         for (; it != end; ++it) {
00330                 t = *it;
00331                 nju->add_back(t->clone(a_location));
00332         }
00333 
00334         return nju;
00335 }
00336 
00337 /*!
00338   Inserts another token sequence before the beginning of the sequence.
00339   \pre inserted != NULL
00340   \post inserted->length() == 0
00341   \param inserted  The sequence to insert, the content is moved into new place.
00342 */
00343 void token_sequence::prepend(const ptr<token_sequence> &inserted)
00344 {
00345         lassert(inserted);
00346         sequence->splice(sequence->begin(),*(inserted->sequence));
00347 }
00348 
00349 /*!
00350   Inserts another token sequence after the end of the sequence.
00351   \pre inserted != NULL
00352   \post inserted->length() == 0
00353   \param inserted  The sequence to insert, the content is moved into new place.
00354 */
00355 void token_sequence::append(const ptr<token_sequence> &inserted)
00356 {
00357         lassert(inserted);
00358         sequence->splice(sequence->end(),*(inserted->sequence));
00359 }
00360 
00361 /*!
00362   Returns length of the sequence.
00363   \return The length of the sequence.
00364 */
00365 token_sequence::size_type token_sequence::length(void) const
00366 {
00367         return sequence->size();
00368 }
00369 
00370 /*!
00371   Returns empty token sequence.
00372   \return  Empty token sequence.
00373 */
00374 ptr<token_sequence> token_sequence::create(void)
00375 {
00376         return new token_sequence();
00377 }
00378 
00379 /*!
00380   Tests equality to other token sequence.
00381   \param other  The token sequence to compare with.
00382   \return true  If both sequences contain equal tokens.
00383 */
00384 bool token_sequence::equals(const ptr<token_sequence> &other) const
00385 {
00386         if (!other || length() != other->length()) return false;
00387         
00388         sequence_type::iterator it = sequence->begin();
00389         sequence_type::iterator end = sequence->end();
00390 
00391         sequence_type::iterator ot = other->sequence->begin();
00392         
00393         for (; it != end; ++it, ++ot) {
00394                 ptr<pp_token> pt = *it;
00395                 ptr<pp_token> qt = *ot;
00396                 
00397                 if (!is_equal(pt,qt)) return false;
00398         }
00399         
00400         return true;
00401 }
00402 
00403 /*!
00404   Tests whether sequences have the same type and spelling of tokens.
00405   \param other  The token sequence to compare with.
00406   \return true  If both sequences contain interchangeable tokens.
00407 */
00408 bool token_sequence::congruent(const ptr<token_sequence> &other) const
00409 {
00410         // TODO pt ::std::cerr << "token_sequence::resembles\n";
00411         // TODO pt debug_print( ::std::cerr); ::std::cerr << '\n';
00412         // TODO pt ::std::cerr << other << '\n';
00413         
00414         if (!other || length() != other->length()) return false;
00415         
00416         // TODO pt ::std::cerr << "length ok\n";
00417         
00418         sequence_type::iterator it = sequence->begin();
00419         sequence_type::iterator end = sequence->end();
00420 
00421         sequence_type::iterator ot = other->sequence->begin();
00422         
00423         for (; it != end; ++it, ++ot) {
00424                 ptr<pp_token> pt = *it;
00425                 ptr<pp_token> qt = *ot;
00426                 
00427                 if (!pt->congruent(qt)) return false;
00428                 // TODO pt ::std::cerr << pt->description_get() << " is congruent to " << qt->description_get() << '\n';
00429         }
00430         
00431         return true;
00432 }
00433 
00434 /*!
00435   Marks the object.
00436 */
00437 void token_sequence::gc_mark(void)
00438 {
00439         sequence.gc_mark();
00440         token_input::gc_mark();
00441 }
00442 
00443 /*!
00444   Prints debug dump of content to stream.
00445   \param o  The stream to print to.
00446 */
00447 void token_sequence::debug_print(ostream &o) const
00448 {
00449         bool next = false;
00450 
00451         for (sequence_type::iterator it = sequence->begin(), end = sequence->end();
00452                   it != end; ++it) {
00453                 if (next) o << ' '; else next = true;
00454                 o << (*it)->spelling_get();
00455         }
00456 }
00457 
00458 /*!
00459   Prints debug dump of token sequence to stream.
00460   \param o  The stream to print to.
00461   \param ts  The token sequence to print.
00462 */
00463 ::std::ostream &operator<<(::std::ostream &o, const ptr<token_sequence> &ts) {
00464         ts->debug_print(o);
00465         return o;
00466 }
00467 
00468 end_package(lex);
00469 end_package(cplus);
00470 end_package(lang);
00471 end_package(lestes);
00472 /* vim: set ft=lestes : */

Generated on Mon Feb 12 18:23:43 2007 for lestes by doxygen 1.5.1-20070107