CMS 3D CMS Logo

DDPartSelection.cc

Go to the documentation of this file.
00001 #include "DetectorDescription/Base/interface/Singleton.h"
00002 #include "DetectorDescription/Core/interface/DDPartSelection.h"
00003 #include "DetectorDescription/Base/interface/DDException.h"
00004 #include "DetectorDescription/Base/interface/DDdebug.h"
00005 #include "DetectorDescription/Core/interface/DDSplit.h"
00006 
00007 #include "boost/spirit.hpp"
00008 
00009 // Message logger.
00010 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00011 
00012 #include <map>
00013 
00014 namespace boost { namespace spirit {} } using namespace boost::spirit;
00015 
00016 struct DDSelLevelCollector
00017 {
00018   std::string namespace_;
00019   std::string name_;
00020   int copyNo_;
00021   bool isCopyNoValid_;
00022   bool isChild_;
00023   std::vector<DDPartSelRegExpLevel>* p_;
00024 
00025   std::vector<DDPartSelRegExpLevel>* path(std::vector<DDPartSelRegExpLevel>* p=0) {
00026     if (p) {
00027       p_=p; 
00028       namespace_="";
00029       name_="";
00030       copyNo_=0;
00031       isCopyNoValid_=false;
00032       isChild_=false;
00033     }
00034     return p_;
00035   }
00036 };
00037 
00038 
00039 void noNameSpace(char const * first, char const* last) {
00040   DDI::Singleton<DDSelLevelCollector>::instance().namespace_="";
00041 }
00042 /* Functor for the parser; it does not consume memory -
00043   pointers are only used to store references to memory
00044   managed elsewhere 
00045 */
00046 struct DDSelLevelFtor
00047 {
00048   DDSelLevelFtor() 
00049     : c_(DDI::Singleton<DDSelLevelCollector>::instance())
00050   { }
00051   
00052   // parser calls this whenever a selection has been parsed ( //ns:nm[cn], /nm, //ns:nm, .... ) 
00053   void operator() (char const* first, char const* last) const {
00054    if(c_.path()){
00055     if (c_.isCopyNoValid_ && c_.isChild_) {
00056       c_.path()->push_back(DDPartSelRegExpLevel(c_.namespace_,c_.name_,c_.copyNo_,ddchildposp));
00057       //edm::LogInfo("DDPartSelection")  << namespace_ << name_ << copyNo_ << ' ' << ddchildposp << std::endl;
00058     } else
00059     if (c_.isCopyNoValid_ && !c_.isChild_) {
00060       c_.path()->push_back(DDPartSelRegExpLevel(c_.namespace_,c_.name_,c_.copyNo_,ddanyposp));
00061       //      edm::LogInfo("DDPartSelection")  << namespace_ << name_ << copyNo_ << ' ' << ddanyposp << std::endl;
00062     } else
00063     if (!c_.isCopyNoValid_ && c_.isChild_) {
00064       c_.path()->push_back(DDPartSelRegExpLevel(c_.namespace_,c_.name_,c_.copyNo_,ddchildlogp));
00065       //      edm::LogInfo("DDPartSelection")  << namespace_ << name_ << copyNo_ << ' ' << ddchildlogp << std::endl;
00066     } else
00067     if (!c_.isCopyNoValid_ && !c_.isChild_) {
00068       c_.path()->push_back(DDPartSelRegExpLevel(c_.namespace_,c_.name_,c_.copyNo_,ddanylogp));
00069       //      edm::LogInfo("DDPartSelection")  << namespace_ << name_ << copyNo_ << ' ' << ddanylogp << std::endl;
00070     } 
00071     c_.namespace_="";
00072     c_.name_="";
00073     c_.isCopyNoValid_=false;   
00074    } 
00075   }
00076      
00077   DDSelLevelCollector & c_;    
00078 };
00079 
00080 
00081 struct DDIsChildFtor
00082 {
00083   
00084   void operator()(char const* first, char const* last) const {
00085    DDSelLevelCollector & sl = DDI::Singleton<DDSelLevelCollector>::instance();
00086    if ( (last-first) > 1) 
00087      sl.isChild_=false;
00088    if ( (last-first) ==1 )
00089      sl.isChild_=true;
00090    //edm::LogInfo("DDPartSelection")  << "DDIsChildFtor  isChild=" << (last-first) << std::endl;
00091   }
00092  
00093 };
00094 
00095 
00096 struct DDNameSpaceFtor
00097 {
00098   
00099   void operator()(char const* first, char const* last) const {
00100     DDSelLevelCollector & sl = DDI::Singleton<DDSelLevelCollector>::instance();  
00101     sl.namespace_.assign(first,last);
00102     // edm::LogInfo("DDPartSelection")  << "DDNameSpaceFtor singletonname=" << DDI::Singleton<DDSelLevelCollector>::instance().namespace_ << std::endl;
00103   }
00104   
00105   DDSelLevelFtor* selLevelFtor_;
00106 };
00107 
00108 
00109 struct DDNameFtor
00110 {
00111  
00112   void operator()(char const* first, char const* last) const {
00113     DDSelLevelCollector & sl = DDI::Singleton<DDSelLevelCollector>::instance();
00114     sl.name_.assign(first,last);  
00115     // edm::LogInfo("DDPartSelection")  << "DDNameFtor singletonname=" << Singleton<DDSelLevelCollector>::instance().name_ << std::endl;
00116   }
00117   
00118 };
00119 
00120 
00121 struct DDCopyNoFtor
00122 {
00123   
00124   void operator()(int i) const {
00125     DDSelLevelCollector & sl = DDI::Singleton<DDSelLevelCollector>::instance();  
00126     sl.copyNo_ = i;
00127     sl.isCopyNoValid_ = true;
00128     // edm::LogInfo("DDPartSelection")  << "DDCopyNoFtor ns=" << i;
00129   }
00130  
00131 };
00132  
00133  
00134 
00136 struct SpecParParser : public grammar<SpecParParser>
00137 {
00138   template <typename ScannerT>
00139   struct definition
00140   {
00141     definition(SpecParParser const& self) {
00142          
00143         Selection  //= FirstStep[selLevelFtor()] 
00144                   //>> *SelectionStep[selLevelFtor()]
00145                    = +SelectionStep[selLevelFtor()]
00146                    ;
00147 
00148         FirstStep  = Descendant 
00149                   >> Part
00150                    ; 
00151 
00152         Part       = PartNameCopyNumber 
00153                    | PartName
00154                    ;
00155 
00156         PartNameCopyNumber = PartName 
00157                   >> CopyNumber
00158                    ;
00159 
00160         SelectionStep = NavigationalElement[isChildFtor()] 
00161                   >> Part
00162                    ;
00163 
00164         NavigationalElement = Descendant 
00165                    | Child
00166                    ;
00167 
00168         CopyNumber = ch_p('[') 
00169                   >> int_p[copyNoFtor()] 
00170                   >> ch_p(']')
00171                    ;
00172 
00173         PartName   = NameSpaceName 
00174                    | SimpleName[nameFtor()][&noNameSpace]
00175                    ;
00176 
00177         SimpleName = +( alnum_p | ch_p('_') | ch_p('.') | ch_p('*') )
00178                    ;
00179 
00180         NameSpaceName = SimpleName[nameSpaceFtor()] 
00181                   >> ':' 
00182                   >> SimpleName[nameFtor()]
00183                    ;
00184 
00185         Descendant = ch_p('/') 
00186                   >> ch_p('/')
00187                    ;
00188 
00189         Child      = ch_p('/')
00190                     ;
00191   
00192          }
00193   
00194     rule<ScannerT> Selection, FirstStep, Part, SelectionStep, NavigationalElement,
00195         CopyNumber, PartName, PartNameCopyNumber, NameSpaceName, SimpleName, 
00196         Descendant, Child; 
00197 
00198     rule<ScannerT> const& start() const { return Selection; }
00199     
00200     DDSelLevelFtor & selLevelFtor() {
00201       return DDI::Singleton<DDSelLevelFtor>::instance();
00202     }
00203     
00204     DDNameFtor & nameFtor() {
00205      static DDNameFtor f_;
00206      return f_;
00207     }
00208     
00209     DDNameSpaceFtor & nameSpaceFtor() {
00210      static DDNameSpaceFtor f_;
00211      return f_;
00212     }
00213     
00214     DDIsChildFtor & isChildFtor() {
00215      static DDIsChildFtor f_;
00216      return f_;
00217     }
00218 
00219     DDCopyNoFtor & copyNoFtor() {
00220      static DDCopyNoFtor f_;
00221      return f_;
00222     }    
00223   };
00224   
00225 };
00226 
00227 
00228 /*
00229 std::ostream & operator<<(std::ostream & os, const DDPartSelection & ps)
00230 {
00231   DDPartSelection::const_iterator it = ps.begin();
00232   for (; it != ps.end(); ++it) {
00233     std::string s;
00234     switch (it->selectionType_) {
00235       case ddunknown: case ddanynode: case ddanychild:
00236         os << "*ERROR*";
00237         break;
00238       case ddanylogp: 
00239         os << "//" << it->lp_.ddname();
00240         break;
00241       case ddanyposp:
00242         os << "//" << it->lp_.ddname() << '[' << it->copyno_ << ']';
00243         break;
00244       case ddchildlogp:                 
00245         os << "/" << it->lp_.ddname();
00246         break;
00247       case ddchildposp:
00248         os << "/" << it->lp_.ddname() << '[' << it->copyno_ << ']';             
00249         break;
00250     }
00251   
00252   }
00253   return os;
00254 }
00255 */
00256 
00257 DDPartSelectionLevel::DDPartSelectionLevel(const DDLogicalPart & lp, int c, ddselection_type t)
00258  : lp_(lp), copyno_(c), selectionType_(t)
00259 {
00260   
00261 }
00262 
00263 
00264 
00265 void DDTokenize2(const std::string & sel, std::vector<DDPartSelRegExpLevel> & path)
00266 {
00267   static SpecParParser parser;
00268   DDI::Singleton<DDSelLevelCollector>::instance().path(&path);
00269   bool result = parse(sel.c_str(), parser).full;
00270   if (!result) {
00271     edm::LogError("DDPartSelection") << "DDTokenize2() error in parsing of " << sel << std::endl;
00272   }
00273 }
00274 
00275 // uhhhhhhhhhhhhhhhh! Spaghetti code!!!!!!!!! (or worse?)
00276 // FIXME: DDTokenize: if a LogicalPart is not yet defined during parsing of a SpecPar 
00277 // FIXME: (ddunknown is then the corresponding ddselection_type of the PartSelection)
00278 // FIXME: then set a state-variable to 'undefined' .
00279 // FIXME: After parsing, reprocess all undefined SpecPars ...
00280 void DDTokenize(const std::string & sel, std::vector<DDPartSelRegExpLevel> &  path)
00281 {
00282 
00283 
00284   static bool isInit(false);
00285   static std::vector<std::string> tokens;
00286   if(!isInit) {
00287     // initialize with valid tokens
00288     tokens.push_back("/"); 
00289     tokens.push_back("//");
00290     tokens.push_back("[");
00291     tokens.push_back("]");
00292   }
00293   std::string s = sel;
00294   std::string::size_type st = std::string::npos;
00295   std::string::size_type cu = 0;
00296   std::vector<std::string> toksVec;
00297   std::vector<std::string> textVec;
00298   std::string tkn, txt;
00299   bool braceOpen(false);
00300   /*
00301     the following code should decompose a selection std::string into 2 std::vectors,
00302     a token-std::vector and a text-std::vector. Tokens are /,//,[,] 
00303     example: "//Abc[3]/Def" ->
00304              tokens  text
00305              //      ""
00306              [       Abc
00307              ]       3
00308              /       ""
00309                      "Def"
00310   */  
00311   
00312   while (s.size()) {
00313     std::vector<std::string>::iterator tkit = tokens.begin();
00314     std::vector<std::string>::iterator mint = tokens.end();
00315     st=s.size();
00316     std::string::size_type ts;
00317     for(;tkit!=tokens.end();++tkit) { // find the first match of one of the token std::strings
00318       ts = s.find(*tkit); 
00319       if (ts<=st) { 
00320         st=ts;
00321         mint = tkit;
00322       }  
00323     }
00324     
00325     if (mint!=tokens.end())     
00326      tkn = s.substr(st,mint->size());
00327     else
00328      tkn=""; 
00329     txt = s.substr(cu,st);
00330     toksVec.push_back(tkn);
00331     textVec.push_back(txt);
00332     if (braceOpen) {
00333       if (tkn!="]")
00334         throw DDException(std::string("PartSelector: syntaxerror in ") + sel + 
00335                           std::string("\ncheck the braces!") );
00336       else
00337         braceOpen=false;
00338     }           
00339     if (tkn=="[")
00340       braceOpen=true;
00341     DCOUT_V('C',"tkn=" << tkn << " txt=" << txt);   
00342     if (mint!=tokens.end())
00343       s.erase(cu,st+mint->size()); 
00344     else
00345       s.erase();  
00346     DCOUT_V('C', std::endl << "s=" << s);   
00347     //break;    
00348   }
00349   DCOUT_V('C', "The original std::string was:" << std::endl);
00350   unsigned int i=0;
00351   DCOUT_V('C', "toks\ttext");
00352   for (i=0; i<toksVec.size();++i) {
00353     DCOUT_V('C',  toksVec[i] << "\t" << textVec[i]);
00354   }  
00355   DCOUT_V('C', std::endl); 
00356   
00357   // now some spaghetti code 
00358   std::string nm = "blabla" ; // std::string("PartSelector=") + ns() + std::string(":") + name();
00359   if (textVec[0] != "")
00360     throw DDException( nm 
00361                       +std::string(" selection must not start with a LogicalPart-name")); 
00362   
00363   if ((toksVec[0] != "//"))
00364     throw DDException( nm 
00365                       +std::string(" selection must start with '//' !")); 
00366   
00367   if (textVec.size() < 2)
00368     throw DDException( nm + std::string(" internal error [textVec.size()<2]!"));
00369     
00370   std::vector<std::string>::iterator tk_it = toksVec.begin();
00371   std::vector<std::string>::iterator tx_it = textVec.begin(); ++tx_it;
00372   // the BIG switch - yes, this is OO!!!
00373   while(tk_it != toksVec.end() && tx_it != textVec.end()) {
00374  
00375     // anynode ... token //* makes no sense (except as last entry which is forbidden ...)
00376     DCOUT_V('C', ">- anynode tkn=" << *tk_it << " d=" << tk_it-toksVec.begin() << " txt=" << *tx_it << std::endl);
00377     if ( *tk_it == "//" && *tx_it=="*" ) { 
00378       path.push_back(DDPartSelRegExpLevel("","",0,ddanynode));
00379       DCOUT_V('C', "--anynode: //*" << std::endl);
00380       ++tk_it;
00381       ++tx_it;
00382       continue;
00383     }
00384              
00385     // anychild
00386     DCOUT_V('C', ">- anychild tkn=" << *tk_it << " d=" << tk_it-toksVec.begin() << " txt=" << *tx_it << std::endl);
00387     if ( *tk_it == "/" && *tx_it=="*" ) { 
00388       path.push_back(DDPartSelRegExpLevel("","",0,ddanychild));
00389       DCOUT_V('C', "--anychild: /*" << std::endl);
00390       ++tk_it;
00391       ++tx_it;
00392       continue;
00393     }    
00394 
00395     // anylogp
00396     DCOUT_V('C', ">- anylogp tkn=" << *tk_it << " d=" << tk_it-toksVec.begin() << " txt=" << *tx_it << std::endl);
00397     if ( *tk_it == "//" && tx_it->size()) {
00398       ++tk_it;
00399       if ( tk_it != toksVec.end() && *tk_it != "[" && *tk_it != "]") {
00400         std::pair<std::string,std::string> p(DDSplit(*tx_it));
00401           path.push_back(DDPartSelRegExpLevel(p.second,p.first,0,ddanylogp));
00402         DCOUT_V('C', "--anylogp: " << *tx_it << std::endl);
00403         ++tx_it;
00404         continue;
00405       } 
00406       --tk_it;
00407     }    
00408 
00409     // childlogp
00410     DCOUT_V('C', ">- childlogp tkn=" << *tk_it << " d=" << tk_it-toksVec.begin() << " txt=" << *tx_it << std::endl);
00411     if ( *tk_it == "/" && tx_it->size()) {
00412       ++tk_it;
00413       if ( tk_it == toksVec.end() - 1 ) {
00414         DCOUT_V('C', "--childlogp: " << *tx_it << std::endl);
00415         std::pair<std::string,std::string> p(DDSplit(*tx_it));
00416           path.push_back(DDPartSelRegExpLevel(p.second,p.first,0,ddchildlogp));
00417         ++tx_it;   
00418         continue;
00419       }
00420       if ( *tk_it == "/" || *tk_it=="//") {
00421         DCOUT_V('C', "--childlogp: " << *tx_it << std::endl);
00422         std::pair<std::string,std::string> p(DDSplit(*tx_it));
00423           path.push_back(DDPartSelRegExpLevel(p.second,p.first,0,ddchildlogp));
00424         ++tx_it;
00425         continue;
00426       }
00427       --tk_it;
00428     }   
00429 
00430 
00431     // anyposp
00432     DCOUT_V('C', ">- anyposp tkn=" << *tk_it << " d=" << tk_it-toksVec.begin() << " txt=" << *tx_it << std::endl);
00433     if ( *tk_it == "//" && tx_it->size()) {
00434       ++tk_it;
00435       if ( tk_it != toksVec.end() && *tk_it == "[" ) {
00436         ++tk_it;
00437         if ( tk_it == toksVec.end() || (tk_it != toksVec.end() && *tk_it != "]")) {
00438          DCOUT_V('C', *tk_it << " " << *tx_it );
00439            break;
00440         }  
00441         ++tx_it;
00442         ++tk_it;
00443         std::pair<std::string,std::string> p(DDSplit(*(tx_it-1)));
00444           path.push_back(DDPartSelRegExpLevel(p.second,p.first,atoi(tx_it->c_str()),ddanyposp));
00445         DCOUT_V('C', "--anyposp: " << *tx_it << " " << atoi(tx_it->c_str()) << std::endl);
00446         ++tx_it;
00447         ++tx_it;
00448         continue;
00449       } 
00450     }    
00451         
00452          
00453     // childposp
00454     DCOUT_V('C', ">- childposp tkn=" << *tk_it << " d=" << tk_it-toksVec.begin() << " txt=" << *tx_it << std::endl);
00455     if ( *tk_it == "/" && tx_it->size()) {
00456       ++tk_it;
00457       if ( tk_it != toksVec.end() && *tk_it=="[" ) {
00458         DCOUT_V('C', "--childposp: " << *tx_it << " " << *tk_it << *(tx_it+1) << std::endl);
00459         std::pair<std::string,std::string> p(DDSplit(*tx_it));
00460           path.push_back(DDPartSelRegExpLevel(p.second,p.first,atoi((tx_it+1)->c_str()),ddchildposp));
00461 
00462         ++tx_it;
00463 
00464         ++tx_it;
00465         ++tk_it;
00466         if (tk_it != toksVec.end() && *tk_it != "]") 
00467           break;
00468         ++tk_it;
00469         ++tx_it;
00470         continue;  
00471       }
00472     }
00473     
00474     // any
00475     throw DDException( nm + std::string(" syntax error in:\n") + sel + 
00476                             std::string("\n  tkn=") + *tk_it + std::string("  txt=")+ *tx_it);                              
00477   }
00478   //FIXME: DDPartSelectorImpl::tokenize : prototype has restricted support for selection std::string (code below restricts)
00479   ddselection_type tmp = path.back().selectionType_;
00480   if (tmp==ddunknown || tmp==ddanynode || tmp==ddanychild ) 
00481         throw DDException(std::string("PartSelector: last element in selection std::string in ") + sel + 
00482                           std::string("\nmust address a distinct LogicalPart or PosPart!") );
00483 }
00484 
00485 
00486 std::ostream & operator<<(std::ostream & o, const DDPartSelection & p)
00487 {
00488   DDPartSelection::const_iterator it(p.begin()), ed(p.end());
00489   for (; it != ed; ++it) {
00490     const DDPartSelectionLevel lv  =*it;
00491     switch (lv.selectionType_) {
00492     case ddanylogp:
00493       o << "//" << lv.lp_.ddname();
00494       break;
00495     case ddanyposp:
00496       o << "//" << lv.lp_.ddname() << '[' << lv.copyno_ << ']';
00497       break;
00498     case ddchildlogp:
00499       o << "/" << lv.lp_.ddname();
00500       break;
00501     case ddchildposp:
00502       o << "/" << lv.lp_.ddname() << '[' << lv.copyno_ << ']';
00503       break;
00504     default:
00505       o << "{Syntax ERROR}";
00506     }
00507   }
00508   return o;
00509 }
00510 
00511 std::ostream & operator<<(std::ostream & os, const std::vector<DDPartSelection> & v)
00512 {
00513   std::vector<DDPartSelection>::const_iterator it(v.begin()), ed(v.end());
00514   for (; it != (ed-1); ++it) {
00515     os << *it << std::endl;
00516   }
00517   if ( it != ed ) {
00518     ++it;
00519     os << *it;
00520   }
00521   return os;
00522 }

Generated on Tue Jun 9 17:32:16 2009 for CMSSW by  doxygen 1.5.4