Gaudi Framework, version v23r2

Home   Generated: Thu Jun 28 2012

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           // INFO: we don't need this warning
00239           // messages->AddWarning(node->position, message);
00240         }else if (node->children[1].type == gp::Node::kPlusEqual) {
00241           *exists += *value;
00242         }else if (node->children[1].type == gp::Node::kMinusEqual) {
00243           *exists -= *value;
00244         }
00245       }catch(const gp::PropertyValueException& ex) {
00246         std::string message = ex.what();
00247         if (exists->HasDefinedPosition()) {
00248           message += " Previously defined at "+exists->DefinedPosition().
00249               ToString()+".";
00250         }
00251         messages->AddError(node->position, message);
00252         return false;
00253       }
00254     }
00255 // ----------------------------------------------------------------------------
00256     bool result = true;
00257     if ( (NULL == exists) || reassign) {
00258       result = catalog->Add(new gp::Property(*property, *value));
00259     }
00260 
00261     if (result && is_print) { /*;%|72t|%2% %3%*/
00262       std::string message = str(boost::format("%1% %2% %3%")
00263             % property->FullName()
00264             % SignString(node->children[1].type)
00265             % value->ToString());
00266       messages->AddInfo(node->position, message);
00267     }
00268     return result;
00269 }
00270 // ============================================================================
00271 static bool UnitNode(const gp::Node* node,
00272         gp::Messages* messages, gp::Units* units, bool is_print) {
00273   // --------------------------------------------------------------------------
00274   double left  = boost::lexical_cast<double>(node->children[0].value);
00275   std::string name  = node->children[1].value;
00276   double right  = boost::lexical_cast<double>(node->children[2].value);
00277   // --------------------------------------------------------------------------
00278   gp::Units::Container::mapped_type exists;
00279   if (units->Find(name, exists)) {
00280     std::string message =
00281         str(boost::format("Unit '%1%' already defined") % name);
00282     if (exists.second.Exists()) {
00283       message += " at "+exists.second.ToString();
00284     }
00285     messages->AddError(node->children[1].position, message);
00286     return false;
00287   }
00288   // --------------------------------------------------------------------------
00289   bool result = units->Add(name, right / left, node->children[1].position);
00290   if (result && is_print) {
00291         std::string message = str(boost::format("%1% %2% = %3%")
00292               % left
00293               % name
00294               % right);
00295        messages->AddInfo(node->position, message);
00296   }
00297   return result;
00298 }
00299 // ============================================================================
00300 static bool ConditionNode(gp::Node* node,
00301                 gp::Catalog* catalog, gp::Node** next) {
00302 // ----------------------------------------------------------------------------
00303   gp::PropertyName::ScopedPtr property_name;
00304   GetPropertyName(&node->children[0], property_name);
00305   // --------------------------------------------------------------------------
00306   bool is_defined = (NULL != catalog->Find(property_name->client(),
00307       property_name->property()));
00308   // --------------------------------------------------------------------------
00309   if ((is_defined && (node->children[1].type == gp::Node::kIfdef))
00310   || (!is_defined && (node->children[1].type == gp::Node::kIfndef))
00311   ) {
00312     *next = &node->children[1];
00313   }else if (node->children.size()>2){
00314     *next = &node->children[2];
00315   } else{
00316     *next = NULL;
00317   }
00318   return true;
00319 }
00320 // ============================================================================
00321 static bool Analyze(gp::Node* node,
00322     const std::string& search_path, gp::IncludedFiles* included,
00323     gp::Messages* messages, gp::Catalog* catalog, gp::Units* units,
00324     gp::PragmaOptions* pragma) {
00325 // ----------------------------------------------------------------------------
00326     bool result = true;
00327     bool local_result = true;
00328     bool skip_childs = true;
00329     gp::Node* next_root = node;
00330     // ------------------------------------------------------------------------
00331     switch (node->type) {
00332     // ------------------------------------------------------------------------
00333       case gp::Node::kRoot: {
00334         skip_childs = false;
00335         break;
00336       }
00337       // ----------------------------------------------------------------------
00338       case gp::Node::kInclude: {
00339         local_result = IncludeNode(node, search_path, included, messages);
00340         skip_childs = false;
00341         break;
00342       }
00343       // ----------------------------------------------------------------------
00344       case gp::Node::kUnits: {
00345         local_result = UnitsNode(node, search_path, included, messages);
00346         skip_childs = false;
00347         break;
00348       }
00349       // ----------------------------------------------------------------------
00350       case gp::Node::kAssign: {
00351         local_result = AssignNode(node, messages, catalog, units,
00352             pragma->is_print());
00353         break;
00354       }
00355       // ----------------------------------------------------------------------
00356       case gp::Node::kUnit: {
00357         local_result = UnitNode(node, messages, units, pragma->is_print());
00358         break;
00359       }
00360       // ----------------------------------------------------------------------
00361       case gp::Node::kCondition: {
00362         local_result = ConditionNode(node, catalog, &next_root);
00363         skip_childs = false;
00364         break;
00365       }
00366 
00367       case gp::Node::kPrintOptions: {
00368         pragma->setIsPrintOptions(true);
00369         break;
00370       }
00371 
00372       case gp::Node::kPrintOn : {
00373         pragma->setIsPrint(true);
00374         break;
00375       }
00376 
00377       case gp::Node::kPrintOff : {
00378         pragma->setIsPrint(false);
00379         break;
00380       }
00381 
00382       case gp::Node::kPrintTree : {
00383         pragma->setIsPrintTree(true);
00384         break;
00385       }
00386 
00387       case gp::Node::kDumpFile : {
00388         std::string file="";
00389         if(System::resolveEnv(node->value, file)) {
00390           pragma->setDumpFile(file);
00391         } else {
00392           pragma->setDumpFile(node->value);
00393         }
00394         break;
00395       }
00396       // ----------------------------------------------------------------------
00397       default: {
00398         break;
00399       }
00400     }
00401     if (result) result = local_result;
00402 
00403     if (!skip_childs && (next_root!=NULL)) {
00404       BOOST_FOREACH(gp::Node& child, next_root->children) {
00405         local_result =
00406             Analyze(&child, search_path, included, messages, catalog, units,
00407                 pragma);
00408         if (result) result = local_result;
00409       }
00410     }
00411     return result;
00412 }
00413 
00414 bool Unreference(gp::Catalog& catalog, gp::Messages* messages) {
00415   bool unreference_result = true;
00416   BOOST_FOREACH(gp::Catalog::value_type& client, catalog) {
00417     for (gp::Catalog::CatalogSet::mapped_type::iterator current
00418         = client.second.begin(); current != client.second.end();
00419         ++current) {
00420       if (current->IsReference()) {
00421         gp::PropertyValue& value = current->property_value();
00422         std::vector<std::string> names = value.Vector();
00423 
00424         gp::Property* property = catalog.Find(names[0], names[1]);
00425         if (NULL == property) {
00426           messages->AddError(value.position(),
00427               "Could not unreference " + current->ValueAsString());
00428           unreference_result = false;
00429         }else{
00430           value = property->property_value();
00431         }
00432       }
00433     }
00434   }
00435   return unreference_result;
00436 }
00437 
00438 // ============================================================================
00439 bool gp::ReadOptions(const std::string& filename,
00440         const std::string& search_path, Messages* messages, Catalog* catalog,
00441         Units* units, PragmaOptions* pragma, Node* root) {
00442   // Extract Path
00443   IncludedFiles included;
00444   bool result = Parse(filename, search_path, &included, messages, root);
00445   if (!result) return false;
00446 
00447   bool result1 = Analyze(root, search_path, &included, messages, catalog, units,
00448       pragma);
00449   bool result2 = Unreference(*catalog, messages);
00450   return result1 && result2;
00451 }
00452 
00453 // ============================================================================
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines

Generated at Thu Jun 28 2012 23:27:17 for Gaudi Framework, version v23r2 by Doxygen version 1.7.2 written by Dimitri van Heesch, © 1997-2004