Gaudi Framework, version v22r2

Home   Generated: Tue May 10 2011

Parser.cpp

Go to the documentation of this file.
00001 // $Id: Parser.cpp,v 1.11 2007/12/06 15:14:21 marcocle Exp $
00002 // ============================================================================
00003 #ifdef WIN32
00004 // Disable warning
00005 //   C4996: 'std::copy': Function call with parameters that may be unsafe
00006 // Probably coming from Boost classification.
00007 #pragma warning(disable:4996)
00008 #endif
00009 // ============================================================================
00010 // Include files
00011 // ============================================================================
00012 // STD & STL
00013 // ============================================================================
00014 #include <iostream>
00015 // ============================================================================
00016 // Boost
00017 // ============================================================================
00018 #include <boost/filesystem/operations.hpp>
00019 #include <boost/format.hpp>
00020 #include <boost/algorithm/string.hpp>
00021 // ============================================================================
00022 // GaudiKernel
00023 // ============================================================================
00024 #include <GaudiKernel/SystemOfUnits.h>
00025 // ============================================================================
00026 // local
00027 // ============================================================================
00028 #include "ParserUtils.h"
00029 #include "ParserGrammar.h"
00030 // ============================================================================
00031 // local namespaces:
00032 // ============================================================================
00033 namespace fs = boost::filesystem;
00034 namespace ba = boost::algorithm;
00035 // ============================================================================
00036 namespace
00037 {
00038   const std::string GPP_COMMENT = "//GP:" ;
00039 }
00040 // ============================================================================
00041 Gaudi::Parsers::Parser::Parser
00042 ( Catalogue&                catalogue ,
00043   std::vector<std::string>& included  ,
00044   std::ostream&             m         )
00045   : m_isPrint(true)
00046   , m_isPrintOptions(false)
00047   , m_catalogue(catalogue)
00048   , m_included(included)
00049   , m_stream ( m )
00050 {
00051   m_searchPath = Gaudi::Parsers::Utils::extractPath("$JOBOPTSEARCHPATH");
00052   initUnits();
00053 }
00054 // ============================================================================
00055 Gaudi::Parsers::Parser::Parser
00056 ( Catalogue&                      catalogue  ,
00057   std::vector<std::string>&       included   ,
00058   const std::vector<std::string>& searchPath ,
00059   std::ostream&                   m          )
00060   : m_isPrint(true)
00061   , m_isPrintOptions(false)
00062   , m_catalogue(catalogue)
00063   , m_included(included)
00064   , m_stream ( m )
00065 {
00066   m_searchPath = searchPath;
00067   initUnits();
00068 }
00069 // ============================================================================
00070 Gaudi::Parsers::Parser::Parser
00071 ( Catalogue&                catalogue  ,
00072   std::vector<std::string>& included   ,
00073   const std::string&        searchPath ,
00074   std::ostream&             m          )
00075   : m_isPrint(true)
00076   , m_isPrintOptions(false)
00077   , m_catalogue(catalogue)
00078   , m_included(included)
00079   , m_stream ( m )
00080 {
00081   m_searchPath = Gaudi::Parsers::Utils::extractPath(searchPath);
00082   initUnits();
00083 }
00084 // ============================================================================
00085 StatusCode Gaudi::Parsers::Parser::parse ( const std::string& fileName )
00086 {
00087   m_stream << GPP_COMMENT + std::string(80,'=') << std::endl;
00088   parseFile(fileName,Position()).ignore();
00089   resolveReferences();
00090   if ( m_isPrintOptions ){ printOptions(); }
00091   m_stream << GPP_COMMENT + std::string(80,'=') << std::endl;
00092   return errorsCount()==0?StatusCode::SUCCESS:StatusCode::FAILURE;
00093 }
00094 // ============================================================================
00095 int Gaudi::Parsers::Parser::errorsCount()
00096 {
00097         int result=0;
00098         for ( MessagesStoreT::const_iterator cur=m_messages.begin();
00099         cur!=m_messages.end() ; ++cur)
00100   { if ( cur->severity() == Message::E_ERROR){ ++result; } }
00101         return result;
00102 }
00103 // ============================================================================
00104 void Gaudi::Parsers::Parser::matchInclude
00105 (const std::string& fileName,const Position& pos)
00106 { parseFile(fileName,pos).ignore(); }
00107 // ============================================================================
00108 void Gaudi::Parsers::Parser::matchUnits
00109 (const std::string& fileName,const Position& pos)
00110 { parseFile(fileName,pos,true).ignore(); }
00111 
00112 // ============================================================================
00113 long double Gaudi::Parsers::Parser::matchUnit
00114 ( const std::string& unit,
00115   const Position& pos)
00116 {
00117   UnitsStoreT::const_iterator u = m_units.find(unit);
00118   if ( u==m_units.end())
00119   {
00120     addMessage
00121       ( Message::E_ERROR ,
00122         Message::C_UNITNOTFOUND,
00123         boost::str(boost::format("Cann't find unit \"%1%\"")%unit),pos);
00124     return 1;
00125   }
00126   return u->second;
00127 }
00128 // ============================================================================
00129 void Gaudi::Parsers::Parser::matchUnitEntry
00130 ( const std::string& newUnit ,
00131   double value,
00132   const Position& pos)
00133 {
00134   if(isPrint())
00135   {
00136     m_stream
00137       << boost::format("%4% %2%  = %3%; %|78t|%1%")
00138       % posString(pos.line(), pos.column())
00139       % newUnit
00140       % value
00141       % GPP_COMMENT
00142       << std::endl ;
00143   }
00144   m_units[newUnit] = value ;
00145 }
00146 // ============================================================================
00147 void Gaudi::Parsers::Parser::matchAssign
00148 ( const std::string& objName  ,
00149   const std::string& propName ,
00150   const Sign& oper,
00151   const std::vector<std::string>& vectorValue,
00152   const Position& pos,bool isVector)
00153 {
00154   // --------------------------------------------------------------------------
00155   if(isPrint())
00156   {
00157     m_stream
00158       << boost::format("%2% %3% %4%;%|72t|%5% %1%")
00159       % posString(pos.line(),pos.column())
00160       % (objName+"."+propName)
00161       % sign(oper)
00162       % valueToString(vectorValue , isVector)
00163       % GPP_COMMENT
00164       << std::endl ;
00165   }
00166   // --------------------------------------------------------------------------
00167   // --------------------------------------------------------------------------
00168   if (oper == S_ASSIGN)
00169   {
00170     // ------------------------------------------------------------------------
00171     PropertyEntry* assignProp;
00172     if(isVector){
00173       assignProp = new PropertyEntry(propName,vectorValue,pos);
00174     }else{
00175       assignProp = new PropertyEntry(propName,vectorValue[0],pos);
00176     }
00177     m_catalogue.addProperty(objName,*assignProp);
00178     delete assignProp;
00179     // ------------------------------------------------------------------------
00180   }
00181   else
00182   {
00183     // += or -=
00184     // ------------------------------------------------------------------------
00185     PropertyEntry foundProp;
00186     StatusCode ok;
00187     ok = m_catalogue.findProperty(objName,propName,foundProp);
00188     if (ok.isFailure())
00189     {
00190       foundProp = PropertyEntry(propName,std::vector<std::string>());
00191     }
00192     if(oper == S_PLUSASSIGN)
00193     {
00194       ok = foundProp.addValues(vectorValue);
00195       if(ok.isFailure()){
00196         addMessage
00197           ( Message::E_ERROR,
00198             Message::C_CANNOTADDTONOTVECTOR,
00199             boost::str
00200             ( boost::format
00201               ("Cannot add values to not vector property \"%1%.%2%\"")
00202               %  objName % propName),pos);
00203         return;
00204       }
00205       m_catalogue.addProperty(objName,foundProp);
00206     }
00207     // ------------------------------------------------------------------------
00208     if(oper == S_MINUSASSIGN)
00209     {
00210       int count=0;
00211       ok = foundProp.removeValues(vectorValue,count);
00212       if(ok.isFailure()){
00213         addMessage
00214           ( Message::E_ERROR,
00215             Message::C_CANNOTREMOVEFROMNOTVECTOR,
00216             boost::str
00217             ( boost::format
00218               ( "Cannot remove values from not vector property \"%1%.%2%\"" )
00219               %  objName % propName),pos);
00220         return;
00221       }
00222       // ----------------------------------------------------------------------
00223       if (count == 0)
00224       {
00225         addMessage
00226           ( Message::E_WARNING,
00227             Message::C_ZEROREMOVED,
00228             boost::str
00229             ( boost::format
00230               ( "Nothing removed from property \"%1%.%2%\"" )
00231               %  objName % propName),pos);
00232       }
00233       else
00234       {
00235         m_catalogue.addProperty(objName,foundProp);
00236       }
00237 
00238     }
00239     // ------------------------------------------------------------------------
00240   }
00241 }
00242 // ============================================================================
00243 void Gaudi::Parsers::Parser::setIsPrint
00244 ( bool on , const Gaudi::Parsers::Position& pos)
00245 {
00246   // ignore the printout if the full print is activated
00247   if ( on && m_isPrintOptions ) { return ; }
00248   m_isPrint = on;
00249   m_stream
00250     << boost::format("%3% printing is %2% %|78t|%1%")
00251     % posString(pos.line(),pos.column())
00252     % (on?"ON":"OFF")
00253     % GPP_COMMENT
00254     << std::endl ;
00255 }
00256 // ============================================================================
00257 void Gaudi::Parsers::Parser::setIsPrintOptions
00258 ( bool on , const Position& pos)
00259 {
00260   m_isPrintOptions = on;
00261   m_stream
00262     << boost::format ("%3% printing options is %2% %|78t|%1%")
00263     % posString(pos.line(),pos.column())
00264     % (on?"ON":"OFF")
00265     % GPP_COMMENT
00266     << std::endl ;
00267   // deactivate the printout if the print of all options is activated
00268   if ( m_isPrintOptions && m_isPrint ) { setIsPrint ( false , pos ) ; }
00269 }
00270 // ============================================================================
00271 void Gaudi::Parsers::Parser::initUnits()
00272 {
00273   m_units[ "mm"   ] = Gaudi::Units::mm  ;
00274   m_units[ "cm"   ] = Gaudi::Units::cm  ;
00275   m_units[ "cm2"  ] = Gaudi::Units::cm2 ;
00276   m_units[ "m"    ] = Gaudi::Units::m   ;
00277   m_units[ "m2"   ] = Gaudi::Units::m2  ;
00278   //
00279   m_units[ "ns"   ] = Gaudi::Units::nanosecond ;
00280   m_units[ "ps"   ] = Gaudi::Units::picosecond ;
00281   m_units[ "fs"   ] = Gaudi::Units::picosecond * 0.001 ;
00282   //
00283   m_units[ "MeV"  ] = Gaudi::Units::MeV ;
00284   m_units[ "GeV"  ] = Gaudi::Units::GeV ;
00285   m_units[ "keV"  ] = Gaudi::Units::keV ;
00286 }
00287 // ============================================================================
00288 StatusCode Gaudi::Parsers::Parser::parseFile
00289 ( const std::string& fileName ,
00290   const Position& pos,
00291   bool isUnitsFile)
00292 {
00293   StatusCode  ok;
00294   std::vector<std::string> sp = m_searchPath;
00295   if(pos.fileName().length()>0){
00296     // Add current file directory to search path
00297     sp.insert(sp.begin(),
00298               fs::path(pos.fileName(),fs::native).branch_path()
00299               .native_directory_string());
00300   }
00301   std::string fileToParse;
00302   ok = Gaudi::Parsers::Utils::searchFile(fileName,true,sp,fileToParse);
00303   if(ok.isFailure()){
00304     addMessage( Message::E_ERROR, Message::C_FILENOTFOUND,
00305                boost::str(boost::format("Couldn't find file \"%1%\"") % fileName),pos);
00306     return StatusCode::FAILURE;
00307   }
00308 
00309   ok = isIncluded(fileToParse);
00310   if(ok.isSuccess())
00311   {
00312     const std::string _msg =
00313       ( boost::format("Skip already included file  \"%1%\"") % fileToParse ).str() ;
00314     addMessage ( Message::E_WARNING , Message::C_OK , _msg , pos ) ;
00315     if ( isPrint() )
00316     {
00317       m_stream
00318         << boost::format("%3% skip already included file  \"%2%\" %|78t|%1%")
00319         % posString(pos.line(), pos.column())
00320         % fileToParse
00321         % GPP_COMMENT
00322         << std::endl ;
00323     }
00324     return StatusCode::SUCCESS;
00325   }
00326   std::string input;
00327   ok = Gaudi::Parsers::Utils::readFile(fileToParse,input);
00328   if(ok.isFailure())
00329   {
00330     addMessage
00331       ( Message::E_ERROR, Message::C_FILENOTOPENED,
00332        boost::str
00333        (boost::format("Couldn't open file \"%1%\"") % fileToParse),pos);
00334     return StatusCode::FAILURE;
00335   }
00336   m_included.push_back(fileToParse);
00337 
00338 
00339   IteratorT beginpos(input.begin(), input.end(), fileToParse);
00340   IteratorT endpos;
00341 
00342   boost::spirit::parse_info<IteratorT> info;
00343   SkipperGrammar grSkipper;
00344 
00345   if(!isUnitsFile){
00346     m_stream
00347       << boost::format("%3% include \"%2%\" %|78t|%1%")
00348       % posString(pos.line(), pos.column())
00349       % fileToParse
00350       % GPP_COMMENT
00351       << std::endl ;
00352     ParserGrammar grParser(this);
00353     info = boost::spirit::parse(beginpos, endpos, grParser >> end_p,grSkipper);
00354   }else{
00355     m_stream
00356       << boost::format("#units \"%3%\" %|72t|%2% %1%")
00357       % posString(pos.line(), pos.column())
00358       % GPP_COMMENT
00359       % fileToParse
00360       << std::endl ;
00361     UnitsFileGrammar grParser(this);
00362     info = boost::spirit::parse(beginpos, endpos, grParser >> end_p,grSkipper);
00363   }
00364   boost::spirit::file_position stoppos = info.stop.get_position();
00365   if (!info.full) {
00366     addMessage(Message::E_ERROR, Message::C_SYNTAXERROR,
00367                "Syntax error",Position(stoppos.file,stoppos.line,stoppos.column));
00368     return StatusCode::FAILURE;
00369   }
00370   {
00371     std::string _msg =
00372       ( boost::format("Parsed file \"%2%\" %|78t|%1%")
00373         % posString(stoppos.line, stoppos.column)
00374         % fileToParse ) .str() ;
00375     addMessage ( Message::E_VERBOSE ,
00376                  Message::C_OK ,
00377                  _msg ,
00378                  Position(stoppos.file,stoppos.line,stoppos.column) ) ;
00379     if ( isPrint() )
00380     {
00381       m_stream
00382         << boost::format("%3% end  \"%2%\" %|78t|%1%")
00383         % posString(stoppos.line, stoppos.column)
00384         % fileToParse
00385         % GPP_COMMENT
00386         << std::endl ;
00387     }
00388   }
00389   return StatusCode::SUCCESS;
00390 }
00391 // ============================================================================
00392 std::string Gaudi::Parsers::Parser::severityName
00393 (Message::Severity severity){
00394   switch(severity)
00395   {
00396   case Message::E_ERROR   :
00397     return "ERROR"     ;
00398   case Message::E_WARNING :
00399     return "WARNING"   ;
00400   case Message::E_NOTICE  :
00401     return "NOTICE"    ;
00402   case Message::E_VERBOSE :
00403     return "VERBOSE"   ;
00404   default:
00405     return "UNDEFINED" ;
00406   }
00407 }
00408 // ============================================================================
00409 void Gaudi::Parsers::Parser::addMessage
00410 ( const Message::Severity& severity ,
00411   const Message::Code&     code     ,
00412   const std::string&       message  ,
00413   const Position&          pos      )
00414 {
00415   Message result
00416     ( severity , code,
00417       boost::str(boost::format("%1%(%2%,%3%) : %4% #%5% : %6%") % pos.fileName()
00418                  % pos.line() % pos.column() % severityName(severity) % code
00419                  % message));
00420   m_messages.push_back(result);
00421 }
00422 // ============================================================================
00423 // Purpose: Implementation of Parser::isIncluded()
00424 // Comment: Test if file already included
00425 // Parameters:
00426 //  - fileName File name
00427 // Return: true if file already included
00428 // ============================================================================
00429 bool Gaudi::Parsers::Parser::isIncluded(const std::string& fileName)
00430 {
00431   for(std::vector<std::string>::const_iterator cur=m_included.begin();
00432       cur!=m_included.end();cur++)
00433   { if(fileName==*cur){ return true; } }
00434   return false;
00435 }
00436 // ============================================================================
00437 // Purpose: Implementation of Parser::resolveReferences()
00438 // Comment: Resolve references
00439 // TODO: Refactor?
00440 // ============================================================================
00441 void Gaudi::Parsers::Parser::resolveReferences()
00442 {
00443   Catalogue::CatalogueT cat = m_catalogue.catalogue();
00444   // ----------------------------------------------------------------------------
00445   for( Catalogue::CatalogueT::const_iterator curObj = cat.begin();
00446        curObj!=cat.end();curObj++)
00447   {
00448     std::string objName = curObj->first;
00449     // ------------------------------------------------------------------------
00450     for( std::vector<PropertyEntry>::const_iterator curProp =
00451            curObj->second.begin();curProp != curObj->second.end(); curProp++)
00452     {
00453       std::string value = curProp->value();
00454       if ( (value.length()>0) && (value[0]=='@'))
00455       {
00456         // --------------------------------------------------------------------
00457         std::vector<std::string> objAndProp;
00458         std::string refprop(value.begin()+1,value.end());
00459         ba::split(objAndProp,
00460                   refprop,
00461                   ba::is_any_of("."));
00462         PropertyEntry foundProperty;
00463         StatusCode ok;
00464         ok = m_catalogue.findProperty(objAndProp[0],objAndProp[1],
00465                                       foundProperty);
00466         if(ok.isFailure())
00467         {
00468           addMessage
00469             ( Message::E_ERROR,
00470               Message::C_PROPERTYNOTFOUND,
00471               boost::str(boost::format("Cannot find property \"%1%.%2%\"")
00472                          % objAndProp[0] % objAndProp[1]),curProp->position());
00473         }
00474         else
00475         {
00476           // -------------------------------------------------------------------
00477           if((ba::to_lower_copy(objAndProp[0]) == objName)
00478              &&
00479              (ba::to_lower_copy(objAndProp[1])
00480               == curProp->name()))
00481           {
00482             // ----------------------------------------------------------------
00483             addMessage
00484               ( Message::E_ERROR,
00485                 Message::C_BADREFERENCE,
00486                 boost::str(boost::format("Reference to self \"%1%.%2%\"")
00487                            % objAndProp[0] % objAndProp[1]),curProp->position());
00488             // ----------------------------------------------------------------
00489           }
00490           else
00491           {
00492             PropertyEntry property = foundProperty;
00493             property.setName(curProp->name());
00494             m_catalogue.addProperty(objName,property);
00495           }
00496           // ------------------------------------------------------------------
00497         }
00498         // --------------------------------------------------------------------
00499       }
00500     }
00501     // ------------------------------------------------------------------------
00502   }
00503 }
00504 // ============================================================================
00505 // String representation of sign
00506 // ============================================================================
00507 std::string Gaudi::Parsers::Parser::sign(Sign aSign)
00508 {
00509   switch(aSign)
00510   {
00511   case S_ASSIGN:
00512     return "=";
00513   case S_PLUSASSIGN:
00514     return "+=";
00515   case S_MINUSASSIGN:
00516     return "-=";
00517   default:
00518     return "unknown_operation";
00519   }
00520 }
00521 // ============================================================================
00522 // String representation of value vector
00523 // ============================================================================
00524 std::string Gaudi::Parsers::Parser::valueToString
00525 ( std::vector<std::string> value, bool isVector )
00526 {
00527   if ( !isVector){ return value[0]; }
00528   //
00529   std::string result;
00530   std::string delim;
00531   result+=" [ ";
00532   for ( std::vector<std::string>::const_iterator cur = value.begin();
00533         cur != value.end(); cur++ )
00534   {
00535     result += delim + *cur;
00536     delim = " , ";
00537   }
00538   return result + " ] ";
00539 }
00540 // ============================================================================
00541 // Print options
00542 // ============================================================================
00543 void Gaudi::Parsers::Parser::printOptions() { m_stream << m_catalogue ; }
00544 // ============================================================================
00545 /*  Implementation of Gaudi::Parsers::Utils::posString()
00546  *  Comment: Convert position to string
00547  *  Parameters:
00548  *    - line Line
00549  *    - column Column
00550  */
00551 // ============================================================================
00552 std::string Gaudi::Parsers::Parser::posString(int line, int column)
00553 { return boost::str(boost::format("(%1%,%2%)") % line % column); }
00554 // ============================================================================
00555 
00556 // ============================================================================
00557 // The END
00558 // ============================================================================
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines

Generated at Tue May 10 2011 18:54:03 for Gaudi Framework, version v22r2 by Doxygen version 1.7.2 written by Dimitri van Heesch, © 1997-2004