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.