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,
const bool lattice=
true)
266 std::unique_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);
277 if(ctxt.line.size()==0)
278 throw std::runtime_error(
"No beamlines defined by this file");
280 parse_line *line = NULL;
284 parse_context::map_idx_t::const_iterator it=ctxt.element_idx.find(
"USE");
285 if(it!=ctxt.element_idx.end()) {
286 parse_element &elem = ctxt.elements[it->second];
287 parse_context::map_idx_t::const_iterator lit = ctxt.line_idx.find(elem.etype);
289 if(lit!=ctxt.line_idx.end()) {
290 line = &ctxt.line[lit->second];
292 std::ostringstream strm;
293 strm<<
"\"USE: "<<elem.etype<<
";\" references undefined beamline";
294 throw std::runtime_error(strm.str());
298 line = &ctxt.line.back();
304 if(line->names.size()==0) {
305 std::ostringstream strm;
306 strm<<
"Beamline '"<<line->label<<
"' has no elements";
307 throw std::runtime_error(strm.str());
310 Config::vector_t elements;
311 elements.resize(line->names.size());
315 for(strlist_t::list_t::const_iterator it=line->names.begin(), end=line->names.end();
318 Config next(ret->new_scope());
319 const parse_element& elem = ctxt.elements[ctxt.element_idx[*it]];
321 next.reserve(elem.props.size()+2);
324 for(kvlist_t::map_t::const_iterator itx=elem.props.begin(), endx=elem.props.end();
327 assign_expr_to_Config(next, itx->first, itx->second);
331 assert(!elem.etype.empty() && !elem.label.empty());
332 next.set<std::string>(
"type", elem.etype);
333 next.set<std::string>(
"name", elem.label);
334 elements[i++].swap(next);
337 ret->swap<std::string>(
"name", line->label);
338 ret->swap<Config::vector_t>(
"elements", elements);
341 return ret.release();
349 GLPSParser::~GLPSParser() {}
354 priv->vars[name] = v;
360 priv->printer = strm;
366 boost::filesystem::path fpath;
368 fpath = boost::filesystem::canonical(fname).parent_path();
370 fpath = boost::filesystem::current_path();
374 bool closeme = fname!=NULL && strcmp(fname,
"-")!=0;
376 fp = fopen(fname,
"r");
380 std::ostringstream strm;
381 strm<<
"Failed to open file for parsing '"<<fname<<
"'";
382 throw std::runtime_error(strm.str());
386 if(closeme) fclose(fp);
389 if(closeme) fclose(fp);
397 parse_context ctxt(path);
398 ctxt.printer = priv->printer;
399 priv->fill_vars(ctxt);
401 return priv->fill_context(ctxt, have_lattice);
407 parse_context ctxt(path);
408 ctxt.printer = priv->printer;
409 priv->fill_vars(ctxt);
411 return priv->fill_context(ctxt);
417 parse_context ctxt(path);
418 ctxt.printer = priv->printer;
419 priv->fill_vars(ctxt);
421 return priv->fill_context(ctxt);
426 struct glps_show_props :
public boost::static_visitor<void>
429 const std::string& name;
430 glps_show_props(std::ostream& s,
const std::string& n) :strm(s), name(n) {}
432 void operator()(
double v)
const
434 strm<<
", "<<name<<
" = "<<v;
437 void operator()(
const std::string& v)
const
439 strm<<
", "<<name<<
" = \""<<v<<
"\"";
442 void operator()(
const std::vector<double>& v)
const
444 strm <<
", " << name <<
" = [";
445 for(
size_t i=0, N=v.size(); i<N; i++)
454 void operator()(
const Config::vector_t& v)
const
460 struct glps_show :
public boost::static_visitor<void>
463 const std::string& name;
464 glps_show(std::ostream& s,
const std::string& n) :strm(s), name(n) {}
466 void operator()(
double v)
const
468 strm<<name<<
" = "<<v<<
";\n";
471 void operator()(
const std::string& v)
const
473 strm<<name<<
" = \""<<v<<
"\";\n";
476 void operator()(
const std::vector<double>& v)
const
478 strm << name <<
" = [";
479 for(
size_t i=0, N=v.size(); i<N; i++)
488 void operator()(
const Config::vector_t& v)
const
490 if(name!=
"elements") {
492 strm <<
"# "<<name<<
" = [... skipped ...];\n";
499 void GLPSPrint(std::ostream& strm,
const Config& conf)
505 boost::apply_visitor(glps_show(strm, it->first), it->second);
508 const Config::vector_t *v;
510 v = &conf.
get<Config::vector_t>(
"elements");
512 strm<<
"# Missing beamline element list\n";
514 }
catch(boost::bad_get&){
515 strm<<
"# 'elements' is not a beamline element list\n";
519 std::vector<std::string> line;
520 line.reserve(v->size());
522 std::set<std::string> eshown;
525 for(Config::vector_t::const_iterator it=v->begin(), end=v->end();
530 const std::string& name=it->get<std::string>(
"name");
531 const std::string& type=it->get<std::string>(
"type");
532 if(name.empty() || type.empty())
533 throw std::runtime_error(
"Element missing 'name' and/or 'type'");
534 line.push_back(name);
536 if(eshown.find(name)!=eshown.end())
538 strm<<name<<
": "<<type;
542 }
catch(boost::bad_get&){
546 strm<<
"# <malformed element>";
551 if(itx->first==
"name" || itx->first==
"type")
553 boost::apply_visitor(glps_show_props(strm, itx->first), itx->second);
559 std::string lname(conf.
get<std::string>(
"name",
"default"));
560 strm<<lname<<
": LINE = (";
563 for(std::vector<std::string>::const_iterator it=line.begin(), end=line.end();
572 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
Config * parse_file(const char *fname, const bool have_lattice=true)
Open and parse a file.
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.
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.