22 #include <fmt/format.h> 28 static bool IncludeNode( gp::Node* node,
const std::string& search_path, gp::IncludedFiles* included,
29 gp::Messages* messages ) {
30 gp::Node include_root;
31 bool status =
gp::Parse( node->position, node->value, search_path, included, messages, &include_root );
32 if ( !status )
return false;
33 node->value = include_root.value;
34 node->children.reserve( node->children.size() + include_root.children.size() );
40 static bool UnitsNode( gp::Node* node,
const std::string& search_path, gp::IncludedFiles* included,
41 gp::Messages* messages ) {
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;
46 node->children.reserve( node->children.size() + units_root.children.size() );
52 if ( node->children.size() == 1 ) {
53 return std::make_unique<gp::PropertyName>( node->children[0].value, node->position );
57 for (
unsigned int i = 0; i < ( node->children.size() - 1 ); ++i ) {
58 client += delim + node->children[i].value;
61 return std::make_unique<gp::PropertyName>( client, node->children[node->children.size() - 1].value, node->position );
67 switch ( node->type ) {
69 case gp::Node::kReal: {
75 if ( node->children.size() == 1 ) {
78 double unit_value = 0;
79 if ( units->Find( unit_name, unit_value ) ) {
82 value = std::make_unique<gp::PropertyValue>(
std::to_string( val * unit_value ) );
85 throw gp::PositionalPropertyValueException::CouldNotFindUnit( node->children[0].position, unit_name );
88 value = std::make_unique<gp::PropertyValue>( node->value );
93 case gp::Node::kString: {
95 ss << std::quoted( node->value );
96 value = std::make_unique<gp::PropertyValue>( ss.
str() );
100 case gp::Node::kBool: {
101 value = std::make_unique<gp::PropertyValue>( node->value );
105 case gp::Node::kVector: {
107 result.
reserve( node->children.size() );
109 [&](
const gp::Node& child ) { return GetPropertyValue( &child, catalog, units )->ToString(); } );
110 value = std::make_unique<gp::PropertyValue>(
std::move( result ) );
114 case gp::Node::kMap: {
116 for (
const auto& child : node->children ) {
117 auto kvalue = GetPropertyValue( &child.children[0], catalog, units );
118 auto vvalue = GetPropertyValue( &child.children[1], catalog, units );
119 result.
emplace( kvalue->ToString(), vvalue->ToString() );
121 value = std::make_unique<gp::PropertyValue>(
std::move( result ) );
125 case gp::Node::kProperty: {
126 auto property = GetPropertyName( node );
127 gp::Property* exists = catalog->Find( property->client(),
property->property() );
129 value = std::make_unique<gp::PropertyValue>( exists->property_value() );
131 throw gp::PositionalPropertyValueException::CouldNotFindProperty( node->position, property->ToString() );
135 case gp::Node::kPropertyRef: {
136 auto property = GetPropertyName( node );
139 reference.
push_back( property->client() );
140 reference.
push_back( property->property() );
142 value = std::make_unique<gp::PropertyValue>(
std::move( reference ), property->position(), true );
157 case gp::Node::kEqual: {
161 case gp::Node::kPlusEqual: {
165 case gp::Node::kMinusEqual: {
176 static bool AssignNode(
const gp::Node* node, gp::Messages* messages, gp::Catalog* catalog, gp::Units* units,
181 auto property = GetPropertyName( &node->children[0] );
183 value = GetPropertyValue( &node->children[2], catalog, units );
184 }
catch (
const gp::PositionalPropertyValueException& ex ) {
185 messages->AddError( ex.position(), ex.what() );
189 bool reassign =
false;
190 gp::Property* exists = catalog->Find( property->client(),
property->property() );
197 if ( node->children[1].type == gp::Node::kEqual ) {
200 if ( exists->HasDefinedPosition() ) {
201 message +=
fmt::format(
" Previously defined at {}.", exists->DefinedPosition().ToString() );
206 }
else if ( node->children[1].type == gp::Node::kPlusEqual ) {
208 }
else if ( node->children[1].type == gp::Node::kMinusEqual ) {
211 }
catch (
const gp::PropertyValueException& ex ) {
213 if ( exists->HasDefinedPosition() ) {
214 message +=
fmt::format(
" Previously defined at {}.", exists->DefinedPosition().ToString() );
216 messages->AddError( node->position, message );
222 if ( !exists || reassign ) { result = catalog->Add(
new gp::Property( *property, *value ) ); }
224 if ( result && is_print ) {
226 fmt::format(
"{} {} {}", property->FullName(), SignString( node->children[1].type ), value->ToString() );
227 messages->AddInfo( node->position, message );
232 static bool UnitNode(
const gp::Node* node, gp::Messages* messages, gp::Units* units,
bool is_print ) {
238 gp::Units::Container::mapped_type exists;
239 if ( units->Find(
name, exists ) ) {
241 if ( exists.second.Exists() ) { message +=
" at " + exists.second.ToString(); }
242 messages->AddError( node->children[1].position, message );
246 bool result = units->Add(
name, right / left, node->children[1].position );
247 if ( result && is_print ) {
249 messages->AddInfo( node->position, message );
254 static bool ConditionNode( gp::Node* node, gp::Catalog* catalog, gp::Node** next ) {
256 auto property_name = GetPropertyName( &node->children[0] );
258 bool is_defined = (
nullptr != catalog->Find( property_name->client(), property_name->property() ) );
260 if ( ( is_defined && ( node->children[1].type == gp::Node::kIfdef ) ) ||
261 ( !is_defined && ( node->children[1].type == gp::Node::kIfndef ) ) ) {
262 *
next = &node->children[1];
263 }
else if ( node->children.size() > 2 ) {
264 *
next = &node->children[2];
271 static bool Analyze( gp::Node* node,
const std::string& search_path, gp::IncludedFiles* included,
272 gp::Messages* messages, gp::Catalog* catalog, gp::Units* units, gp::PragmaOptions* pragma ) {
275 bool local_result =
true;
276 bool skip_childs =
true;
277 gp::Node* next_root = node;
279 switch ( node->type ) {
281 case gp::Node::kRoot: {
286 case gp::Node::kInclude: {
287 local_result = IncludeNode( node, search_path, included, messages );
292 case gp::Node::kUnits: {
293 local_result = UnitsNode( node, search_path, included, messages );
298 case gp::Node::kAssign: {
299 local_result = AssignNode( node, messages, catalog, units, pragma->is_print() );
303 case gp::Node::kUnit: {
304 local_result = UnitNode( node, messages, units, pragma->is_print() );
308 case gp::Node::kCondition: {
309 local_result = ConditionNode( node, catalog, &next_root );
314 case gp::Node::kPrintOptions: {
315 pragma->setIsPrintOptions(
true );
319 case gp::Node::kPrintOn: {
320 pragma->setIsPrint(
true );
324 case gp::Node::kPrintOff: {
325 pragma->setIsPrint(
false );
329 case gp::Node::kPrintTree: {
330 pragma->setIsPrintTree(
true );
334 case gp::Node::kDumpFile: {
337 pragma->setDumpFile( file );
339 pragma->setDumpFile( node->value );
348 if ( result ) result = local_result;
350 if ( !skip_childs && next_root ) {
351 for (
auto& child : next_root->children ) {
352 local_result = Analyze( &child, search_path, included, messages, catalog, units, pragma );
353 if ( result ) result = local_result;
359 bool Unreference( gp::Catalog& catalog, gp::Messages* messages ) {
360 bool unreference_result =
true;
361 for (
auto& client : catalog ) {
362 for (
auto& current : client.second ) {
363 if ( current.IsReference() ) {
364 gp::PropertyValue& value = current.property_value();
366 gp::Property*
property = catalog.Find( names[0], names[1] );
368 messages->AddError( value.position(),
"Could not unreference " + current.ValueAsString() );
369 unreference_result =
false;
371 value =
property->property_value();
376 return unreference_result;
385 if ( !result )
return false;
387 bool result1 = Analyze(
root, search_path, &included, messages, catalog, units, pragma );
389 return result1 && result2;
GAUDI_API std::string format(const char *,...)
MsgStream format utility "a la sprintf(...)".
GAUDI_API StatusCode resolveEnv(const std::string &var, std::string &res, int recusions=124)
bool ParseUnits(const Position &from, const std::string &filename, const std::string &search_path, IncludedFiles *included, Messages *messages, Node *root)
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.
Gaudi::Details::PropertyBase Property
\fixme backward compatibility hack for old Property base class
bool Parse(const std::string &filename, const std::string &search_path, IncludedFiles *included, Messages *messages, Node *root)
T back_inserter(T... args)
bool Unreference(gp::Catalog &catalog, gp::Messages *messages)