| The Gaudi Framework v28r2p1 (f1a77ff4)

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

- File List
- File Members

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