8 #include <boost/foreach.hpp>
9 #include <boost/lexical_cast.hpp>
10 #include <boost/format.hpp>
25 namespace gp = Gaudi::Parsers;
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);
34 node->value = include_root.value;
35 BOOST_FOREACH(
const gp::Node& child, include_root.children) {
36 node->children.push_back(child);
44 static bool UnitsNode(gp::Node* node,
45 const std::string& search_path,
46 gp::IncludedFiles* included, gp::Messages* messages) {
48 bool status =
gp::ParseUnits(node->position, node->value, search_path,
49 included, messages, &units_root);
51 node->value = units_root.value;
52 BOOST_FOREACH(
const gp::Node& child, units_root.children) {
53 node->children.push_back(child);
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,
68 std::string client=
"";
69 for(
unsigned int i=0;
i < (node->children.size() - 1);
i++) {
70 client += delim+node->children[
i].value;
73 property_name.reset(
new gp::PropertyName(client,
74 node->children[node->children.size() - 1].value, node->position));
78 static void GetPropertyValue(
const gp::Node* node,
79 gp::PropertyValue::ScopedPtr&
value, gp::Catalog* catalog,
83 case gp::Node::kReal: {
89 if (node->children.size() == 1) {
91 std::string unit_name = node->children[0].value;
92 double unit_value = 0;
93 if (units->Find(unit_name, unit_value)) {
95 double val = boost::lexical_cast<
double>(node->value);
97 boost::lexical_cast<std::string>(val * unit_value);
98 value.reset(
new gp::PropertyValue(store));
102 gp::PositionalPropertyValueException::CouldNotFindUnit(
103 node->children[0].position, unit_name);
106 value.reset(
new gp::PropertyValue(node->value));
111 case gp::Node::kString: {
112 value.reset(
new gp::PropertyValue(
'"'+node->value+
'"'));
116 case gp::Node::kBool: {
117 value.reset(
new gp::PropertyValue(node->value));
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());
128 value.reset(
new gp::PropertyValue(result));
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);
140 std::pair<std::string, std::string>(
142 vvalue->ToString()));
144 value.reset(
new gp::PropertyValue(result));
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()));
157 gp::PositionalPropertyValueException::CouldNotFindProperty(
158 node->position,property->ToString());
162 case gp::Node::kPropertyRef: {
163 gp::PropertyName::ScopedPtr property;
164 GetPropertyName(node, property);
167 reference.push_back(property->client());
168 reference.push_back(property->property());
170 value.reset(
new gp::PropertyValue(reference,property->position(),
183 static std::string SignString(gp::Node::NodeType
type) {
185 case gp::Node::kEqual : {
189 case gp::Node::kPlusEqual : {
193 case gp::Node::kMinusEqual : {
205 static bool AssignNode(
const gp::Node* node,
206 gp::Messages* messages, gp::Catalog* catalog, gp::Units* units,
209 gp::PropertyName::ScopedPtr property;
210 gp::PropertyValue::ScopedPtr
value;
212 GetPropertyName(&node->children[0], property);
214 GetPropertyValue(&node->children[2], value, catalog, units);
215 }
catch(
const gp::PositionalPropertyValueException& ex){
216 messages->AddError(ex.position(), ex.what());
220 gp::Property* exists = NULL;
221 bool reassign =
false;
223 if (NULL != (exists = catalog->Find(property->client(),
224 property->property()))) {
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() +
".";
239 }
else if (node->children[1].type == gp::Node::kPlusEqual) {
241 }
else if (node->children[1].type == gp::Node::kMinusEqual) {
244 }
catch(
const gp::PropertyValueException& ex) {
245 std::string message = ex.what();
246 if (exists->HasDefinedPosition()) {
247 message +=
" Previously defined at "+exists->DefinedPosition().
250 messages->AddError(node->position, message);
256 if ( (NULL == exists) || reassign) {
257 result = catalog->Add(
new gp::Property(*property, *value));
260 if (result && is_print) {
262 % property->FullName()
263 % SignString(node->children[1].type)
264 % value->ToString());
265 messages->AddInfo(node->position, message);
270 static bool UnitNode(
const gp::Node* node,
271 gp::Messages* messages, gp::Units* units,
bool is_print) {
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);
277 gp::Units::Container::mapped_type exists;
278 if (units->Find(name, exists)) {
279 std::string message =
281 if (exists.second.Exists()) {
282 message +=
" at "+exists.second.ToString();
284 messages->AddError(node->children[1].position, message);
288 bool result = units->Add(name, right / left, node->children[1].position);
289 if (result && is_print) {
294 messages->AddInfo(node->position, message);
299 static bool ConditionNode(gp::Node* node,
300 gp::Catalog* catalog, gp::Node** next) {
302 gp::PropertyName::ScopedPtr property_name;
303 GetPropertyName(&node->children[0], property_name);
305 bool is_defined = (NULL != catalog->Find(property_name->client(),
306 property_name->property()));
308 if ((is_defined && (node->children[1].type == gp::Node::kIfdef))
309 || (!is_defined && (node->children[1].type == gp::Node::kIfndef))
311 *next = &node->children[1];
312 }
else if (node->children.size()>2){
313 *next = &node->children[2];
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) {
326 bool local_result =
true;
327 bool skip_childs =
true;
328 gp::Node* next_root = node;
330 switch (node->type) {
332 case gp::Node::kRoot: {
337 case gp::Node::kInclude: {
338 local_result = IncludeNode(node, search_path, included, messages);
343 case gp::Node::kUnits: {
344 local_result = UnitsNode(node, search_path, included, messages);
349 case gp::Node::kAssign: {
350 local_result = AssignNode(node, messages, catalog, units,
355 case gp::Node::kUnit: {
356 local_result = UnitNode(node, messages, units, pragma->is_print());
360 case gp::Node::kCondition: {
361 local_result = ConditionNode(node, catalog, &next_root);
366 case gp::Node::kPrintOptions: {
367 pragma->setIsPrintOptions(
true);
371 case gp::Node::kPrintOn : {
372 pragma->setIsPrint(
true);
376 case gp::Node::kPrintOff : {
377 pragma->setIsPrint(
false);
381 case gp::Node::kPrintTree : {
382 pragma->setIsPrintTree(
true);
386 case gp::Node::kDumpFile : {
389 pragma->setDumpFile(file);
391 pragma->setDumpFile(node->value);
400 if (result) result = local_result;
402 if (!skip_childs && (next_root!=NULL)) {
403 BOOST_FOREACH(gp::Node& child, next_root->children) {
405 Analyze(&child, search_path, included, messages, catalog, units,
407 if (result) result = local_result;
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();
419 if (current->IsReference()) {
420 gp::PropertyValue& value = current->property_value();
421 std::vector<std::string>
names = value.Vector();
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;
429 value =
property->property_value();
434 return unreference_result;
443 bool result =
Parse(filename, search_path, &included, messages, root);
444 if (!result)
return false;
446 bool result1 = Analyze(root, search_path, &included, messages, catalog, units,
449 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.
bool Parse(const std::string &filename, const std::string &search_path, IncludedFiles *included, Messages *messages, Node *root)
bool Unreference(gp::Catalog &catalog, gp::Messages *messages)
TO * reference(FROM *from)