FLAME  devel
 All Classes Functions Variables Typedefs Enumerations Pages
glps_ops.cpp
1 
2 # include <cmath>
3 
4 #include <sstream>
5 #include <limits>
6 #include <stdexcept>
7 
8 #include "glps_parser.h"
9 #include "flame/config.h"
10 
11 # define M_PI 3.14159265358979323846
12 
13 using std::isfinite;
14 namespace {
15 // Numeric operations
16 
17 int unary_negate(parse_context* ctxt, expr_value_t *R, const expr_t * const *A)
18 {
19  *R = -boost::get<double>(A[0]->value);
20  return 0;
21 }
22 
23 int unary_sin(parse_context* ctxt, expr_value_t *R, const expr_t * const *A)
24 {
25  *R = sin(boost::get<double>(A[0]->value));
26  return 0;
27 }
28 int unary_cos(parse_context* ctxt, expr_value_t *R, const expr_t * const *A)
29 {
30  *R = cos(boost::get<double>(A[0]->value));
31  return 0;
32 }
33 int unary_tan(parse_context* ctxt, expr_value_t *R, const expr_t * const *A)
34 {
35  *R = tan(boost::get<double>(A[0]->value));
36  return 0;
37 }
38 int unary_asin(parse_context* ctxt, expr_value_t *R, const expr_t * const *A)
39 {
40  *R = asin(boost::get<double>(A[0]->value));
41  return 0;
42 }
43 int unary_acos(parse_context* ctxt, expr_value_t *R, const expr_t * const *A)
44 {
45  *R = acos(boost::get<double>(A[0]->value));
46  return 0;
47 }
48 int unary_atan(parse_context* ctxt, expr_value_t *R, const expr_t * const *A)
49 {
50  *R = atan(boost::get<double>(A[0]->value));
51  return 0;
52 }
53 
54 int unary_deg2rad(parse_context* ctxt, expr_value_t *R, const expr_t * const *A)
55 {
56  double val = boost::get<double>(A[0]->value);
57  val *= M_PI/180.0;
58  *R = val;
59  return 0;
60 }
61 int unary_rad2deg(parse_context* ctxt, expr_value_t *R, const expr_t * const *A)
62 {
63  double val = boost::get<double>(A[0]->value);
64  val *= 180.0/M_PI;
65  *R = val;
66  return 0;
67 }
68 
69 int binary_add(parse_context* ctxt, expr_value_t *R, const expr_t * const *A)
70 {
71  *R = boost::get<double>(A[0]->value)+boost::get<double>(A[1]->value);
72  return 0;
73 }
74 int binary_sub(parse_context* ctxt, expr_value_t *R, const expr_t * const *A)
75 {
76  *R = boost::get<double>(A[0]->value)-boost::get<double>(A[1]->value);
77  return 0;
78 }
79 int binary_mult(parse_context* ctxt, expr_value_t *R, const expr_t * const *A)
80 {
81  *R = boost::get<double>(A[0]->value)*boost::get<double>(A[1]->value);
82  return 0;
83 }
84 int binary_div(parse_context* ctxt, expr_value_t *R, const expr_t * const *A)
85 {
86  double result = boost::get<double>(A[0]->value)/boost::get<double>(A[1]->value);
87  if(!isfinite(result)) {
88  ctxt->last_error = "division results in non-finite value";
89  return 1;
90  }
91  *R = result;
92  return 0;
93 }
94 
95 // beamline operations
96 
97 int unary_bl_negate(parse_context* ctxt, expr_value_t *R, const expr_t * const *A)
98 {
99  // reverse the order of the beamline
100  const std::vector<std::string>& line = boost::get<std::vector<std::string> >(A[0]->value);
101  std::vector<std::string> ret(line.size());
102  std::copy(line.rbegin(),
103  line.rend(),
104  ret.begin());
105  *R = ret;
106  return 0;
107 }
108 
109 template<int MULT, int LINE>
110 int binary_bl_mult(parse_context* ctxt, expr_value_t *R, const expr_t * const *A)
111 {
112  // multiple of scale * beamline repeats the beamline 'scale' times
113  assert(A[MULT]->etype==glps_expr_number);
114  assert(A[LINE]->etype==glps_expr_line);
115 
116  double factor = boost::get<double>(A[MULT]->value);
117 
118  if(factor<0.0 || factor>std::numeric_limits<unsigned>::max()) {
119  ctxt->last_error = "beamline scale by negative value or out of range value";
120  return 1;
121  }
122  unsigned factori = (unsigned)factor;
123 
124  const std::vector<std::string>& line = boost::get<std::vector<std::string> >(A[LINE]->value);
125 
126  std::vector<std::string> ret(line.size()*factori);
127 
128  if(factori>0)
129  {
130  std::vector<std::string>::iterator outi = ret.begin();
131 
132  while(factori--)
133  outi = std::copy(line.begin(),
134  line.end(),
135  outi);
136  }
137  *R = ret;
138  return 0;
139 }
140 
141 int unary_parse(parse_context* ctxt, expr_value_t *R, const expr_t * const *A)
142 {
143  using namespace boost::filesystem;
144  assert(A[0]->etype==glps_expr_string);
145  path name(canonical(boost::get<std::string>(A[0]->value), ctxt->cwd));
146 
147  GLPSParser P;
148  P.setPrinter(ctxt->printer);
149 
150  boost::shared_ptr<Config> ret(P.parse_file(name.native().c_str()));
151  *R = ret;
152  return 0;
153 }
154 
155 int unary_file(parse_context* ctxt, expr_value_t *R, const expr_t * const *A)
156 {
157  using namespace boost::filesystem;
158  const std::string& inp = boost::get<std::string>(A[0]->value);
159  path ret(canonical(inp, ctxt->cwd));
160 
161  if(!exists(ret)) {
162  std::ostringstream strm;
163  strm<<"\""<<ret<<"\" does not exist";
164  ctxt->last_error = strm.str();
165  return 1;
166  }
167 
168  *R = ret.native();
169  return 0;
170 }
171 
172 int unary_h5file(parse_context* ctxt, expr_value_t *R, const expr_t * const *A)
173 {
174  using namespace boost::filesystem;
175  const std::string& inp = boost::get<std::string>(A[0]->value);
176 
177  /* The provided spec may contain both file path and group(s)
178  * seperated by '/' which is ambigious as the file path
179  * may contain '/' as well...
180  * so do as h5ls does and strip off from the right hand side until
181  * and try to open while '/' remain.
182  */
183  size_t sep = inp.npos;
184 
185  while(true) {
186  sep = inp.find_last_of('/', sep-1);
187 
188  path fname(absolute(inp.substr(0, sep), ctxt->cwd));
189 
190  if(exists(fname)) {
191  *R = canonical(fname).native() + inp.substr(sep);
192  return 0;
193  } else if(sep==inp.npos) {
194  break;
195  }
196  }
197 
198  std::ostringstream strm;
199  strm<<"\""<<inp<<"\" does not exist";
200  ctxt->last_error = strm.str();
201  return 1;
202 }
203 
204 } // namespace
205 
206 parse_context::parse_context(const char *path)
207  :last_line(0), printer(NULL), error_scratch(300), scanner(NULL)
208 {
209  if(path)
210  cwd = boost::filesystem::canonical(path);
211  else
212  cwd = boost::filesystem::current_path();
213  addop("-", &unary_negate, glps_expr_number, 1, glps_expr_number);
214 
215  addop("sin", &unary_sin, glps_expr_number, 1, glps_expr_number);
216  addop("cos", &unary_cos, glps_expr_number, 1, glps_expr_number);
217  addop("tan", &unary_tan, glps_expr_number, 1, glps_expr_number);
218  addop("asin",&unary_asin,glps_expr_number, 1, glps_expr_number);
219  addop("acos",&unary_acos,glps_expr_number, 1, glps_expr_number);
220  addop("atan",&unary_atan,glps_expr_number, 1, glps_expr_number);
221  // aliases to capture legacy behavour :P
222  addop("arcsin",&unary_asin,glps_expr_number, 1, glps_expr_number);
223  addop("arccos",&unary_acos,glps_expr_number, 1, glps_expr_number);
224  addop("arctan",&unary_atan,glps_expr_number, 1, glps_expr_number);
225 
226  addop("deg2rad",&unary_deg2rad,glps_expr_number, 1, glps_expr_number);
227  addop("rad2deg",&unary_rad2deg,glps_expr_number, 1, glps_expr_number);
228 
229  addop("+", &binary_add, glps_expr_number, 2, glps_expr_number, glps_expr_number);
230  addop("-", &binary_sub, glps_expr_number, 2, glps_expr_number, glps_expr_number);
231  addop("*", &binary_mult,glps_expr_number, 2, glps_expr_number, glps_expr_number);
232  addop("/", &binary_div, glps_expr_number, 2, glps_expr_number, glps_expr_number);
233 
234  addop("-", &unary_bl_negate, glps_expr_line, 1, glps_expr_line);
235 
236  addop("*", &binary_bl_mult<0,1>, glps_expr_line, 2, glps_expr_number, glps_expr_line);
237  addop("*", &binary_bl_mult<1,0>, glps_expr_line, 2, glps_expr_line, glps_expr_number);
238 
239  addop("parse", &unary_parse, glps_expr_config, 1, glps_expr_string);
240  addop("file", &unary_file, glps_expr_string, 1, glps_expr_string);
241  addop("dir", &unary_file, glps_expr_string, 1, glps_expr_string);
242  addop("h5file", &unary_h5file, glps_expr_string, 1, glps_expr_string);
243 }
244 
245 parse_context::~parse_context()
246 {
247 }
248 
void setPrinter(std::ostream *)
Set output for lexer/parser error messages.
Definition: config.cpp:356
Interface to lattice file parser.
Definition: config.h:240
Config * parse_file(const char *fname)
Open and parse a file.
Definition: config.cpp:362