File indexing completed on 2024-04-06 12:05:32
0001 #include "DetectorDescription/Parser/src/DDLMap.h"
0002 #include "DetectorDescription/Core/interface/ClhepEvaluator.h"
0003 #include "DetectorDescription/Parser/interface/DDLElementRegistry.h"
0004
0005
0006 #include "boost/spirit/home/classic/core/non_terminal/grammar.hpp"
0007 #include "boost/spirit/include/classic.hpp"
0008
0009 #include <cstddef>
0010 #include <utility>
0011
0012 class DDCompactView;
0013
0014 class MapPair {
0015 public:
0016 MapPair(DDLMap* iMap) : map_{iMap} {};
0017 void operator()(char const* str, char const* end) const;
0018
0019 private:
0020 DDLMap* map_;
0021 };
0022
0023 class MapMakeName {
0024 public:
0025 MapMakeName(DDLMap* iMap) : map_{iMap} {};
0026 void operator()(char const* str, char const* end) const;
0027
0028 private:
0029 DDLMap* map_;
0030 };
0031
0032 class MapMakeDouble {
0033 public:
0034 MapMakeDouble(DDLMap* iMap) : map_{iMap} {};
0035 void operator()(char const* str, char const* end) const;
0036
0037 private:
0038 DDLMap* map_;
0039 };
0040
0041 class Mapper : public boost::spirit::classic::grammar<Mapper> {
0042 public:
0043 Mapper(DDLMap* iMap) : map_{iMap} {};
0044 template <typename ScannerT>
0045 struct definition;
0046
0047 MapPair mapPair() const { return MapPair(map_); }
0048 MapMakeName mapMakeName() const { return MapMakeName(map_); }
0049 MapMakeDouble mapMakeDouble() const { return MapMakeDouble(map_); }
0050
0051 private:
0052 DDLMap* map_;
0053 };
0054
0055 namespace boost {
0056 namespace spirit {
0057 namespace classic {}
0058 }
0059 }
0060
0061 using namespace boost::spirit::classic;
0062
0063 DDLMap::DDLMap(DDLElementRegistry* myreg) : DDXMLElement(myreg) {}
0064
0065 template <typename ScannerT>
0066 struct Mapper::definition {
0067 definition(Mapper const& self) {
0068 mapSet = ppair[self.mapPair()] >> *((',' >> ppair)[self.mapPair()]);
0069
0070 ppair = name >> ch_p('=') >> value;
0071
0072 name = (alpha_p >> *alnum_p)[self.mapMakeName()];
0073
0074 value = (+(anychar_p - ','))[self.mapMakeDouble()];
0075 }
0076
0077 rule<ScannerT> mapSet, ppair, name, value;
0078
0079 rule<ScannerT> const& start() const { return mapSet; }
0080 };
0081
0082 void MapPair::operator()(char const* str, char const* end) const { map_->do_pair(str, end); }
0083
0084 void MapMakeName::operator()(char const* str, char const* end) const { map_->do_makeName(str, end); }
0085
0086 void MapMakeDouble::operator()(char const* str, char const* end) const { map_->do_makeDouble(str, end); }
0087
0088 void DDLMap::preProcessElement(const std::string& name, const std::string& nmspace, DDCompactView& cpv) {
0089 pName = "";
0090 pMap.clear();
0091
0092 pDouble = 0.0;
0093 pNameSpace = nmspace;
0094 }
0095
0096 void DDLMap::processElement(const std::string& name, const std::string& nmspace, DDCompactView& cpv) {
0097 std::string tTextToParse = getText();
0098 DDXMLAttribute atts = getAttributeSet();
0099 std::string tName = atts.find("name")->second;
0100
0101 if (tTextToParse.empty()) {
0102 errorOut("No std::string to parse!");
0103 }
0104
0105
0106 if (atts.find("type") != atts.end() && atts.find("type")->second == "string") {
0107 errorOut("Map of type std::string is not supported yet.");
0108 }
0109
0110 Mapper mapGrammar{this};
0111
0112 pMap.clear();
0113
0114 parse_info<> info = boost::spirit::classic::parse(tTextToParse.c_str(), mapGrammar >> end_p, space_p);
0115 if (!info.full) {
0116 errorOut("Does not conform to name=value, name=value... etc. of ddl Map element.");
0117 }
0118
0119 if (parent() == "Algorithm" || parent() == "SpecPar") {
0120 pMapMap[tName] = pMap;
0121 } else if (parent() == "ConstantsSection" || parent() == "DDDefinition") {
0122 dd_map_type tMap;
0123 for (std::map<std::string, double>::const_iterator it = pMap.begin(); it != pMap.end(); ++it) {
0124 tMap[it->first] = it->second;
0125 }
0126 DDMap m(getDDName(pNameSpace), std::make_unique<dd_map_type>(tMap));
0127
0128 pMapMap.clear();
0129 }
0130
0131 std::string nEntries = atts.find("nEntries")->second;
0132 if (pMap.size() != size_t(myRegistry_->evaluator().eval(pNameSpace, nEntries))) {
0133 errorOut("Number of entries found in Map text does not match number in attribute nEntries.");
0134 }
0135 clear();
0136 }
0137
0138 void DDLMap::do_pair(char const* str, char const* end) { pMap[pName] = pDouble; }
0139
0140 void DDLMap::do_makeName(char const* str, char const* end) { pName = std::string(str, end); }
0141
0142 void DDLMap::do_makeDouble(char const* str, char const* end) {
0143 std::string ts(str, end);
0144 pDouble = myRegistry_->evaluator().eval(pNameSpace, ts);
0145 }
0146
0147 void DDLMap::errorOut(const char* str) {
0148 std::string msg("\nDDLMap: Failed to parse the following: \n");
0149 msg += std::string(str);
0150 msg += "\n as a Map element (comma separated list of name=value).";
0151 throwError(msg);
0152 }
0153
0154 ReadMapType<std::map<std::string, double> >& DDLMap::getMapOfMaps(void) { return pMapMap; }