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
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
00043
00044
00045
00046 struct DDSelLevelFtor
00047 {
00048 DDSelLevelFtor()
00049 : c_(DDI::Singleton<DDSelLevelCollector>::instance())
00050 { }
00051
00052
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
00058 } else
00059 if (c_.isCopyNoValid_ && !c_.isChild_) {
00060 c_.path()->push_back(DDPartSelRegExpLevel(c_.namespace_,c_.name_,c_.copyNo_,ddanyposp));
00061
00062 } else
00063 if (!c_.isCopyNoValid_ && c_.isChild_) {
00064 c_.path()->push_back(DDPartSelRegExpLevel(c_.namespace_,c_.name_,c_.copyNo_,ddchildlogp));
00065
00066 } else
00067 if (!c_.isCopyNoValid_ && !c_.isChild_) {
00068 c_.path()->push_back(DDPartSelRegExpLevel(c_.namespace_,c_.name_,c_.copyNo_,ddanylogp));
00069
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
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
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
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
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
00144
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
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
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
00276
00277
00278
00279
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
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
00302
00303
00304
00305
00306
00307
00308
00309
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) {
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
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
00358 std::string nm = "blabla" ;
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
00373 while(tk_it != toksVec.end() && tx_it != textVec.end()) {
00374
00375
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
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
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
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
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
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
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
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 }