6 #include <flame/config.h>
7 #include <flame/util.h>
9 #include "glps_parser.h"
17 ,implicit_values(O.implicit_values)
25 implicit_values = O.implicit_values;
33 if(!values.unique()) {
34 Config::values_pointer U(
new values_t(*values));
42 values_t::const_iterator it=values->find(name);
43 if(it!=values->end()) {
48 it = implicit_values->find(name);
49 if(it!=implicit_values->end()) {
60 values_t::const_iterator it=values->find(name);
61 if(it!=values->end())
return it->second;
63 it = implicit_values->find(name);
64 if(it!=implicit_values->end())
return it->second;
66 throw key_error(SB()<<
"Missing parameter '"<<name<<
"'");
72 (*values)[name] = val;
80 values_t::iterator it = values->find(name);
81 if(it!=values->end()) {
86 std::pair<values_t::iterator, bool> ret = values->insert(std::make_pair(name,
value_t()));
88 ret.first->second.swap(val);
96 ret.implicit_values = implicit_values;
97 }
else if(!implicit_values || implicit_values->empty()) {
98 ret.implicit_values = values;
100 values_pointer ptr(
new values_t(*values));
101 ptr->insert(implicit_values->begin(),
102 implicit_values->end());
104 ret.implicit_values = ptr;
109 void Config::push_scope()
112 implicit_values = values;
113 values.reset(
new values_t);
116 void Config::flatten()
118 if(implicit_values) {
119 values->insert(implicit_values->begin(),
120 implicit_values->end());
121 implicit_values.reset();
127 struct show_value :
public boost::static_visitor<void>
131 const std::string& name;
132 show_value(std::ostream& s,
const std::string& n,
unsigned ind=0)
133 : indent(ind), strm(s), name(n) {}
135 void operator()(
double v)
const
140 strm << name <<
" = " << v <<
"\n";
143 void operator()(
const std::string& v)
const
146 strm << name <<
" = \"" << v <<
"\"\n";
149 void operator()(
const std::vector<double>& v)
const
152 strm << name <<
" = [";
153 for(
size_t i=0, N=v.size(); i<N; i++)
162 void operator()(
const Config::vector_t& v)
const
165 strm << name <<
" = [\n";
166 for(
size_t i=0, N=v.size(); i<N; i++)
169 strm <<
"[" << i <<
"] = {\n";
170 v[i].show(strm, indent+4);
178 void doindent(
unsigned extra=0)
const
180 unsigned i=indent+extra;
190 for(Config::values_t::const_iterator it=values->begin(),
end=values->end();
193 boost::apply_visitor(show_value(strm, it->first, indent), it->second);
199 struct store_ctxt_var :
public boost::static_visitor<void>
201 const std::string& name;
203 store_ctxt_var(parse_context& c,
const std::string& n)
206 #define VISIT(TYPE, E) \
207 void operator()(TYPE v) const { \
208 ctxt.vars.push_back(parse_var(name.c_str(), expr_t(E, v))); \
209 ctxt.var_idx[name] = ctxt.vars.size()-1; \
211 VISIT(
double, glps_expr_number)
212 VISIT(const
std::
string&, glps_expr_string)
213 VISIT(const
std::vector<
double>&, glps_expr_vector)
215 void operator()(
const Config::vector_t&)
const
221 void assign_expr_to_Config(
Config& conf,
const std::string& name,
const expr_t& expr)
225 case glps_expr_number:
226 conf.
set<
double>(name, boost::get<double>(expr.value));
228 case glps_expr_string:
229 conf.
set<std::string>(name, boost::get<std::string>(expr.value));
231 case glps_expr_vector:
232 conf.
set<std::vector<double> >(name, boost::get<std::vector<double> >(expr.value));
234 case glps_expr_config: {
235 boost::shared_ptr<Config> pconf(boost::get<boost::shared_ptr<Config> >(expr.value));
236 std::vector<Config> cvect;
238 cvect.push_back(*pconf);
239 conf.set<std::vector<Config> >(name, cvect);
243 throw std::logic_error(
"Context contained unresolved/illegal variable");
248 struct GLPSParser::Pvt {
249 typedef Config::values_t values_t;
251 std::ostream *printer;
253 Pvt() :printer(&
std::cerr) {}
255 void fill_vars(parse_context& ctxt)
257 for(values_t::const_iterator it=vars.begin(), end=vars.end(); it!=end; ++it)
260 boost::apply_visitor(store_ctxt_var(ctxt, it->first), it->second);
264 Config* fill_context(parse_context& ctxt)
266 std::auto_ptr<Config> ret(
new Config);
267 ret->reserve(ctxt.vars.size()+2);
270 for(parse_context::vars_t::iterator it=ctxt.vars.begin(), end=ctxt.vars.end();
273 assign_expr_to_Config(*ret, it->name, it->expr);
276 if(ctxt.line.size()==0)
277 throw std::runtime_error(
"No beamlines defined by this file");
279 parse_line *line = NULL;
283 parse_context::map_idx_t::const_iterator it=ctxt.element_idx.find(
"USE");
284 if(it!=ctxt.element_idx.end()) {
285 parse_element &elem = ctxt.elements[it->second];
286 parse_context::map_idx_t::const_iterator lit = ctxt.line_idx.find(elem.etype);
288 if(lit!=ctxt.line_idx.end()) {
289 line = &ctxt.line[lit->second];
291 std::ostringstream strm;
292 strm<<
"\"USE: "<<elem.etype<<
";\" references undefined beamline";
293 throw std::runtime_error(strm.str());
297 line = &ctxt.line.back();
303 if(line->names.size()==0) {
304 std::ostringstream strm;
305 strm<<
"Beamline '"<<line->label<<
"' has no elements";
306 throw std::runtime_error(strm.str());
309 Config::vector_t elements;
310 elements.resize(line->names.size());
314 for(strlist_t::list_t::const_iterator it=line->names.begin(), end=line->names.end();
317 Config next(ret->new_scope());
318 const parse_element& elem = ctxt.elements[ctxt.element_idx[*it]];
320 next.reserve(elem.props.size()+2);
323 for(kvlist_t::map_t::const_iterator itx=elem.props.begin(), endx=elem.props.end();
326 assign_expr_to_Config(next, itx->first, itx->second);
330 assert(!elem.etype.empty() && !elem.label.empty());
331 next.set<std::string>(
"type", elem.etype);
332 next.set<std::string>(
"name", elem.label);
333 elements[i++].swap(next);
336 ret->swap<std::string>(
"name", line->label);
337 ret->swap<Config::vector_t>(
"elements", elements);
339 return ret.release();
347 GLPSParser::~GLPSParser() {}
352 priv->vars[name] = v;
358 priv->printer = strm;
364 boost::filesystem::path fpath;
366 fpath = boost::filesystem::canonical(fname).parent_path();
368 fpath = boost::filesystem::current_path();
372 bool closeme = fname!=NULL && strcmp(fname,
"-")!=0;
374 fp = fopen(fname,
"r");
378 std::ostringstream strm;
379 strm<<
"Failed to open file for parsing '"<<fname<<
"'";
380 throw std::runtime_error(strm.str());
384 if(closeme) fclose(fp);
387 if(closeme) fclose(fp);
395 parse_context ctxt(path);
396 ctxt.printer = priv->printer;
397 priv->fill_vars(ctxt);
399 return priv->fill_context(ctxt);
405 parse_context ctxt(path);
406 ctxt.printer = priv->printer;
407 priv->fill_vars(ctxt);
409 return priv->fill_context(ctxt);
415 parse_context ctxt(path);
416 ctxt.printer = priv->printer;
417 priv->fill_vars(ctxt);
419 return priv->fill_context(ctxt);
424 struct glps_show_props :
public boost::static_visitor<void>
427 const std::string& name;
428 glps_show_props(std::ostream& s,
const std::string& n) :strm(s), name(n) {}
430 void operator()(
double v)
const
432 strm<<
", "<<name<<
" = "<<v;
435 void operator()(
const std::string& v)
const
437 strm<<
", "<<name<<
" = \""<<v<<
"\"";
440 void operator()(
const std::vector<double>& v)
const
442 strm <<
", " << name <<
" = [";
443 for(
size_t i=0, N=v.size(); i<N; i++)
452 void operator()(
const Config::vector_t& v)
const
458 struct glps_show :
public boost::static_visitor<void>
461 const std::string& name;
462 glps_show(std::ostream& s,
const std::string& n) :strm(s), name(n) {}
464 void operator()(
double v)
const
466 strm<<name<<
" = "<<v<<
";\n";
469 void operator()(
const std::string& v)
const
471 strm<<name<<
" = \""<<v<<
"\";\n";
474 void operator()(
const std::vector<double>& v)
const
476 strm << name <<
" = [";
477 for(
size_t i=0, N=v.size(); i<N; i++)
486 void operator()(
const Config::vector_t& v)
const
488 if(name!=
"elements") {
490 strm <<
"# "<<name<<
" = [... skipped ...];\n";
497 void GLPSPrint(std::ostream& strm,
const Config& conf)
503 boost::apply_visitor(glps_show(strm, it->first), it->second);
506 const Config::vector_t *v;
508 v = &conf.
get<Config::vector_t>(
"elements");
510 strm<<
"# Missing beamline element list\n";
512 }
catch(boost::bad_get&){
513 strm<<
"# 'elements' is not a beamline element list\n";
517 std::vector<std::string> line;
518 line.reserve(v->size());
520 std::set<std::string> eshown;
523 for(Config::vector_t::const_iterator it=v->begin(), end=v->end();
528 const std::string& name=it->get<std::string>(
"name");
529 const std::string& type=it->get<std::string>(
"type");
530 if(name.empty() || type.empty())
531 throw std::runtime_error(
"Element missing 'name' and/or 'type'");
532 line.push_back(name);
534 if(eshown.find(name)!=eshown.end())
536 strm<<name<<
": "<<type;
540 }
catch(boost::bad_get&){
544 strm<<
"# <malformed element>";
549 if(itx->first==
"name" || itx->first==
"type")
551 boost::apply_visitor(glps_show_props(strm, itx->first), itx->second);
557 std::string lname(conf.
get<std::string>(
"name",
"default"));
558 strm<<lname<<
": LINE = (";
561 for(std::vector<std::string>::const_iterator it=line.begin(), end=line.end();
570 strm<<
");\nUSE: "<<lname<<
";\n";
bool tryGetAny(const std::string &name, value_t &ret) const
Config()
New empty config.
void setVar(const std::string &name, const Config::value_t &v)
Pre-define variable.
const value_t & getAny(const std::string &name) const
void setPrinter(std::ostream *)
Set output for lexer/parser error messages.
void set(const std::string &name, typename boost::call_traits< typename detail::is_config_value< T >::type >::param_type val)
Config & operator=(const Config &)
Assignment.
GLPSParser()
Construct an empty parser context.
Associative configuration container.
void show(std::ostream &, unsigned indent=0) const
Print listing of inner scope.
Config * parse_file(const char *fname)
Open and parse a file.
void setAny(const std::string &name, const value_t &val)
boost::variant< double, std::vector< double >, std::string, std::vector< Config > > value_t
An individual value (double, double[], string, or Config[])
const_iterator end() const
one after the last element
detail::RT< T >::type get(const std::string &name) const
Config new_scope() const
Create a new inner scope.
void swapAny(const std::string &name, value_t &val)
Exchange a single parameter untyped.
values_t::const_iterator const_iterator
const_iterator
Config * parse_byte(const char *s, size_t len, const char *path=NULL)
Parse from byte buffer.
const_iterator begin() const
The first element.