| # Gaudi Framework, version v25r0 |

Home |  | Generated: Mon Feb 17 2014

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

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