condition_stack.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 Conditional directives stack.
00030 
00031   Declaration of conditions class representing conditonal directives stack.
00032   \author pt
00033 */
00034 #include <lestes/common.hh>
00035 #include <lestes/lang/cplus/lex/condition_stack.hh>
00036 #include <lestes/lang/cplus/lex/condition_stack.m.hh>
00037 #include <lestes/lang/cplus/lex/condition.hh>
00038 #include <lestes/std/source_location.hh>
00039 
00040 package(lestes);
00041 package(lang);
00042 package(cplus);
00043 package(lex);
00044 
00045 /*!
00046   Creates empty condition stack.
00047   \post active == true
00048 */
00049 condition_stack::condition_stack(void):
00050         active(true),
00051         cstack(cstack_type::create())
00052 {
00053         cstack->push_back(condition::create_empty());
00054 }
00055         
00056 /*!
00057   Tests if the output is active.
00058   \return true  If tokens shall be output for the current condition.
00059 */
00060 bool condition_stack::active_get(void) const
00061 {
00062         return active;
00063 }
00064 
00065 /*!
00066   Processes conditional directive, issues any error messages.
00067   \pre a_location != NULL
00068   \param a_dir  The directive to process 
00069   \param value  The value of the condition for if-like directives.
00070   \param a_location  The location of the directive.
00071   \return true  If the directive is correct in the current context.
00072 */
00073 bool condition_stack::process(directive_type a_dir, bool value, const ptr<source_location> &a_location)
00074 {
00075         lassert(a_location);
00076 
00077         condition::type_type cond = condition::COND_EMPTY;
00078         ptr<condition> curr = cstack->back();
00079         condition::type_type curr_type = curr->type_get();
00080         bool curr_waiting = true;
00081         
00082         switch (a_dir) {
00083                 case DIR_IFNDEF:
00084                         cond = condition::COND_IFNDEF;
00085                         break;
00086                 case DIR_IF:
00087                         cond = condition::COND_IF;
00088                         break;
00089                 case DIR_IFDEF:
00090                         cond = condition::COND_IFDEF;
00091                         break;
00092                 case DIR_ELIF:
00093                         switch (curr_type) {
00094                                 case condition::COND_EMPTY:
00095                                         report << elif_without_if << a_location;
00096                                         return false;
00097                                 case condition::COND_ELSE:
00098                                         report << elif_after_else << a_location;
00099                                         report << conditional_starts_here << curr->location_get();
00100                                         return false;
00101                                 default:
00102                                         break;
00103                         }
00104                         curr_waiting = curr->waiting_get();
00105                         cond = condition::COND_ELIF;
00106                         break;
00107                 case DIR_ELSE:
00108                         switch (curr_type) {
00109                                 case condition::COND_EMPTY:
00110                                         report << else_without_if << a_location;
00111                                         return false;
00112                                 case condition::COND_ELSE:
00113                                         report << else_after_else << a_location;
00114                                         report << conditional_starts_here << curr->location_get();
00115                                         return false;
00116                                 default:
00117                                         break;
00118                         }
00119                         // implicitly fulfilled condition
00120                         value = true;
00121                         curr_waiting = curr->waiting_get();
00122                         cond = condition::COND_ELSE;
00123                         break;
00124                 case DIR_ENDIF:
00125                         if (curr_type == condition::COND_EMPTY) {
00126                                 report << endif_without_if << a_location;
00127                                 return false;
00128                         }
00129                         break;
00130                 case DIR_EOF:
00131                         if (curr_type != condition::COND_EMPTY) {
00132                                 report << unterminated_conditional << curr->name_get() << curr->location_get();
00133                                 return false;
00134                         }
00135                         break;
00136                 default:
00137                         lassert2(false,"You should never get here");
00138                         break;
00139         }
00140         
00141         // active = curr_active && value
00142         switch (a_dir) {
00143                 case DIR_ELSE:
00144                 case DIR_ELIF:
00145                         {
00146                                 // remove old condition on the same level
00147                                 cstack->pop_back();
00148                                 bool curr_active = curr->active_get();
00149 
00150                                 // new waiting = curr_active && curr_waiting && !value
00151                                 // keep the original location
00152                                 cstack->push_back(
00153                                                 condition::create(cond,curr_active && curr_waiting && !value,curr_active,curr->location_get()));
00154                                 active = curr_active && curr_waiting && value;
00155                         }
00156                         break;
00157                 case DIR_IFNDEF:
00158                 case DIR_IF:
00159                 case DIR_IFDEF:
00160                         // new waiting = active && curr_waiting && !value
00161                         cstack->push_back(condition::create(cond,active && curr_waiting && !value,active,a_location));
00162                         active = active && curr_waiting && value;
00163                         break;
00164                 case DIR_ENDIF:
00165                         // restore active value
00166                         active = curr->active_get();
00167                         // remove the old condition
00168                         cstack->pop_back();
00169                         break;
00170                 case DIR_EOF:
00171                         // do nothing
00172                         break;
00173                 default:
00174                         lassert2(false,"You should never get here");
00175                         break;
00176         }
00177 
00178         return true;
00179 }
00180 
00181 /*!
00182   Returns depth of the condition stack.
00183   \return The number of nested conditions.
00184 */
00185 ulint condition_stack::depth(void) const
00186 {
00187         // subtract the padding
00188         return cstack->size() - 1;
00189 }
00190 
00191 /*!
00192   Marks the object.
00193 */
00194 void condition_stack::gc_mark(void)
00195 {
00196         cstack.gc_mark();
00197 	::lestes::std::object::gc_mark();
00198 }
00199 
00200 /*!
00201   Returns empty condition stack.
00202   \return An empty condition stack.
00203 */
00204 ptr<condition_stack> condition_stack::create(void)
00205 {
00206         return new condition_stack();
00207 }
00208 
00209 end_package(lex);
00210 end_package(cplus);
00211 end_package(lang);
00212 end_package(lestes);
00213 
00214 /* vim: set ft=lestes : */

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