| The Gaudi Framework v29r1 (5cd95fa2)

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