Gaudi Framework, version v23r6

Home   Generated: Wed Jan 30 2013
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
Analyzer.cpp
Go to the documentation of this file.
1 // ============================================================================
2 // STD:
3 // ============================================================================
4 #include <iostream>
5 // ============================================================================
6 // BOOST:
7 // ============================================================================
8 #include <boost/foreach.hpp>
9 #include <boost/lexical_cast.hpp>
10 #include <boost/format.hpp>
11 #include <boost/shared_ptr.hpp>
12 // ============================================================================
13 #include "Analyzer.h"
14 #include "Parser.h"
15 #include "Messages.h"
16 #include "Catalog.h"
17 #include "Units.h"
18 #include "PragmaOptions.h"
19 #include "Node.h"
20 #include "IncludedFiles.h"
21 #include "PropertyName.h"
22 #include "PropertyValue.h"
23 // ============================================================================
25 // ============================================================================
26 namespace gp = Gaudi::Parsers;
27 // ============================================================================
28 static bool IncludeNode(gp::Node* node,
29  const std::string& search_path,
30  gp::IncludedFiles* included, gp::Messages* messages) {
31  gp::Node include_root;
32  bool status = gp::Parse(node->position, node->value, search_path, included,
33  messages, &include_root);
34  if (status) {
35  node->value = include_root.value; // Save absolute file path
36  BOOST_FOREACH(const gp::Node& child, include_root.children) {
37  node->children.push_back(child);
38  }
39  } else {
40  return false;
41  }
42  return true;
43 }
44 // ============================================================================
45 static bool UnitsNode(gp::Node* node,
46  const std::string& search_path,
47  gp::IncludedFiles* included, gp::Messages* messages) {
48  gp::Node units_root;
49  bool status = gp::ParseUnits(node->position, node->value, search_path,
50  included, messages, &units_root);
51  if (status) {
52  node->value = units_root.value; // Save absolute file path
53  BOOST_FOREACH(const gp::Node& child, units_root.children) {
54  node->children.push_back(child);
55  }
56  } else {
57  return false;
58  }
59  return true;
60 }
61 // ============================================================================
62 static void GetPropertyName(const gp::Node* node,
63  gp::PropertyName::ScopedPtr& property_name) {
64  if (node->children.size() == 1) {
65  property_name.reset(new gp::PropertyName(node->children[0].value,
66  node->position));
67  }else {
68  std::string delim="";
69  std::string client="";
70  for(unsigned int i=0; i < (node->children.size() - 1); i++) {
71  client += delim+node->children[i].value;
72  delim = '.';
73  }
74  property_name.reset(new gp::PropertyName(client,
75  node->children[node->children.size() - 1].value, node->position));
76  }
77 }
78 // ============================================================================
79 static void GetPropertyValue(const gp::Node* node,
80  gp::PropertyValue::ScopedPtr& value, gp::Catalog* catalog,
81  gp::Units* units) {
82  switch (node->type) {
83  // ------------------------------------------------------------------------
84  case gp::Node::kReal: {
85  // Example:
86  // <real value="10" line="3" column="7">
87  // <identifier value="m" line="3" column="10"/>
88  // </real>
89  //
90  if (node->children.size() == 1) {
91  // Unit is presented
92  std::string unit_name = node->children[0].value;
93  double unit_value = 0;
94  if (units->Find(unit_name, unit_value)) {
95  // We have found a unit
96  double val = boost::lexical_cast<double>(node->value);
97  std::string store =
98  boost::lexical_cast<std::string>(val * unit_value);
99  value.reset(new gp::PropertyValue(store));
100  }else {
101  // Unit not found
102  throw
103  gp::PositionalPropertyValueException::CouldNotFindUnit(
104  node->children[0].position, unit_name);
105  }
106  }else {
107  value.reset(new gp::PropertyValue(node->value));
108  }
109  break;
110  }
111  // ------------------------------------------------------------------------
112  case gp::Node::kString: {
113  value.reset(new gp::PropertyValue('"'+node->value+'"'));
114  break;
115  }
116  // ------------------------------------------------------------------------
117  case gp::Node::kBool: {
118  value.reset(new gp::PropertyValue(node->value));
119  break;
120  }
121  // ------------------------------------------------------------------------
122  case gp::Node::kVector: {
124  BOOST_FOREACH(const gp::Node& child, node->children) {
125  gp::PropertyValue::ScopedPtr vvalue;
126  GetPropertyValue(&child, vvalue, catalog, units);
127  result.push_back(vvalue->ToString());
128  }
129  value.reset(new gp::PropertyValue(result));
130  break;
131  }
132  // ------------------------------------------------------------------------
133  case gp::Node::kMap: {
135  BOOST_FOREACH(const gp::Node& child, node->children) {
136  gp::PropertyValue::ScopedPtr kvalue;
137  gp::PropertyValue::ScopedPtr vvalue;
138  GetPropertyValue(&child.children[0], kvalue, catalog, units);
139  GetPropertyValue(&child.children[1], vvalue, catalog, units);
140  result.insert(
142  kvalue->ToString(),
143  vvalue->ToString()));
144  }
145  value.reset(new gp::PropertyValue(result));
146  break;
147  }
148  // ------------------------------------------------------------------------
149  case gp::Node::kProperty: {
150  gp::PropertyName::ScopedPtr property;
151  GetPropertyName(node, property);
152  gp::Property* exists = NULL;
153  if (NULL != (exists = catalog->Find(property->client(),
154  property->property()))) {
155  value.reset(new gp::PropertyValue(exists->property_value()));
156  }else {
157  throw
158  gp::PositionalPropertyValueException::CouldNotFindProperty(
159  node->position,property->ToString());
160  }
161  break;
162  }
163  case gp::Node::kPropertyRef: {
164  gp::PropertyName::ScopedPtr property;
165  GetPropertyName(node, property);
166  // Save a property reference as vector [clientname, property]
168  reference.push_back(property->client());
169  reference.push_back(property->property());
170 
171  value.reset(new gp::PropertyValue(reference,property->position(),
172  true));
173  break;
174  }
175  // ------------------------------------------------------------------------
176  default: {
177  assert(false);
178  break;
179  }
180  }
181 }
182 
183 // ============================================================================
184 static std::string SignString(gp::Node::NodeType type) {
185  switch (type) {
186  case gp::Node::kEqual : {
187  return "=";
188  }
189 
190  case gp::Node::kPlusEqual : {
191  return "+=";
192  }
193 
194  case gp::Node::kMinusEqual : {
195  return "-=";
196  }
197  default: {
198  assert(false);
199  break;
200  }
201  }
202  return "unknown";
203 
204 }
205 // ============================================================================
206 static bool AssignNode(const gp::Node* node,
207  gp::Messages* messages, gp::Catalog* catalog, gp::Units* units,
208  bool is_print) {
209 // ----------------------------------------------------------------------------
210  gp::PropertyName::ScopedPtr property;
211  gp::PropertyValue::ScopedPtr value;
212 // ----------------------------------------------------------------------------
213  GetPropertyName(&node->children[0], property);
214  try {
215  GetPropertyValue(&node->children[2], value, catalog, units);
216  }catch(const gp::PositionalPropertyValueException& ex){
217  messages->AddError(ex.position(), ex.what());
218  return false;
219  }
220  // ------------------------------------------------------------------------
221  gp::Property* exists = NULL;
222  bool reassign = false;
223 // ----------------------------------------------------------------------------
224  if (NULL != (exists = catalog->Find(property->client(),
225  property->property()))) {
226  // ----------------------------------------------------------------------
227  // If property already exists:
228  // ----------------------------------------------------------------------
229  try {
230  if (node->children[1].type == gp::Node::kEqual) {
231  std::string message = str(boost::format("Reassignment of option '%1%' .")
232  % property->FullName());
233  if (exists->HasDefinedPosition()) {
234  message += " Previously defined at " +
235  exists->DefinedPosition().ToString() + ".";
236  }
237  reassign = true;
238  // INFO: we don't need this warning
239  // messages->AddWarning(node->position, message);
240  }else if (node->children[1].type == gp::Node::kPlusEqual) {
241  *exists += *value;
242  }else if (node->children[1].type == gp::Node::kMinusEqual) {
243  *exists -= *value;
244  }
245  }catch(const gp::PropertyValueException& ex) {
246  std::string message = ex.what();
247  if (exists->HasDefinedPosition()) {
248  message += " Previously defined at "+exists->DefinedPosition().
249  ToString()+".";
250  }
251  messages->AddError(node->position, message);
252  return false;
253  }
254  }
255 // ----------------------------------------------------------------------------
256  bool result = true;
257  if ( (NULL == exists) || reassign) {
258  result = catalog->Add(new gp::Property(*property, *value));
259  }
260 
261  if (result && is_print) { /*;%|72t|%2% %3%*/
262  std::string message = str(boost::format("%1% %2% %3%")
263  % property->FullName()
264  % SignString(node->children[1].type)
265  % value->ToString());
266  messages->AddInfo(node->position, message);
267  }
268  return result;
269 }
270 // ============================================================================
271 static bool UnitNode(const gp::Node* node,
272  gp::Messages* messages, gp::Units* units, bool is_print) {
273  // --------------------------------------------------------------------------
274  double left = boost::lexical_cast<double>(node->children[0].value);
275  std::string name = node->children[1].value;
276  double right = boost::lexical_cast<double>(node->children[2].value);
277  // --------------------------------------------------------------------------
278  gp::Units::Container::mapped_type exists;
279  if (units->Find(name, exists)) {
280  std::string message =
281  str(boost::format("Unit '%1%' already defined") % name);
282  if (exists.second.Exists()) {
283  message += " at "+exists.second.ToString();
284  }
285  messages->AddError(node->children[1].position, message);
286  return false;
287  }
288  // --------------------------------------------------------------------------
289  bool result = units->Add(name, right / left, node->children[1].position);
290  if (result && is_print) {
291  std::string message = str(boost::format("%1% %2% = %3%")
292  % left
293  % name
294  % right);
295  messages->AddInfo(node->position, message);
296  }
297  return result;
298 }
299 // ============================================================================
300 static bool ConditionNode(gp::Node* node,
301  gp::Catalog* catalog, gp::Node** next) {
302 // ----------------------------------------------------------------------------
303  gp::PropertyName::ScopedPtr property_name;
304  GetPropertyName(&node->children[0], property_name);
305  // --------------------------------------------------------------------------
306  bool is_defined = (NULL != catalog->Find(property_name->client(),
307  property_name->property()));
308  // --------------------------------------------------------------------------
309  if ((is_defined && (node->children[1].type == gp::Node::kIfdef))
310  || (!is_defined && (node->children[1].type == gp::Node::kIfndef))
311  ) {
312  *next = &node->children[1];
313  }else if (node->children.size()>2){
314  *next = &node->children[2];
315  } else{
316  *next = NULL;
317  }
318  return true;
319 }
320 // ============================================================================
321 static bool Analyze(gp::Node* node,
322  const std::string& search_path, gp::IncludedFiles* included,
323  gp::Messages* messages, gp::Catalog* catalog, gp::Units* units,
324  gp::PragmaOptions* pragma) {
325 // ----------------------------------------------------------------------------
326  bool result = true;
327  bool local_result = true;
328  bool skip_childs = true;
329  gp::Node* next_root = node;
330  // ------------------------------------------------------------------------
331  switch (node->type) {
332  // ------------------------------------------------------------------------
333  case gp::Node::kRoot: {
334  skip_childs = false;
335  break;
336  }
337  // ----------------------------------------------------------------------
338  case gp::Node::kInclude: {
339  local_result = IncludeNode(node, search_path, included, messages);
340  skip_childs = false;
341  break;
342  }
343  // ----------------------------------------------------------------------
344  case gp::Node::kUnits: {
345  local_result = UnitsNode(node, search_path, included, messages);
346  skip_childs = false;
347  break;
348  }
349  // ----------------------------------------------------------------------
350  case gp::Node::kAssign: {
351  local_result = AssignNode(node, messages, catalog, units,
352  pragma->is_print());
353  break;
354  }
355  // ----------------------------------------------------------------------
356  case gp::Node::kUnit: {
357  local_result = UnitNode(node, messages, units, pragma->is_print());
358  break;
359  }
360  // ----------------------------------------------------------------------
361  case gp::Node::kCondition: {
362  local_result = ConditionNode(node, catalog, &next_root);
363  skip_childs = false;
364  break;
365  }
366 
367  case gp::Node::kPrintOptions: {
368  pragma->setIsPrintOptions(true);
369  break;
370  }
371 
372  case gp::Node::kPrintOn : {
373  pragma->setIsPrint(true);
374  break;
375  }
376 
377  case gp::Node::kPrintOff : {
378  pragma->setIsPrint(false);
379  break;
380  }
381 
382  case gp::Node::kPrintTree : {
383  pragma->setIsPrintTree(true);
384  break;
385  }
386 
387  case gp::Node::kDumpFile : {
388  std::string file="";
389  if(System::resolveEnv(node->value, file)) {
390  pragma->setDumpFile(file);
391  } else {
392  pragma->setDumpFile(node->value);
393  }
394  break;
395  }
396  // ----------------------------------------------------------------------
397  default: {
398  break;
399  }
400  }
401  if (result) result = local_result;
402 
403  if (!skip_childs && (next_root!=NULL)) {
404  BOOST_FOREACH(gp::Node& child, next_root->children) {
405  local_result =
406  Analyze(&child, search_path, included, messages, catalog, units,
407  pragma);
408  if (result) result = local_result;
409  }
410  }
411  return result;
412 }
413 
414 bool Unreference(gp::Catalog& catalog, gp::Messages* messages) {
415  bool unreference_result = true;
416  BOOST_FOREACH(gp::Catalog::value_type& client, catalog) {
417  for (gp::Catalog::CatalogSet::mapped_type::iterator current
418  = client.second.begin(); current != client.second.end();
419  ++current) {
420  if (current->IsReference()) {
421  gp::PropertyValue& value = current->property_value();
422  std::vector<std::string> names = value.Vector();
423 
424  gp::Property* property = catalog.Find(names[0], names[1]);
425  if (NULL == property) {
426  messages->AddError(value.position(),
427  "Could not unreference " + current->ValueAsString());
428  unreference_result = false;
429  }else{
430  value = property->property_value();
431  }
432  }
433  }
434  }
435  return unreference_result;
436 }
437 
438 // ============================================================================
439 bool gp::ReadOptions(const std::string& filename,
440  const std::string& search_path, Messages* messages, Catalog* catalog,
441  Units* units, PragmaOptions* pragma, Node* root) {
442  // Extract Path
443  IncludedFiles included;
444  bool result = Parse(filename, search_path, &included, messages, root);
445  if (!result) return false;
446 
447  bool result1 = Analyze(root, search_path, &included, messages, catalog, units,
448  pragma);
449  bool result2 = Unreference(*catalog, messages);
450  return result1 && result2;
451 }
452 
453 // ============================================================================

Generated at Wed Jan 30 2013 17:13:38 for Gaudi Framework, version v23r6 by Doxygen version 1.8.2 written by Dimitri van Heesch, © 1997-2004