Main Page   Namespace List   Class Hierarchy   Compound List   File List   Namespace Members   Compound Members  

pattern_based_code_generator.cc

00001 /*
00002 *  Name:      pattern_based_code_generator.cc
00003 *  Author:    Rafael Jesus Alcantara Perez
00004 *  Summary:   Pattern based code generator       
00005 *  Date:      $Date: 2003/04/14 00:18:35 $
00006 *  Revision:  $Revision: 1.1 $
00007 *
00008 *  Copyright (C) 1994-2002  Rafael Jesus Alcantara Perez <rafa@dedalo-ing.com>
00009 *
00010 *  This program is free software; you can redistribute it and/or modify
00011 *  it under the terms of the GNU General Public License as published by
00012 *  the Free Software Foundation; either version 2 of the License, or
00013 *  (at your option) any later version.
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 *  You should have received a copy of the GNU General Public License
00021 *  along with this program; if not, write to the Free Software
00022 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
00023 *  MA 02111-1307, USA.
00024 */
00025 
00026 #include <fstream>
00027 #include <mpcl/system/all.hh>
00028 #include <mpcl/text/codegen/pattern_based_code_generator.hh>
00029 #include <mpcl/text/regex/matcher.hh>
00030 
00031 
00032 //
00033 //  C O N S T R U C T O R S
00034 //
00035 
00036 mpcl::text::codegen::TPatternBasedCodeGenerator::
00037 TPatternBasedCodeGenerator ( const TString& rkySOURCE_CDML_FILE ,
00038                              const TString& rkyCDML_PATH        ) :
00039   IStreamable<>      ()                                           ,
00040   tInstructionMap    ()                                           ,
00041   tVariableMap       ()                                           ,
00042   yCdmlPath          (rkyCDML_PATH)                               ,
00043   yDescription       ()                                           ,
00044   yInherit           ()                                           ,
00045   yPublic            ()                                           ,
00046   ySystem            ()                                           ,
00047   yTarget            ()
00048 {
00049 
00050   initConstants();
00051   loadFrom (rkySOURCE_CDML_FILE);
00052 
00053 }  // TPatternBasedCodeGenerator()
00054 
00055 
00056 void mpcl::text::codegen::TPatternBasedCodeGenerator::
00057 clear (void)
00058 {
00059   
00060   tInstructionMap.clear();
00061   yTarget.erase();
00062   yInherit.erase();
00063   yDescription.erase();
00064   yCdmlPath.erase();
00065 
00066 }  // clear()
00067 
00068 
00069 void mpcl::text::codegen::TPatternBasedCodeGenerator::
00070 clearCode (void)
00071 {
00072 
00073   TInstructionMap::iterator                      tInstructionIter;
00074   TInstructionBody::TClauseMap::iterator         tClauseIter;
00075   TInstructionBody::TClauseMap::const_iterator   ktClauseEnd;
00076   
00077   tInstructionIter = tInstructionMap.begin();
00078   for (; ( tInstructionIter != tInstructionMap.end() ) ;++tInstructionIter)
00079   {
00080     tClauseIter = tInstructionIter->second.tClauseMap.begin();
00081     ktClauseEnd = tInstructionIter->second.tClauseMap.end();
00082     for (; ( tClauseIter != ktClauseEnd ) ;++tClauseIter)
00083     {
00084       tClauseIter->second.erase();
00085     }
00086   }
00087 
00088 }  // clearCode()
00089 
00090 
00091 void mpcl::text::codegen::TPatternBasedCodeGenerator::
00092 loadFrom (const TString& rkySOURCE_CDML_FILE)
00093 {
00094 
00095   using mpcl::system::tSystem;
00096   using std::basic_ifstream;
00097   using std::vector;
00098   
00099   basic_ifstream<char>   tCdmlIfstream;
00100   TString                yCdmlFileName;
00101   bool                   gSuccess = false;
00102 
00103   //
00104   //  If there is CDML path and it  can't open the file,  then it tries to load
00105   //  the file from the directories in the CDML path.
00106   //
00107   tCdmlIfstream.open (rkySOURCE_CDML_FILE.c_str());
00108   if ( !tCdmlIfstream.is_open() && !yCdmlPath.empty() )
00109   {
00110     //
00111     //  There are some path items to test.
00112     //
00113     vector<TString>                   tPathVector = tSystem.getPathItems (yCdmlPath);
00114     vector<TString>::const_iterator   I           = tPathVector.begin();
00115 
00116     yCdmlFileName  = tSystem.getDirectorySeparator();
00117     yCdmlFileName += rkySOURCE_CDML_FILE;
00118     for (; ( I != tPathVector.end() ) ;++I)
00119     {
00120       tCdmlIfstream.clear();
00121       tCdmlIfstream.open ((*I + yCdmlFileName).c_str());
00122       if ( tCdmlIfstream.is_open() )
00123       {
00124         break;
00125       }
00126     }
00127   }
00128   if ( tCdmlIfstream.is_open() )
00129   {
00130     //
00131     //  Loads CDML file into code-generator.
00132     //
00133     gSuccess = true;
00134     read (tCdmlIfstream);
00135     tCdmlIfstream.close();
00136   }
00137   if ( !gSuccess )
00138   {
00139     TString   yMessage = Format ("couldn't open file '%s'", rkySOURCE_CDML_FILE.c_str());
00140 
00141     throw TFileNotFoundException (yMessage, __FILE__, __LINE__);
00142   }
00143 
00144 }  // loadFrom()
00145 
00146 
00147 void mpcl::text::codegen::TPatternBasedCodeGenerator::
00148 compile (void)
00149 {
00150 
00151   size_t   zOffset;
00152 
00153   //
00154   //  There is no inheritance from here towards.
00155   //
00156   yInherit.erase();
00157 
00158   //
00159   //  Preprocess source variables (normal and file types).
00160   //
00161   {
00162     TStringToVariableMap::iterator         I             = tVariableMap.begin();
00163     TStringToVariableMap::const_iterator   ktVariableEnd = tVariableMap.end();
00164     
00165     for (; ( I != ktVariableEnd ) ;++I)
00166     {
00167       zOffset = I->second.find (pkcEOC_EntityPattern);
00168       if ( TString::npos != zOffset )
00169       {
00170         I->second.erase (zOffset);
00171       }
00172     }
00173   }
00174   
00175   //
00176   //  Preprocess clause-body-strings.
00177   //
00178   {
00179     TInstructionMap::iterator                      I;
00180     TInstructionMap::const_iterator                ktInstructionEnd;
00181     TInstructionBody::TClauseMap::iterator         J;
00182     TInstructionBody::TClauseMap::const_iterator   ktClauseEnd;
00183     
00184     I                = tInstructionMap.begin();
00185     ktInstructionEnd = tInstructionMap.end();
00186     for (; ( I != ktInstructionEnd ) ;++I)
00187     {
00188       J           = I->second.tClauseMap.begin();
00189       ktClauseEnd = I->second.tClauseMap.end();
00190       for (; ( J != ktClauseEnd ) ;++J)
00191       {
00192         zOffset = J->second.find (pkcEOC_EntityPattern);
00193         if ( TString::npos != zOffset )
00194         {
00195           J->second.erase (zOffset);
00196         }
00197       }
00198     }
00199   }
00200 
00201 }  // compile()
00202 
00203 
00204 void mpcl::text::codegen::TPatternBasedCodeGenerator::
00205 preprocessVariables (void)
00206 {
00207 
00208   TStringToVariableMap::iterator         I             = tVariableMap.begin();
00209   TStringToVariableMap::const_iterator   ktVariableEnd = tVariableMap.end();
00210   
00211   for (; ( I != ktVariableEnd ) ;++I)
00212   {
00213     InstantiateEntities (I->second);
00214   }
00215   
00216 }  // preprocessVariables()
00217 
00218 
00219 void mpcl::text::codegen::TPatternBasedCodeGenerator::
00220 setDescription (const char* pkcSOURCE_DESCRIPTION)
00221 {
00222 
00223   yDescription = pkcSOURCE_DESCRIPTION;
00224 
00225 }  // setDescription()
00226 
00227 
00228 void mpcl::text::codegen::TPatternBasedCodeGenerator::
00229 setCdmlPath (const TString& rkyCDML_PATH)
00230 {
00231 
00232   yCdmlPath = rkyCDML_PATH;
00233 
00234 }  // setCdmlPath()
00235 
00236 
00237 void mpcl::text::codegen::TPatternBasedCodeGenerator::
00238 initConstants (void) const
00239 {
00240 
00241   using std::strlen;
00242 
00243   //
00244   //  Due to a bug in GNU-C version <= 2.7.2.3.
00245   //
00246   if ( !zEntityPrefixLength )
00247   {
00248     zEntityPrefixLength      = strlen (pkcEntityPrefix);
00249     zGT_EntityPatternLength  = strlen (pkcGT_EntityPattern);
00250     zGT_EntityValueLength    = strlen (pkcGT_EntityValue);
00251     zLT_EntityPatternLength  = strlen (pkcLT_EntityPattern);
00252     zLT_EntityValueLength    = strlen (pkcLT_EntityValue);
00253     zNL_EntityPatternLength  = strlen (pkcNL_EntityPattern);
00254     zNL_EntityValueLength    = strlen (pkcNL_EntityValue);
00255     zEOC_EntityPatternLength = strlen (pkcEOC_EntityPattern);
00256     zAMP_EntityPatternLength = strlen (pkcAMP_EntityPattern);
00257     zAMP_EntityValueLength   = strlen (pkcAMP_EntityValue);
00258   }
00259 
00260 }  // initConstants()
00261 
00262 
00263 void mpcl::text::codegen::TPatternBasedCodeGenerator::
00264 inheritFrom (const TString& rkySOURCE_CDML_FILE)
00265 {
00266 
00267   //
00268   //  The only attribute that must persists is
00269   //  string yTarget.
00270   //
00271 
00272   TString   yOldTarget  = yTarget;
00273   TString   yOldInherit = yInherit;
00274   
00275   loadFrom (rkySOURCE_CDML_FILE);
00276   yTarget  = yOldTarget;
00277   yInherit = yOldInherit;
00278 
00279 }  // inheritFrom()
00280 
00281 
00282 void mpcl::text::codegen::TPatternBasedCodeGenerator::
00283 read (std::basic_istream<char_type, traits_type>& rtSOURCE_ISTREAM)
00284 {
00285 
00286 # define PBCG_REMOVE_COMMENTS                                    \
00287          {                                                       \
00288            while ( tMatcher.scan (pkcCommentTagPattern, NULL) ); \
00289          }
00290 
00291   using text::regex::TMatcher;
00292 
00293   //
00294   //  CDML document must be validated, so parsing
00295   //  doesn't have to worry about syntax errors.
00296   //  First it musts find CDML tag, and then skip
00297   //  it.
00298   //
00299 
00300   //
00301   //  If gUpdateOnly is false, then it's loading a root CDML file (maybe,
00302   //  it is an only-one-node tree). Else, it is updating the inner nodes.
00303   //
00304   bool       gUpdateOnly = false;
00305   TMatcher   tMatcher (rtSOURCE_ISTREAM);
00306 
00307   yPublic.erase();
00308   ySystem.erase();
00309   yTarget.erase();
00310   yInherit.erase();
00311   tInstructionMap.clear();  
00312   tMatcher.setCaseSensitiveness (false);
00313   PBCG_REMOVE_COMMENTS;
00314 
00315   //
00316   //  !DOCTYPE tag.
00317   //
00318   if ( !tMatcher.scan (pkcDOCTYPE_TagPattern_1, NULL) )
00319   {
00320     if ( !tMatcher.scan (pkcDOCTYPE_TagPattern_2, NULL) )
00321     {
00322       if ( !tMatcher.scan (pkcDOCTYPE_TagPattern_3, &ySystem, NULL) )
00323       {
00324         tMatcher.scan (pkcDOCTYPE_TagPattern_4, &yPublic, NULL);
00325       }
00326     }
00327   }
00328   PBCG_REMOVE_COMMENTS;
00329   
00330   //
00331   //  CDML tag.
00332   //
00333   if ( !tMatcher.scan (pkcCDML_TagPattern_1, &yTarget, NULL) )
00334   {
00335     if ( !tMatcher.scan (pkcCDML_TagPattern_2, &yTarget, &yInherit, NULL) )
00336     {
00337       if ( !tMatcher.scan (pkcCDML_TagPattern_3, &yInherit, &yTarget, NULL) )
00338       {
00339         throw TNotCdmlFileException ("file doesn't conform CDML", __FILE__, __LINE__);
00340       }
00341     }
00342 
00343     //
00344     //  First, it loads base CDMLs, and then loads this instance, overloading base
00345     //  instruction/clause pairs.
00346     //
00347     inheritFrom (yInherit + ".cdml");
00348     gUpdateOnly = true;
00349   }
00350   PBCG_REMOVE_COMMENTS;
00351   
00352   //
00353   //  Reads DESC tag/DESC body/DESC end-tag.
00354   //
00355   tMatcher.scan (pkcDESC_ElementPattern, &yDescription, NULL);
00356   PBCG_REMOVE_COMMENTS;
00357   
00358   //
00359   //  Reads DECLARE tag/DECLARE end-tag.
00360   //
00361   if ( tMatcher.scan (pkcDECLARE_TagPattern, NULL) > 0 )
00362   {
00363     TString   yName;
00364     TString   yValue;
00365     TString   yType;
00366     bool      gFound;
00367 
00368     if ( !gUpdateOnly )
00369     {
00370       do
00371       {
00372         //
00373         //  It removes  comments  and then,  scans  for  only one of the  three
00374         //  possible patterns.
00375         //
00376         PBCG_REMOVE_COMMENTS;
00377         gFound = ( tMatcher.scan (pkcVARIABLE_ElementPattern_1, &yName, &yValue, NULL) > 0 );
00378         if ( !gFound )
00379         {
00380           gFound = ( tMatcher.scan (pkcVARIABLE_ElementPattern_2, &yName, &yType, &yValue, NULL) > 0 );
00381         }
00382         if ( !gFound )
00383         {
00384           gFound = ( tMatcher.scan (pkcVARIABLE_ElementPattern_3, &yType, &yName, &yValue, NULL) > 0 );
00385         }
00386         if ( gFound )
00387         {
00388           yType.uppercase();
00389           if ( yType == "FILE" )
00390           {
00391             tVariableMap.bind (yName, TVariableString (yValue, TVariableString::eFile));
00392           }
00393           else if ( yType == "OPTIONAL" )
00394           {
00395             tVariableMap.bind (yName, TVariableString (yValue, TVariableString::eOptional));
00396           }
00397           else
00398           {
00399             tVariableMap.bind (yName, TVariableString (yValue));
00400           }
00401           yName.erase();
00402           yValue.erase();
00403           yType.erase();
00404           PBCG_REMOVE_COMMENTS;
00405         }
00406       } while ( gFound );
00407     }
00408     else
00409     {
00410       do
00411       {
00412         //
00413         //  It removes  comments  and then,  scans  for  only one of the  three
00414         //  possible patterns.
00415         //
00416         PBCG_REMOVE_COMMENTS;
00417         gFound = ( tMatcher.scan (pkcVARIABLE_ElementPattern_1, &yName, &yValue, NULL) > 0 );
00418         if ( !gFound )
00419         {
00420           gFound = ( tMatcher.scan (pkcVARIABLE_ElementPattern_2, &yName, &yType, &yValue, NULL) > 0 );
00421         }
00422         if ( !gFound )
00423         {
00424           gFound = ( tMatcher.scan (pkcVARIABLE_ElementPattern_3, &yType, &yName, &yValue, NULL) > 0 );
00425         }
00426         if ( gFound )
00427         {
00428           yType.uppercase();
00429           if ( yType == "FILE" )
00430           {
00431             //
00432             //  Insert or update new value.
00433             //
00434             if ( tVariableMap.end() == tVariableMap.find (yName) )
00435             {
00436               //
00437               //  If variable type was not eFile, then now it musts throw
00438               //  an exception here.
00439               //
00440               tVariableMap.bind (yName, TVariableString (yValue, TVariableString::eFile));
00441             }
00442             else
00443             {
00444               if ( tVariableMap [yName].type() == TVariableString::eFile )
00445               {
00446                 tVariableMap [yName] = yValue;
00447               }
00448               else
00449               {
00450                 TString   yMessage = Format ( "variable '%s' already has another type" ,
00451                                               yName.c_str()                            );
00452 
00453                 throw TBadInstantiateSyntaxException (yMessage, __FILE__, __LINE__);
00454               }
00455             }
00456           }
00457           else if ( yType == "OPTIONAL" )
00458           {
00459             //
00460             //  Insert or update new value.
00461             //
00462             if ( tVariableMap.end() == tVariableMap.find (yName) )   
00463             {
00464               //
00465               //  If variable type was not eFile, then now it musts throw
00466               //  an exception here.
00467               //
00468               tVariableMap.bind (yName, TVariableString (yValue, TVariableString::eOptional));
00469             }
00470             else
00471             {
00472               if ( tVariableMap [yName].type() == TVariableString::eOptional )
00473               {
00474                 tVariableMap [yName] = yValue;
00475               }
00476               else
00477               {
00478                 TString   yMessage = Format ( "variable '%s' already has another type" ,
00479                                               yName.c_str()                            );
00480 
00481                 throw TBadInstantiateSyntaxException (yMessage, __FILE__, __LINE__);
00482               }
00483             }
00484           }
00485           else
00486           {
00487             //
00488             //  Insert or update new value.
00489             //
00490             if ( tVariableMap.end() == tVariableMap.find (yName) )
00491             {
00492               tVariableMap.bind (yName, TVariableString (yValue));
00493             }
00494             else
00495             {                               
00496               if ( tVariableMap [yName].type() == TVariableString::eNormal )
00497               {
00498                 tVariableMap [yName] = yValue;
00499               }
00500               else
00501               {
00502                 TString   yMessage = Format ( "variable '%s' already has another type" ,
00503                                               yName.c_str()                            );
00504 
00505                 throw TBadInstantiateSyntaxException (yMessage, __FILE__, __LINE__);
00506               }
00507             }
00508           }
00509           yName.erase();
00510           yValue.erase();
00511           yType.erase();
00512           PBCG_REMOVE_COMMENTS;
00513         }
00514       } while ( gFound );
00515     }
00516     tMatcher.scan (pkcDECLARE_EndTagPattern, NULL);
00517     PBCG_REMOVE_COMMENTS;
00518   }
00519   
00520   //
00521   //  Read CDML instructions.
00522   //
00523   if ( !gUpdateOnly )
00524   {
00525     //
00526     //  This is a leaf node of the inheritance tree.
00527     //
00528     rtSOURCE_ISTREAM >> tInstructionMap;
00529   }
00530   else
00531   {
00532     //
00533     //  This is an internal or root node of the inheritance tree.
00534     //
00535 
00536     TInstructionMap::const_iterator   I;
00537     TInstructionMap::const_iterator   ktSourceInstructionEnd;
00538     TInstructionMap                   tSourceInstructionMap;
00539 
00540     //
00541     //  Loads the parent CDML instructions into a local instruction map.
00542     //
00543     rtSOURCE_ISTREAM >> tSourceInstructionMap;
00544 
00545     //
00546     //  Iterates over all instructions and their clauses.
00547     //
00548     I                      = tSourceInstructionMap.begin();
00549     ktSourceInstructionEnd = tSourceInstructionMap.end();
00550     for (; ( I != ktSourceInstructionEnd ) ;++I)
00551     {
00553       TInstructionBody::TClauseMap::const_iterator   J;
00554 
00556       TInstructionBody::TClauseMap::iterator   K;
00557 
00559       TInstructionBody::TClauseMap::const_iterator   ktSourceClauseEnd;
00560       
00562       TInstructionBody::TClauseMap&
00563         rtTargetClauseMap = tInstructionMap [I->first].tClauseMap;
00564 
00565       //
00566       //  Initializes iterators.
00567       //
00568       J                 = I->second.tClauseMap.begin();
00569       ktSourceClauseEnd = I->second.tClauseMap.end();
00570       for (; ( J != ktSourceClauseEnd ) ;++J)
00571       {
00572         const TClauseTagString&   rktSourceClauseTag = J->first;
00573 
00574         if ( !rktSourceClauseTag.hasTarget() )
00575         {
00576           //
00577           //  Warning: Key must be bound.
00578           //
00579           //  It musts substitute the key in target map, so it musts
00580           //  remove first the value and insert the modified value again.
00581           //
00582 
00583           TClauseTagString    yTargetClauseTag;
00584           TClauseBodyString   yTargetClauseBody;
00585           
00586           K = rtTargetClauseMap.find (rktSourceClauseTag);
00587           if ( K == rtTargetClauseMap.end() )
00588           {
00589             TString   yMessage =
00590                         Format ( "clause '%s' in instruction '%s' is not defined in parent CDMLs" ,
00591                                  rktSourceClauseTag.c_str()                                       ,
00592                                  I->first.c_str()                                                 );
00593             
00594             throw TBadInstantiateSyntaxException (yMessage, __FILE__, __LINE__);
00595           }
00596           
00597           //
00598           //  There is a previous target clause defined with that tag.
00599           //
00600           yTargetClauseTag  = K->first;
00601           yTargetClauseBody = K->second;
00602           rtTargetClauseMap.erase (K);
00603           yTargetClauseTag.overloadFrom (rktSourceClauseTag);
00604           yTargetClauseBody = J->second;
00605           rtTargetClauseMap.bind (yTargetClauseTag, yTargetClauseBody);
00606         }
00607         else
00608         {
00609           K = rtTargetClauseMap.find (rktSourceClauseTag);
00610           if ( K == rtTargetClauseMap.end() )
00611           {
00612             //
00613             //  Insert clause-tag string value.
00614             //
00615             rtTargetClauseMap.bind (rktSourceClauseTag, J->second);
00616           }
00617           else
00618           {
00619             //
00620             //  Copy clause-tag string value.
00621             //
00622             //  It musts substitute the key in target map, so it musts
00623             //  remove first the value and insert the modified value again.
00624             //
00625 
00626             TClauseTagString    yTargetClauseTag  = K->first;
00627             TClauseBodyString   yTargetClauseBody = K->second;
00628           
00629             rtTargetClauseMap.erase (K);
00630             yTargetClauseTag.overloadFrom (rktSourceClauseTag);
00631             rtTargetClauseMap.bind (yTargetClauseTag, yTargetClauseBody);
00632           }
00633         }
00634       }
00635     }
00636   }
00637   PBCG_REMOVE_COMMENTS;
00638 
00639   //
00640   //  CDML end-tag.
00641   //
00642   tMatcher.scan (pkcCDML_EndTagPattern, NULL);
00643   PBCG_REMOVE_COMMENTS;
00644 
00645 # undef PBCG_REMOVE_COMMENTS
00646 
00647 }  // read()
00648 
00649 
00650 //
00651 //  S E L E C T O R S
00652 //
00653 
00654 const mpcl::text::codegen::TStringToVariableMap& mpcl::text::codegen::TPatternBasedCodeGenerator::
00655 variables (void) const
00656 {
00657 
00658   return tVariableMap;
00659 
00660 }  // variables()
00661 
00662 
00663 const mpcl::text::codegen::TClauseBodyString& mpcl::text::codegen::TPatternBasedCodeGenerator::
00664 codePatternFor ( const char* pkcINSTRUCTION_NAME ,
00665                  const char* pkcCLAUSE_NAME      ) const
00666 {
00667 
00668   TInstructionMap::const_iterator   ktIter = tInstructionMap.find (pkcINSTRUCTION_NAME);
00669 
00670   if ( ktIter == tInstructionMap.end() )
00671   {
00672     TString   yMessage;
00673     
00674     yMessage = Format ("instruction '%s' not found", pkcINSTRUCTION_NAME);
00675     throw TNotFoundException (yMessage, __FILE__, __LINE__);
00676   }
00677   return ktIter->second.clauseBody (pkcCLAUSE_NAME);
00678 
00679 }  // codePatternFor()
00680 
00681 
00682 mpcl::text::codegen::TInstructionBody& mpcl::text::codegen::TPatternBasedCodeGenerator::
00683 instruction (const char* pkcINSTRUCTION_NAME)
00684 {
00685 
00686   TInstructionMap::iterator   tIter = tInstructionMap.find (pkcINSTRUCTION_NAME);
00687 
00688   if ( tIter == tInstructionMap.end() )
00689   {
00690     TString   yMessage;
00691     
00692     yMessage = Format ("instruction '%s' not found", pkcINSTRUCTION_NAME);
00693     throw TNotFoundException (yMessage, __FILE__, __LINE__);
00694   }
00695   return tIter->second;
00696 
00697 }  // instruction()
00698 
00699 
00700 const mpcl::text::codegen::TInstructionBody& mpcl::text::codegen::TPatternBasedCodeGenerator::
00701 instruction (const char* pkcINSTRUCTION_NAME) const
00702 {
00703 
00704   TInstructionMap::const_iterator   ktIter = tInstructionMap.find (pkcINSTRUCTION_NAME);
00705 
00706   if ( ktIter == tInstructionMap.end() )
00707   {
00708     TString   yMessage;
00709     
00710     yMessage = Format ("instruction '%s' not found", pkcINSTRUCTION_NAME);
00711     throw TNotFoundException (yMessage, __FILE__, __LINE__);
00712   }
00713   return ktIter->second;
00714 
00715 }  // instruction()
00716 
00717 
00718 bool mpcl::text::codegen::TPatternBasedCodeGenerator::
00719 existsClause (const char* pkcINSTRUCTION_NAME, const char* pkcCLAUSE_NAME) const
00720 {
00721 
00722   bool                              gSuccess = false;
00723   TInstructionMap::const_iterator   tIter    = tInstructionMap.find (pkcINSTRUCTION_NAME);
00724 
00725   if ( tInstructionMap.end() != tIter )
00726   {
00727     gSuccess = tIter->second.existsClause (pkcCLAUSE_NAME);
00728   }
00729   return gSuccess;
00730 
00731 }  // existsClause()
00732 
00733 
00734 void mpcl::text::codegen::TPatternBasedCodeGenerator::
00735 write (std::basic_ostream<char_type, traits_type>& rtTARGET_OSTREAM) const
00736 {
00737 
00738   rtTARGET_OSTREAM << "<!doctype cdml";
00739   if ( !yPublic.empty() )
00740   {
00741     rtTARGET_OSTREAM << " public \"" << yPublic << "\"";
00742   }
00743   else if ( !ySystem.empty() )
00744   {
00745     rtTARGET_OSTREAM << " system \"" << ySystem << "\"";
00746   }
00747   rtTARGET_OSTREAM << ">\n<cdml target=\"" << yTarget << "\"";
00748   if ( !yInherit.empty() )
00749   {
00750     rtTARGET_OSTREAM << " inherit=\"" << yInherit << '"';
00751   }
00752   rtTARGET_OSTREAM << ">\n";
00753   if ( !yDescription.empty() )
00754   {
00755     rtTARGET_OSTREAM << "<desc>\n" << yDescription << "\n</desc>\n";
00756   }
00757   if ( !tVariableMap.empty() )
00758   {
00759     TStringToVariableMap::const_iterator   ktIter = tVariableMap.begin();
00760     TStringToVariableMap::const_iterator   ktEnd  = tVariableMap.end();
00761     
00762     rtTARGET_OSTREAM << "<declare>\n";
00763     for (; ( ktIter != ktEnd ) ;++ktIter)
00764     {
00765       rtTARGET_OSTREAM << "<variable name=\"" << ktIter->first << "\"";
00766       switch (ktIter->second.type())
00767       {
00768         case TVariableString::eNormal:
00769         {
00770           rtTARGET_OSTREAM << " type=normal";
00771           break;
00772         }
00773         case TVariableString::eFile:
00774         {
00775           rtTARGET_OSTREAM << " type=file";
00776           break;
00777         }
00778         case TVariableString::eOptional:
00779         {
00780           rtTARGET_OSTREAM << " type=optional";
00781           break;
00782         }
00783       }
00784       rtTARGET_OSTREAM << ">" << ktIter->second << "</variable>\n";
00785     }
00786     rtTARGET_OSTREAM << "</declare>\n";
00787   }
00788   rtTARGET_OSTREAM << tInstructionMap;
00789   rtTARGET_OSTREAM << "</cdml>\n";
00790 
00791 }  // write()

Generated on Mon Oct 13 02:35:23 2003 for MPCL by doxygen1.2.18