Gaudi Framework, version v22r4

Home   Generated: Fri Sep 2 2011

Analyzer.cpp

Go to the documentation of this file.
00001 // ============================================================================
00002 // STD:
00003 // ============================================================================
00004 #include <iostream>
00005 // ============================================================================
00006 // BOOST:
00007 // ============================================================================
00008 #include <boost/foreach.hpp>
00009 #include <boost/lexical_cast.hpp>
00010 #include <boost/format.hpp>
00011 #include <boost/shared_ptr.hpp>
00012 // ============================================================================
00013 #include "Analyzer.h"
00014 #include "Parser.h"
00015 #include "Messages.h"
00016 #include "Catalog.h"
00017 #include "Units.h"
00018 #include "PragmaOptions.h"
00019 #include "Node.h"
00020 #include "IncludedFiles.h"
00021 #include "PropertyName.h"
00022 #include "PropertyValue.h"
00023 // ============================================================================
00024 #include "GaudiKernel/Environment.h"
00025 // ============================================================================
00026 namespace gp = Gaudi::Parsers;
00027 // ============================================================================
00028 static bool IncludeNode(gp::Node* node,
00029         const std::string& search_path,
00030         gp::IncludedFiles* included, gp::Messages* messages) {
00031     gp::Node include_root;
00032     bool status = gp::Parse(node->position, node->value, search_path, included,
00033             messages, &include_root);
00034     if (status) {
00035         node->value = include_root.value;  // Save absolute file path
00036         BOOST_FOREACH(const gp::Node& child, include_root.children) {
00037           node->children.push_back(child);
00038         }
00039     } else {
00040         return false;
00041     }
00042     return true;
00043 }
00044 // ============================================================================
00045 static bool UnitsNode(gp::Node* node,
00046         const std::string& search_path,
00047         gp::IncludedFiles* included, gp::Messages* messages) {
00048     gp::Node units_root;
00049     bool status = gp::ParseUnits(node->position, node->value, search_path,
00050             included, messages, &units_root);
00051     if (status) {
00052         node->value = units_root.value;  // Save absolute file path
00053         BOOST_FOREACH(const gp::Node& child, units_root.children) {
00054           node->children.push_back(child);
00055         }
00056     } else {
00057         return false;
00058     }
00059     return true;
00060 }
00061 // ============================================================================
00062 static void GetPropertyName(const gp::Node* node,
00063         gp::PropertyName::ScopedPtr& property_name) {
00064   if (node->children.size() == 1) {
00065     property_name.reset(new gp::PropertyName(node->children[0].value,
00066         node->position));
00067   }else {
00068     std::string delim="";
00069     std::string client="";
00070     for(unsigned int i=0; i < (node->children.size() - 1); i++) {
00071       client += delim+node->children[i].value;
00072       delim = '.';
00073     }
00074     property_name.reset(new gp::PropertyName(client,
00075         node->children[node->children.size() - 1].value, node->position));
00076   }
00077 }
00078 // ============================================================================
00079 static void GetPropertyValue(const gp::Node* node,
00080         gp::PropertyValue::ScopedPtr& value, gp::Catalog* catalog,
00081         gp::Units* units) {
00082   switch (node->type) {
00083     // ------------------------------------------------------------------------
00084     case gp::Node::kReal: {
00085       //  Example:
00086       //  <real value="10" line="3" column="7">
00087       //     <identifier value="m" line="3" column="10"/>
00088       //  </real>
00089       //
00090       if (node->children.size() == 1) {
00091         // Unit is presented
00092         std::string unit_name = node->children[0].value;
00093         double unit_value = 0;
00094         if (units->Find(unit_name, unit_value)) {
00095           // We have found a unit
00096           double val = boost::lexical_cast<double>(node->value);
00097           std::string store =
00098               boost::lexical_cast<std::string>(val * unit_value);
00099           value.reset(new gp::PropertyValue(store));
00100         }else {
00101           // Unit not found
00102           throw
00103           gp::PositionalPropertyValueException::CouldNotFindUnit(
00104               node->children[0].position, unit_name);
00105         }
00106       }else {
00107         value.reset(new gp::PropertyValue(node->value));
00108       }
00109       break;
00110     }
00111     // ------------------------------------------------------------------------
00112     case gp::Node::kString: {
00113       value.reset(new gp::PropertyValue('"'+node->value+'"'));
00114       break;
00115     }
00116     // ------------------------------------------------------------------------
00117     case gp::Node::kBool: {
00118       value.reset(new gp::PropertyValue(node->value));
00119       break;
00120     }
00121     // ------------------------------------------------------------------------
00122     case gp::Node::kVector: {
00123       std::vector<std::string> result;
00124       BOOST_FOREACH(const gp::Node& child, node->children) {
00125         gp::PropertyValue::ScopedPtr vvalue;
00126         GetPropertyValue(&child, vvalue, catalog, units);
00127         result.push_back(vvalue->ToString());
00128       }
00129       value.reset(new gp::PropertyValue(result));
00130       break;
00131     }
00132     // ------------------------------------------------------------------------
00133     case gp::Node::kMap: {
00134       std::map<std::string, std::string> result;
00135       BOOST_FOREACH(const gp::Node& child, node->children) {
00136         gp::PropertyValue::ScopedPtr kvalue;
00137         gp::PropertyValue::ScopedPtr vvalue;
00138         GetPropertyValue(&child.children[0], kvalue, catalog, units);
00139         GetPropertyValue(&child.children[1], vvalue, catalog, units);
00140         result.insert(
00141             std::pair<std::string, std::string>(
00142                 kvalue->ToString(),
00143                 vvalue->ToString()));
00144       }
00145       value.reset(new gp::PropertyValue(result));
00146       break;
00147     }
00148     // ------------------------------------------------------------------------
00149     case gp::Node::kProperty: {
00150       gp::PropertyName::ScopedPtr property;
00151       GetPropertyName(node, property);
00152       gp::Property* exists = NULL;
00153       if (NULL != (exists = catalog->Find(property->client(),
00154           property->property()))) {
00155         value.reset(new gp::PropertyValue(exists->property_value()));
00156       }else {
00157         throw
00158         gp::PositionalPropertyValueException::CouldNotFindProperty(
00159             node->position,property->ToString());
00160       }
00161       break;
00162     }
00163     case gp::Node::kPropertyRef: {
00164       gp::PropertyName::ScopedPtr property;
00165       GetPropertyName(node, property);
00166       // Save a property reference as vector [clientname, property]
00167       std::vector<std::string> reference;
00168       reference.push_back(property->client());
00169       reference.push_back(property->property());
00170 
00171       value.reset(new gp::PropertyValue(reference,property->position(),
00172           true));
00173       break;
00174     }
00175     // ------------------------------------------------------------------------
00176     default: {
00177       assert(false);
00178       break;
00179     }
00180   }
00181 }
00182 
00183 // ============================================================================
00184 static std::string SignString(gp::Node::NodeType type) {
00185   switch (type) {
00186     case gp::Node::kEqual : {
00187       return "=";
00188     }
00189 
00190     case gp::Node::kPlusEqual : {
00191       return "+=";
00192     }
00193 
00194     case gp::Node::kMinusEqual : {
00195       return "-=";
00196     }
00197     default: {
00198       assert(false);
00199       break;
00200     }
00201  }
00202   return "unknown";
00203 
00204 }
00205 // ============================================================================
00206 static bool AssignNode(const gp::Node* node,
00207         gp::Messages* messages, gp::Catalog* catalog, gp::Units* units,
00208         bool is_print) {
00209 // ----------------------------------------------------------------------------
00210     gp::PropertyName::ScopedPtr property;
00211     gp::PropertyValue::ScopedPtr value;
00212 // ----------------------------------------------------------------------------
00213     GetPropertyName(&node->children[0], property);
00214     try {
00215       GetPropertyValue(&node->children[2], value, catalog, units);
00216     }catch(const gp::PositionalPropertyValueException& ex){
00217       messages->AddError(ex.position(), ex.what());
00218       return false;
00219     }
00220     // ------------------------------------------------------------------------
00221     gp::Property* exists = NULL;
00222     bool reassign = false;
00223 // ----------------------------------------------------------------------------
00224     if (NULL != (exists = catalog->Find(property->client(),
00225                                                       property->property()))) {
00226       // ----------------------------------------------------------------------
00227       // If property already exists:
00228       // ----------------------------------------------------------------------
00229       try {
00230         if (node->children[1].type == gp::Node::kEqual) {
00231           std::string message = str(boost::format("Reassignment of option '%1%' .")
00232             % property->FullName());
00233           if (exists->HasDefinedPosition()) {
00234             message += " Previously defined at " +
00235                 exists->DefinedPosition().ToString() + ".";
00236           }
00237           reassign = true;
00238           messages->AddWarning(node->position, message);
00239         }else if (node->children[1].type == gp::Node::kPlusEqual) {
00240           *exists += *value;
00241         }else if (node->children[1].type == gp::Node::kMinusEqual) {
00242           *exists -= *value;
00243         }
00244       }catch(const gp::PropertyValueException& ex) {
00245         std::string message = ex.what();
00246         if (exists->HasDefinedPosition()) {
00247           message += " Previously defined at "+exists->DefinedPosition().
00248               ToString()+".";
00249         }
00250         messages->AddError(node->position, message);
00251         return false;
00252       }
00253     }
00254 // ----------------------------------------------------------------------------
00255     bool result = true;
00256     if ( (NULL == exists) || reassign) {
00257       result = catalog->Add(new gp::Property(*property, *value));
00258     }
00259 
00260     if (result && is_print) { /*;%|72t|%2% %3%*/
00261       std::string message = str(boost::format("%1% %2% %3%")
00262             % property->FullName()
00263             % SignString(node->children[1].type)
00264             % value->ToString());
00265       messages->AddInfo(node->position, message);
00266     }
00267     return result;
00268 }
00269 // ============================================================================
00270 static bool UnitNode(const gp::Node* node,
00271         gp::Messages* messages, gp::Units* units, bool is_print) {
00272   // --------------------------------------------------------------------------
00273   double left  = boost::lexical_cast<double>(node->children[0].value);
00274   std::string name  = node->children[1].value;
00275   double right  = boost::lexical_cast<double>(node->children[2].value);
00276   // --------------------------------------------------------------------------
00277   gp::Units::Container::mapped_type exists;
00278   if (units->Find(name, exists)) {
00279     std::string message =
00280         str(boost::format("Unit '%1%' already defined") % name);
00281     if (exists.second.Exists()) {
00282       message += " at "+exists.second.ToString();
00283     }
00284     messages->AddError(node->children[1].position, message);
00285     return false;
00286   }
00287   // --------------------------------------------------------------------------
00288   bool result = units->Add(name, right / left, node->children[1].position);
00289   if (result && is_print) {
00290         std::string message = str(boost::format("%1% %2% = %3%")
00291               % left
00292               % name
00293               % right);
00294        messages->AddInfo(node->position, message);
00295   }
00296   return result;
00297 }
00298 // ============================================================================
00299 static bool ConditionNode(gp::Node* node,
00300                 gp::Catalog* catalog, gp::Node** next) {
00301 // ----------------------------------------------------------------------------
00302   gp::PropertyName::ScopedPtr property_name;
00303   GetPropertyName(&node->children[0], property_name);
00304   // --------------------------------------------------------------------------
00305   bool is_defined = (NULL != catalog->Find(property_name->client(),
00306       property_name->property()));
00307   // --------------------------------------------------------------------------
00308   if ((is_defined && (node->children[1].type == gp::Node::kIfdef))
00309   || (!is_defined && (node->children[1].type == gp::Node::kIfndef))
00310   ) {
00311     *next = &node->children[1];
00312   }else if (node->children.size()>2){
00313     *next = &node->children[2];
00314   } else{
00315     *next = NULL;
00316   }
00317   return true;
00318 }
00319 // ============================================================================
00320 static bool Analyze(gp::Node* node,
00321     const std::string& search_path, gp::IncludedFiles* included,
00322     gp::Messages* messages, gp::Catalog* catalog, gp::Units* units,
00323     gp::PragmaOptions* pragma) {
00324 // ----------------------------------------------------------------------------
00325     bool result = true;
00326     bool local_result = true;
00327     bool skip_childs = true;
00328     gp::Node* next_root = node;
00329     // ------------------------------------------------------------------------
00330     switch (node->type) {
00331     // ------------------------------------------------------------------------
00332       case gp::Node::kRoot: {
00333         skip_childs = false;
00334         break;
00335       }
00336       // ----------------------------------------------------------------------
00337       case gp::Node::kInclude: {
00338         local_result = IncludeNode(node, search_path, included, messages);
00339         skip_childs = false;
00340         break;
00341       }
00342       // ----------------------------------------------------------------------
00343       case gp::Node::kUnits: {
00344         local_result = UnitsNode(node, search_path, included, messages);
00345         skip_childs = false;
00346         break;
00347       }
00348       // ----------------------------------------------------------------------
00349       case gp::Node::kAssign: {
00350         local_result = AssignNode(node, messages, catalog, units,
00351             pragma->is_print());
00352         break;
00353       }
00354       // ----------------------------------------------------------------------
00355       case gp::Node::kUnit: {
00356         local_result = UnitNode(node, messages, units, pragma->is_print());
00357         break;
00358       }
00359       // ----------------------------------------------------------------------
00360       case gp::Node::kCondition: {
00361         local_result = ConditionNode(node, catalog, &next_root);
00362         skip_childs = false;
00363         break;
00364       }
00365 
00366       case gp::Node::kPrintOptions: {
00367         pragma->setIsPrintOptions(true);
00368         break;
00369       }
00370 
00371       case gp::Node::kPrintOn : {
00372         pragma->setIsPrint(true);
00373         break;
00374       }
00375 
00376       case gp::Node::kPrintOff : {
00377         pragma->setIsPrint(false);
00378         break;
00379       }
00380 
00381       case gp::Node::kPrintTree : {
00382         pragma->setIsPrintTree(true);
00383         break;
00384       }
00385 
00386       case gp::Node::kDumpFile : {
00387         std::string file="";
00388         if(System::resolveEnv(node->value, file)) {
00389           pragma->setDumpFile(file);
00390         } else {
00391           pragma->setDumpFile(node->value);
00392         }
00393         break;
00394       }
00395       // ----------------------------------------------------------------------
00396       default: {
00397         break;
00398       }
00399     }
00400     if (result) result = local_result;
00401 
00402     if (!skip_childs && (next_root!=NULL)) {
00403       BOOST_FOREACH(gp::Node& child, next_root->children) {
00404         local_result =
00405             Analyze(&child, search_path, included, messages, catalog, units,
00406                 pragma);
00407         if (result) result = local_result;
00408       }
00409     }
00410     return result;
00411 }
00412 
00413 bool Unreference(gp::Catalog& catalog, gp::Messages* messages) {
00414   bool unreference_result = true;
00415   BOOST_FOREACH(gp::Catalog::value_type& client, catalog) {
00416     for (gp::Catalog::CatalogSet::mapped_type::iterator current
00417         = client.second.begin(); current != client.second.end();
00418         ++current) {
00419       if (current->IsReference()) {
00420         gp::PropertyValue& value = current->property_value();
00421         std::vector<std::string> names = value.Vector();
00422 
00423         gp::Property* property = catalog.Find(names[0], names[1]);
00424         if (NULL == property) {
00425           messages->AddError(value.position(),
00426               "Could not unreference " + current->ValueAsString());
00427           unreference_result = false;
00428         }else{
00429           value = property->property_value();
00430         }
00431       }
00432     }
00433   }
00434   return unreference_result;
00435 }
00436 
00437 // ============================================================================
00438 bool gp::ReadOptions(const std::string& filename,
00439         const std::string& search_path, Messages* messages, Catalog* catalog,
00440         Units* units, PragmaOptions* pragma, Node* root) {
00441   // Extract Path
00442   IncludedFiles included;
00443   bool result = Parse(filename, search_path, &included, messages, root);
00444   if (!result) return false;
00445 
00446   bool result1 = Analyze(root, search_path, &included, messages, catalog, units,
00447       pragma);
00448   bool result2 = Unreference(*catalog, messages);
00449   return result1 && result2;
00450 }
00451 
00452 // ============================================================================
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines

Generated at Fri Sep 2 2011 16:24:56 for Gaudi Framework, version v22r4 by Doxygen version 1.7.2 written by Dimitri van Heesch, © 1997-2004