pp_lex.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 Integration with flexer.
00030   
00031   Definition of pp_lex class wrapping pp_lex_guts flexer.
00032   \author pt
00033 */
00034 
00035 #include <lestes/common.hh>
00036 #include <lestes/lang/cplus/lex/pp_lex.hh>
00037 #include <lestes/lang/cplus/lex/pp_lex.m.hh>
00038 #include <lestes/lang/cplus/lex/pp_token.hh>
00039 #include <lestes/lang/cplus/lex/pre_lex.hh>
00040 #include <lestes/lang/cplus/lex/token_value.hh>
00041 #include <lestes/lang/cplus/lex/ucn_token_buffer.hh>
00042 #include <lestes/lang/cplus/lex/line_control.hh>
00043 #include <lestes/lang/cplus/lex/lex_loggers.hh>
00044 #include <lestes/std/source_location.hh>
00045 #include <lestes/std/file_info.hh>
00046 
00047 // for pp_lex_guts
00048 #include <sstream>
00049 #include <ostream>
00050 #include <iomanip>
00051 #include <cctype>
00052 
00053 package(lestes);
00054 package(lang);
00055 package(cplus);
00056 package(lex);
00057 
00058 // include the flex generated parser in own separate namespace
00059 package(pp_lex_guts);
00060 #include <lestes/lang/cplus/lex/pp_lex_guts.yy.cc>
00061 end_package(pp_lex_guts);
00062 
00063 using namespace ::std;
00064 
00065 /*!
00066   Creates the object, allocates flex buffer.  
00067   \pre a_input != NULL
00068   \pre a_lines != NULL
00069   \post interactive == true
00070   \param a_input  The input stream of tokens.
00071   \param a_lines  The line control.
00072 */
00073 pp_lex::pp_lex(const ptr<pre_lex> &a_input, const ptr<line_control> &a_lines):
00074         interactive(true),
00075         input(checked(a_input)),
00076         physical(NULL),
00077         lines(checked(a_lines)),
00078         buffer(ucn_token_buffer::create(lines)),
00079         errors(ucn_token_buffer::create(lines)),
00080         yy_buffer(pp_lex_guts::yy_new_buffer(NULL,YY_BUF_SIZE))
00081 {
00082 }
00083 
00084 /*!
00085   Finalizes the object, releases flex buffer.
00086 */
00087 pp_lex::~pp_lex(void)
00088 {
00089         pp_lex_guts::yy_delete_buffer(yy_buffer);
00090 }
00091 
00092 /*!
00093   Prepares pp_lex_guts to work with this pp_lex.
00094   Sets pp_lex_guts shortcut variables current_utb and current_ppl.
00095 */
00096 void pp_lex::activate(void)
00097 {
00098         pp_lex_guts::current_utb = buffer.pointer_get();
00099         pp_lex_guts::current_ppl = this;
00100         yy_switch_to_buffer(yy_buffer);
00101 }
00102 
00103 /*!
00104   Saves location of current input token.
00105 */
00106 void pp_lex::location_save(void)
00107 {
00108         physical = buffer->peek_front()->location_get();
00109 }
00110 
00111 /*!
00112   Creates location from saved token, file information and line number correction.
00113   \pre location_save() was already called.
00114   \return New location with correct logical line.
00115 */
00116 ptr<source_location> pp_lex::location_create(void) const
00117 {
00118         lassert2(physical,"location_save() was not called yet");
00119         return lines->translate_location(physical);
00120 }
00121 
00122 /*!
00123   Reads next token from flex.
00124   \param line_start  Whether reading at start of line.
00125   \return  The token read from flex.
00126 */
00127 ptr<pp_token> pp_lex::read(bool line_start)
00128 {
00129         pp_lex_logger << "pp_lex::read()\n" << msg::eolog;
00130 
00131         pp_lex_logger << "errors length == " << errors->length() << '\n' << msg::eolog;
00132         while (errors->length()) {
00133                 ptr<ucn_token> tok = errors->peek_front();
00134                 errors->advance(1);
00135 
00136                 pp_lex_logger << "handling error from pre_lex\n" << msg::eolog;
00137                 pp_lex_logger << "error == " << tok->error_get() << msg::eolog;
00138 
00139                 report->report(tok->error_get(),lines->translate_location(tok->location_get()));
00140         }
00141 
00142         // this allows concurrent use of pp_lex_guts by different preprocessor instances
00143         if (pp_lex_guts::current_ppl != this) activate();
00144 
00145         ptr<pp_token> t = pp_lex_guts::lexer_parse(line_start);
00146 
00147         pp_lex_logger << "returning " << t->description_get() << "\n" << msg::eolog;
00148         pp_lex_logger << "pp_lex::read() end\n" << msg::eolog;
00149 
00150         return t;
00151 }
00152 
00153 /*!
00154   Reads token from input stream, stores it into buffer.
00155   \return The character representing the class of the token on input.
00156 */
00157 pp_lex::char_type pp_lex::read_char(void)
00158 {
00159         pp_lex_logger << "pp_lex::read_char()\n" << msg::eolog;
00160 
00161         ptr<ucn_token> tok = input->read();
00162         ucn_token_type utt = tok->type_get();
00163         
00164         while (utt == ucn_token::TOK_ERROR) {
00165                 pp_lex_logger << "cummulating error\n" << msg::eolog;
00166 
00167                 // cummulate errors
00168                 errors->add_back(tok);
00169 
00170                 tok = input->read();
00171                 utt = tok->type_get();
00172         }
00173                 
00174         // add the regular token
00175         buffer->add_back(tok);
00176 
00177         char_type c;
00178         switch (utt) {
00179                 case ucn_token::TOK_BASIC:
00180                         c = static_cast<char_type>(character::extract_value(tok->value_get()));
00181                         break;
00182                 case ucn_token::TOK_EOF:
00183                         // special character class
00184                         c = static_cast<char_type>(ucn_token::TOK_EOF);
00185                         break;
00186                 case ucn_token::TOK_TRANSLATED:
00187                         // special character class
00188                         c = static_cast<char_type>(ucn_token::TOK_TRANSLATED);
00189                         break;
00190                 default:
00191                         lassert2(false,"You should never get here");
00192         }
00193 
00194         pp_lex_logger << "returning " << static_cast<ulint>(c) << "\n" << msg::eolog;
00195         pp_lex_logger << "pp_lex::read_char() end\n" << msg::eolog;
00196         return c;
00197 }
00198 
00199 /*!
00200   Fills buffer with characters from current source file.
00201   Called through YY_INPUT flex macro.
00202   \param cbuf  The buffer to fill.
00203   \param max  Maximum count of characters to fill.  
00204   \return  The actual count of filled characters.
00205 */
00206 pp_lex::size_type pp_lex::yy_input(char_type *cbuf, size_type max)
00207 {
00208         pp_lex_logger << "pp_lex::yy_input()\n" << msg::eolog;
00209 
00210         // force the parser interactive
00211         if (interactive_get()) max = 1;
00212 
00213         // initialize not to interfere with the condition
00214         char_type c = ucn_token::TOK_NOT_EOF;
00215         size_type cnt = 0;
00216         
00217         // put all tokens up to max (including TOK_EOF) into buffer
00218         for (cnt = 0; cnt < max && c != ucn_token::TOK_EOF; cnt++) {
00219                 *cbuf++ = c = read_char();
00220         }
00221 
00222         pp_lex_logger << "pp_lex::yy_input() end\n" << msg::eolog;
00223 
00224         return cnt;
00225 }
00226 
00227 /*!
00228   Sets interactive flag.
00229   \param a_interactive  The new flag.
00230 */
00231 void pp_lex::interactive_set(bool a_interactive)
00232 {
00233         interactive = a_interactive;
00234 }
00235 
00236 /*!
00237   Returns interactive flag.
00238   \return The flag.
00239 */
00240 bool pp_lex::interactive_get(void) const
00241 {
00242         return interactive;
00243 }
00244 
00245 /*!
00246   Marks the object.
00247 */
00248 void pp_lex::gc_mark(void)
00249 {
00250         input.gc_mark();
00251         physical.gc_mark();
00252         lines.gc_mark();
00253         buffer.gc_mark();
00254         errors.gc_mark();
00255 	::lestes::std::object::gc_mark();
00256 }
00257 
00258 /*!
00259   Returns new instance of the object.
00260   \pre a_input != NULL
00261   \pre a_lines != NULL
00262   \param a_input  The input stream of tokens.
00263   \param a_lines  The line control.
00264   \return The new instance with own flexer buffer.
00265 */
00266 ptr<pp_lex> pp_lex::create(const ptr<pre_lex> &a_input, const ptr<line_control> &a_lines)
00267 {
00268         return new pp_lex(a_input,a_lines);
00269 }
00270 
00271 end_package(lex);
00272 end_package(cplus);
00273 end_package(lang);
00274 end_package(lestes);
00275 /* vim: set ft=lestes : */

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