/search.css" rel="stylesheet" type="text/css"/> /search.js">
00001 // $Id: Parser.cpp,v 1.11 2007/12/06 15:14:21 marcocle Exp $ 00002 // ============================================================================ 00003 // Include files 00004 // ============================================================================ 00005 // STD & STL 00006 // ============================================================================ 00007 #include <iostream> 00008 // ============================================================================ 00009 // Boost 00010 // ============================================================================ 00011 #include <boost/format.hpp> 00012 #include <boost/algorithm/string.hpp> 00013 // ============================================================================ 00014 // local 00015 // ============================================================================ 00016 #include "ParserUtils.h" 00017 #include "ParserGrammar.h" 00018 // ============================================================================ 00019 // local namespaces: 00020 // ============================================================================ 00021 namespace ba = boost::algorithm; 00022 // ============================================================================ 00023 namespace 00024 { 00025 const std::string GPP_COMMENT = "//GP:" ; 00026 } 00027 // ============================================================================ 00028 Gaudi::Parsers::Parser::Parser 00029 ( Catalogue& catalogue , 00030 std::vector<std::string>& included , 00031 std::ostream& m ) 00032 : m_isPrint(false) 00033 , m_isPrintOptions(true) 00034 , m_catalogue(catalogue) 00035 , m_included(included) 00036 , m_stream ( m ) 00037 { 00038 } 00039 // ============================================================================ 00040 bool Gaudi::Parsers::Parser::parse ( const std::string& fileName ) 00041 { 00042 //m_stream << GPP_COMMENT + std::string(80,'=') << std::endl; 00043 bool sc = parseFile(fileName,Position()); 00044 resolveReferences(); 00045 if ( sc && m_isPrintOptions ){ 00046 m_stream << m_catalogue; 00047 m_stream << "// " << std::string(82,'=') << std::endl; 00048 } 00049 return errorsCount()==0?true:false; 00050 } 00051 // ============================================================================ 00052 int Gaudi::Parsers::Parser::errorsCount() 00053 { 00054 int result=0; 00055 for ( MessagesStoreT::const_iterator cur=m_messages.begin(); 00056 cur!=m_messages.end() ; ++cur) 00057 { if ( cur->severity() == Message::E_ERROR){ ++result; } } 00058 return result; 00059 } 00060 // ============================================================================ 00061 void Gaudi::Parsers::Parser::matchInclude 00062 (const std::string& fileName,const Position& pos) 00063 { parseFile(fileName,pos); } 00064 // ============================================================================ 00065 void Gaudi::Parsers::Parser::matchAssign 00066 ( const std::string& objName , 00067 const std::string& propName , 00068 const Sign& oper, 00069 const std::vector<std::string>& vectorValue, 00070 const Position& pos,bool isVector) 00071 { 00072 // -------------------------------------------------------------------------- 00073 if( m_isPrint ) 00074 { 00075 m_stream 00076 << boost::format("%2% %3% %4%;%|72t|%5% %1%") 00077 % posString(pos.line(),pos.column()) 00078 % (objName+"."+propName) 00079 % sign(oper) 00080 % valueToString(vectorValue , isVector) 00081 % GPP_COMMENT 00082 << std::endl ; 00083 } 00084 // -------------------------------------------------------------------------- 00085 // -------------------------------------------------------------------------- 00086 if (oper == S_ASSIGN) 00087 { 00088 // ------------------------------------------------------------------------ 00089 PropertyEntry* assignProp; 00090 if(isVector){ 00091 assignProp = new PropertyEntry(propName,vectorValue,pos); 00092 }else{ 00093 assignProp = new PropertyEntry(propName,vectorValue[0],pos); 00094 } 00095 m_catalogue.addProperty(objName,*assignProp); 00096 delete assignProp; 00097 // ------------------------------------------------------------------------ 00098 } 00099 else 00100 { 00101 // += or -= 00102 // ------------------------------------------------------------------------ 00103 PropertyEntry foundProp; 00104 bool ok; 00105 ok = m_catalogue.findProperty(objName,propName,foundProp); 00106 if (!ok) 00107 { 00108 foundProp = PropertyEntry(propName,std::vector<std::string>()); 00109 } 00110 if(oper == S_PLUSASSIGN) 00111 { 00112 ok = foundProp.addValues(vectorValue); 00113 if(!ok){ 00114 addMessage 00115 ( Message::E_ERROR, 00116 Message::C_CANNOTADDTONOTVECTOR, 00117 boost::str 00118 ( boost::format 00119 ("Cannot add values to not vector property \"%1%.%2%\"") 00120 % objName % propName),pos); 00121 return; 00122 } 00123 m_catalogue.addProperty(objName,foundProp); 00124 } 00125 // ------------------------------------------------------------------------ 00126 if(oper == S_MINUSASSIGN) 00127 { 00128 int count=0; 00129 ok = foundProp.removeValues(vectorValue,count); 00130 if(!ok){ 00131 addMessage 00132 ( Message::E_ERROR, 00133 Message::C_CANNOTREMOVEFROMNOTVECTOR, 00134 boost::str 00135 ( boost::format 00136 ( "Cannot remove values from not vector property \"%1%.%2%\"" ) 00137 % objName % propName),pos); 00138 return; 00139 } 00140 // ---------------------------------------------------------------------- 00141 if (count == 0) 00142 { 00143 addMessage 00144 ( Message::E_WARNING, 00145 Message::C_ZEROREMOVED, 00146 boost::str 00147 ( boost::format 00148 ( "Nothing removed from property \"%1%.%2%\"" ) 00149 % objName % propName),pos); 00150 } 00151 else 00152 { 00153 m_catalogue.addProperty(objName,foundProp); 00154 } 00155 00156 } 00157 // ------------------------------------------------------------------------ 00158 } 00159 } 00160 // ============================================================================ 00161 void Gaudi::Parsers::Parser::setIsPrint 00162 ( bool on , const Gaudi::Parsers::Position& pos) 00163 { 00164 // ignore the printout if the full print is activated 00165 if ( on && m_isPrintOptions ) { return ; } 00166 m_isPrint = on; 00167 //m_stream 00168 // << boost::format("%3% printing is %2% %|78t|%1%") 00169 // % posString(pos.line(),pos.column()) 00170 // % (on?"ON":"OFF") 00171 // % GPP_COMMENT 00172 // << std::endl ; 00173 } 00174 // ============================================================================ 00175 void Gaudi::Parsers::Parser::setIsPrintOptions 00176 ( bool on , const Position& pos) 00177 { 00178 m_isPrintOptions = on; 00179 //m_stream 00180 // << boost::format ("%3% printing options is %2% %|78t|%1%") 00181 // % posString(pos.line(),pos.column()) 00182 // % (on?"ON":"OFF") 00183 // % GPP_COMMENT 00184 // << std::endl ; 00185 // deactivate the printout if the print of all options is activated 00186 if ( m_isPrintOptions && m_isPrint ) { setIsPrint ( false , pos ) ; } 00187 } 00188 // ============================================================================ 00189 bool Gaudi::Parsers::Parser::parseFile 00190 ( const std::string& fileName , 00191 const Position& pos) 00192 { 00193 std::string fileToParse; 00194 bool ok = Gaudi::Parsers::Utils::searchFile(fileName,fileToParse); 00195 if(!ok){ 00196 addMessage( Message::E_ERROR, Message::C_FILENOTFOUND, 00197 boost::str(boost::format("Couldn't find file \"%1%\"") % fileName),pos); 00198 return false; 00199 } 00200 00201 ok = isIncluded(fileToParse); 00202 if(ok) 00203 { 00204 const std::string _msg = 00205 ( boost::format("Skip already included file \"%1%\"") % fileToParse ).str() ; 00206 addMessage ( Message::E_WARNING , Message::C_OK , _msg , pos ) ; 00207 if ( m_isPrint ) 00208 { 00209 m_stream 00210 << boost::format("%3% skip already included file \"%2%\" %|78t|%1%") 00211 % posString(pos.line(), pos.column()) 00212 % fileToParse 00213 % GPP_COMMENT 00214 << std::endl ; 00215 } 00216 return true; 00217 } 00218 std::string input; 00219 ok = Gaudi::Parsers::Utils::readFile(fileToParse,input); 00220 if(!ok) 00221 { 00222 addMessage 00223 ( Message::E_ERROR, Message::C_FILENOTOPENED, 00224 boost::str 00225 (boost::format("Couldn't open file \"%1%\"") % fileToParse),pos); 00226 return false; 00227 } 00228 m_included.push_back(fileToParse); 00229 00230 00231 IteratorT beginpos(input.begin(), input.end(), fileToParse); 00232 IteratorT endpos; 00233 00234 boost::spirit::parse_info<IteratorT> info; 00235 SkipperGrammar grSkipper; 00236 00237 //m_stream 00238 // << boost::format("%3% include \"%2%\" %|78t|%1%") 00239 // % posString(pos.line(), pos.column()) 00240 // % fileToParse 00241 // % GPP_COMMENT 00242 // << std::endl ; 00243 ParserGrammar grParser(this); 00244 info = boost::spirit::parse(beginpos, endpos, grParser >> end_p,grSkipper); 00245 00246 boost::spirit::file_position stoppos = info.stop.get_position(); 00247 if (!info.full) { 00248 addMessage(Message::E_ERROR, Message::C_SYNTAXERROR, 00249 "Syntax error",Position(stoppos.file,stoppos.line,stoppos.column)); 00250 return false; 00251 } 00252 { 00253 std::string _msg = 00254 ( boost::format("Parsed file \"%2%\" %|78t|%1%") 00255 % posString(stoppos.line, stoppos.column) 00256 % fileToParse ) .str() ; 00257 addMessage ( Message::E_VERBOSE , 00258 Message::C_OK , 00259 _msg , 00260 Position(stoppos.file,stoppos.line,stoppos.column) ) ; 00261 if ( m_isPrint ) 00262 { 00263 m_stream 00264 << boost::format("%3% end \"%2%\" %|78t|%1%") 00265 % posString(stoppos.line, stoppos.column) 00266 % fileToParse 00267 % GPP_COMMENT 00268 << std::endl ; 00269 } 00270 } 00271 return true; 00272 } 00273 // ============================================================================ 00274 std::string Gaudi::Parsers::Parser::severityName 00275 (Message::Severity severity){ 00276 switch(severity) 00277 { 00278 case Message::E_ERROR : 00279 return "ERROR" ; 00280 case Message::E_WARNING : 00281 return "WARNING" ; 00282 case Message::E_NOTICE : 00283 return "NOTICE" ; 00284 case Message::E_VERBOSE : 00285 return "VERBOSE" ; 00286 default: 00287 return "UNDEFINED" ; 00288 } 00289 } 00290 // ============================================================================ 00291 void Gaudi::Parsers::Parser::addMessage 00292 ( const Message::Severity& severity , 00293 const Message::Code& code , 00294 const std::string& message , 00295 const Position& pos ) 00296 { 00297 Message result 00298 ( severity , code, 00299 boost::str(boost::format("%1%(%2%,%3%) : %4% #%5% : %6%") % pos.fileName() 00300 % pos.line() % pos.column() % severityName(severity) % code 00301 % message)); 00302 m_messages.push_back(result); 00303 } 00304 // ============================================================================ 00305 // Purpose: Implementation of Parser::isIncluded() 00306 // Comment: Test if file already included 00307 // Parameters: 00308 // - fileName File name 00309 // Return: true if file already included 00310 // ============================================================================ 00311 bool Gaudi::Parsers::Parser::isIncluded(const std::string& fileName) 00312 { 00313 for(std::vector<std::string>::const_iterator cur=m_included.begin(); 00314 cur!=m_included.end();cur++) 00315 { if(fileName==*cur){ return true; } } 00316 return false; 00317 } 00318 // ============================================================================ 00319 // Purpose: Implementation of Parser::resolveReferences() 00320 // Comment: Resolve references 00321 // TODO: Refactor? 00322 // ============================================================================ 00323 void Gaudi::Parsers::Parser::resolveReferences() 00324 { 00325 Catalogue::CatalogueT cat = m_catalogue.catalogue(); 00326 // ---------------------------------------------------------------------------- 00327 for( Catalogue::CatalogueT::const_iterator curObj = cat.begin(); 00328 curObj!=cat.end();curObj++) 00329 { 00330 std::string objName = curObj->first; 00331 // ------------------------------------------------------------------------ 00332 for( std::vector<PropertyEntry>::const_iterator curProp = 00333 curObj->second.begin();curProp != curObj->second.end(); curProp++) 00334 { 00335 std::string value = curProp->value(); 00336 if ( (value.length()>0) && (value[0]=='@')) 00337 { 00338 // -------------------------------------------------------------------- 00339 std::vector<std::string> objAndProp; 00340 std::string refprop(value.begin()+1,value.end()); 00341 ba::split(objAndProp, 00342 refprop, 00343 ba::is_any_of(".")); 00344 PropertyEntry foundProperty; 00345 bool ok; 00346 ok = m_catalogue.findProperty(objAndProp[0],objAndProp[1], 00347 foundProperty); 00348 if(!ok) 00349 { 00350 addMessage 00351 ( Message::E_ERROR, 00352 Message::C_PROPERTYNOTFOUND, 00353 boost::str(boost::format("Cannot find property \"%1%.%2%\"") 00354 % objAndProp[0] % objAndProp[1]),curProp->position()); 00355 } 00356 else 00357 { 00358 // ------------------------------------------------------------------- 00359 if((ba::to_lower_copy(objAndProp[0]) == objName) 00360 && 00361 (ba::to_lower_copy(objAndProp[1]) 00362 == curProp->name())) 00363 { 00364 // ---------------------------------------------------------------- 00365 addMessage 00366 ( Message::E_ERROR, 00367 Message::C_BADREFERENCE, 00368 boost::str(boost::format("Reference to self \"%1%.%2%\"") 00369 % objAndProp[0] % objAndProp[1]),curProp->position()); 00370 // ---------------------------------------------------------------- 00371 } 00372 else 00373 { 00374 PropertyEntry property = foundProperty; 00375 property.setName(curProp->name()); 00376 m_catalogue.addProperty(objName,property); 00377 } 00378 // ------------------------------------------------------------------ 00379 } 00380 // -------------------------------------------------------------------- 00381 } 00382 } 00383 // ------------------------------------------------------------------------ 00384 } 00385 } 00386 // ============================================================================ 00387 // String representation of sign 00388 // ============================================================================ 00389 std::string Gaudi::Parsers::Parser::sign(Sign aSign) 00390 { 00391 switch(aSign) 00392 { 00393 case S_ASSIGN: 00394 return "="; 00395 case S_PLUSASSIGN: 00396 return "+="; 00397 case S_MINUSASSIGN: 00398 return "-="; 00399 default: 00400 return "unknown_operation"; 00401 } 00402 } 00403 // ============================================================================ 00404 // String representation of value vector 00405 // ============================================================================ 00406 std::string Gaudi::Parsers::Parser::valueToString 00407 ( std::vector<std::string> value, bool isVector ) 00408 { 00409 if ( !isVector){ return value[0]; } 00410 // 00411 std::string result; 00412 std::string delim; 00413 result+=" [ "; 00414 for ( std::vector<std::string>::const_iterator cur = value.begin(); 00415 cur != value.end(); cur++ ) 00416 { 00417 result += delim + *cur; 00418 delim = " , "; 00419 } 00420 return result + " ] "; 00421 } 00422 // ============================================================================ 00423 /* Implementation of Gaudi::Parsers::Utils::posString() 00424 * Comment: Convert position to string 00425 * Parameters: 00426 * - line Line 00427 * - column Column 00428 */ 00429 // ============================================================================ 00430 std::string Gaudi::Parsers::Parser::posString(int line, int column) 00431 { return boost::str(boost::format("(%1%,%2%)") % line % column); } 00432 // ============================================================================ 00433 00434 // ============================================================================ 00435 // The END 00436 // ============================================================================