OPAL (Object Oriented Parallel Accelerator Library)  2021.1.99
OPAL
Expressions.cpp
Go to the documentation of this file.
1 // ------------------------------------------------------------------------
2 // $RCSfile: Expressions.cpp,v $
3 // ------------------------------------------------------------------------
4 // $Revision: 1.2.4.1 $
5 // ------------------------------------------------------------------------
6 // Copyright: see Copyright.readme
7 // ------------------------------------------------------------------------
8 //
9 // Namespace Expressions:
10 // This namespace contains the attribute parsers for OPAL:
11 // a collection of functions.
12 //
13 // ------------------------------------------------------------------------
14 //
15 // $Date: 2002/12/09 15:06:08 $
16 // $Author: jsberg $
17 //
18 // ------------------------------------------------------------------------
19 
25 #include "AbstractObjects/Table.h"
28 #include "AbstractObjects/Object.h"
29 #include "Expressions/ABinary.h"
30 #include "Expressions/AColumn.h"
31 #include "Expressions/AList.h"
32 #include "Expressions/ARefExpr.h"
33 #include "Expressions/ARow.h"
34 #include "Expressions/ASUnary.h"
35 #include "Expressions/AUnary.h"
36 #include "Expressions/ATable.h"
37 #include "Expressions/Indexer.h"
38 #include "Expressions/SBinary.h"
39 #include "Expressions/SCell.h"
40 #include "Expressions/SConstant.h"
41 #include "Expressions/SFunction.h"
42 #include "Expressions/SHash.h"
43 #include "Expressions/SNull.h"
44 #include "Expressions/SRefAttr.h"
45 #include "Expressions/SRefExpr.h"
46 #include "Expressions/SUnary.h"
47 #include "Expressions/TFind.h"
48 #include "Expressions/TFunction0.h"
49 #include "Expressions/TFunction1.h"
50 #include "Expressions/TFunction2.h"
51 #include "Parser/Statement.h"
53 #include "Utilities/Options.h"
54 #include "Utilities/ParseError.h"
57 #include <algorithm>
58 #include <cerrno>
59 #include <cmath>
60 #include <list>
61 #include <sstream>
62 #include <vector>
63 
64 
65 // Namespace Expressions
66 // ------------------------------------------------------------------------
67 
68 namespace Expressions {
69 
70 
71  // Boolean operators.
72  // ----------------------------------------------------------------------
73 
74  bool Or(bool a, bool b) { return a || b; }
75  static const TFunction2<bool, bool> logOr = { "||", 1, Or };
76 
77  bool And(bool a, bool b) { return a && b; }
78  static const TFunction2<bool, bool> logAnd = { "&&", 2, And };
79 
80  bool Le(double a, double b) { return a <= b; }
81  static const TFunction2<bool, double> lessEqual = { "<=", 3, Le } ;
82 
83  bool Lt(double a, double b) { return a < b; }
84  static const TFunction2<bool, double> less = { "<", 3, Lt } ;
85 
86  bool Ge(double a, double b) { return a >= b; }
87  static const TFunction2<bool, double> greaterEqual = { ">=", 3, Ge } ;
88 
89  bool Gt(double a, double b) { return a > b; }
90  static const TFunction2<bool, double> greater = { ">", 3, Gt } ;
91 
92  bool Eq(double a, double b) { return a == b; }
93  static const TFunction2<bool, double> equal = { "==", 3, Eq } ;
94 
95  bool Ne(double a, double b) { return a != b; }
96  static const TFunction2<bool, double> notEqual = { "!=", 3, Ne } ;
97 
98  // Real operators with one or two operands.
99  // ----------------------------------------------------------------------
100 
101  double Neg(double a) {
102  return - a;
103  }
104 
105  static const TFunction1<double, double> negate = { "-", 5, Neg };
106 
107  double Sign(double a) {
108  return (a > 0.) ? 1. : (a < 0.) ? -1. : 0.;
109  }
110 
111  double Tgauss(double a) {
112  double x, y;
113  do { Options::rangen.gauss(x, y); }
114  while(std::abs(x) > a);
115  return x;
116  }
117 
118  double Add(double a, double b) {
119  return a + b;
120  }
121 
122  static const TFunction2<double, double> plus = { "+", 4, Add };
123 
124  double Sub(double a, double b) {
125  return a - b;
126  }
127 
128  static const TFunction2<double, double> minus = { "-", 4, Sub };
129 
130  double Mpy(double a, double b) {
131  return a * b;
132  }
133 
134  static TFunction2<double, double> times = { "*", 5, Mpy };
135 
136  double Div(double a, double b) {
137  if(b == 0.0) {
138  errno = EDOM;
139  return 1.0;
140  } else {
141  return a / b;
142  }
143  }
144 
145  static TFunction2<double, double> divide = { "/", 5, Div };
146 
147  // Real functions without arguments.
148  // ----------------------------------------------------------------------
149 
150 
151  double getEkin() {
152  auto p = OpalData::getInstance()->getPartBunch();
153  if (p)
154  return p->get_meanKineticEnergy();
155  else
156  return -1.0;
157  }
158 
159 
160  double ranf() {
161  return Options::rangen.uniform();
162  }
163 
164  double gauss() {
165  double x, y;
166  Options::rangen.gauss(x, y);
167  return x;
168  }
169 
170  static const TFunction0<double> table0[] = {
171  {"GETEKIN", -2, getEkin},
172  {"RANF", -2, ranf },
173  {"GAUSS", -2, gauss },
174  {"SI", -2, SFunction::arcIn },
175  {"SC", -2, SFunction::arcCtr },
176  {"SO", -2, SFunction::arcOut },
177  { 0, -1, 0 }
178  };
179 
180  // Real functions with two arguments.
181  // ----------------------------------------------------------------------
182 
183  static const TFunction1<double, double> table1[] = {
184  { "TRUNC", -1, std::trunc },
185  { "ROUND", -1, std::round },
186  { "FLOOR", -1, std::floor },
187  { "CEIL", -1, std::ceil },
188  { "SIGN", -1, Sign },
189  { "SQRT", -1, std::sqrt },
190  { "LOG", -1, std::log },
191  { "EXP", -1, std::exp },
192  { "SIN", -1, std::sin },
193  { "COS", -1, std::cos },
194  { "ABS", -1, std::abs },
195  { "TAN", -1, std::tan },
196  { "ASIN", -1, std::asin },
197  { "ACOS", -1, std::acos },
198  { "ATAN", -1, std::atan },
199  { "TGAUSS", -2, Tgauss },
200  { "ERF", -1, std::erf },
201  { 0, -1, 0 }
202  };
203 
204  // Real functions with two arguments.
205  // ----------------------------------------------------------------------
206 
207  double Max(double a, double b) {
208  return std::max(a, b);
209  }
210 
211  double Min(double a, double b) {
212  return std::min(a, b);
213  }
214 
215  double Mod(double a, double b) {
216  if(b <= 0.0) errno = EDOM;
217  return fmod(a, b);
218  }
219 
220  static TFunction2<double, double> power = { "^", 6, pow };
221 
222  static const TFunction2<double, double> table2[] = {
223  { "ATAN2", -1, atan2 },
224  { "MAX", -1, Max },
225  { "MIN", -1, Min },
226  { "MOD", -1, Mod },
227  { "POW", -2, pow },
228  { 0, -1, 0 }
229  };
230 
231 
232  // Function of arrays giving a real result.
233  // ----------------------------------------------------------------------
234 
235  double Mina(const std::vector<double> &array) {
236  if(array.size()) {
237  double result = array[0];
238  for(std::vector<double>::size_type i = 1; i < array.size(); ++i) {
239  result = Min(array[i], result);
240  }
241  return result;
242  } else if(Options::warn) {
243  std::cerr << "\n### Warning ### \"VMIN\" function of empty array.\n"
244  << std::endl;
245  }
246  return 0.0;
247  }
248 
249  double Maxa(const std::vector<double> &array) {
250  if(array.size()) {
251  double result = array[0];
252  for(std::vector<double>::size_type i = 1; i < array.size(); ++i) {
253  result = std::max(array[i], result);
254  }
255  return result;
256  } else if(Options::warn) {
257  std::cerr << "\n### Warning ### \"VMAX\" function of empty array.\n"
258  << std::endl;
259  }
260  return 0.0;
261  }
262 
263  double Rmsa(const std::vector<double> &array) {
264  if(array.size()) {
265  double result = 0.0;
266  for(std::vector<double>::size_type i = 0; i < array.size(); ++i) {
267  result += array[i] * array[i];
268  }
269  return sqrt(result / double(array.size()));
270  } else if(Options::warn) {
271  std::cerr << "\n### Warning ### \"VRMS\" function of empty array.\n"
272  << std::endl;
273  }
274  return 0.0;
275  }
276 
277  double AbsMax(const std::vector<double> &array) {
278  if(array.size()) {
279  double result = std::abs(array[0]);
280  for(std::vector<double>::size_type i = 1; i < array.size(); ++i) {
281  result = std::max(std::abs(array[i]), result);
282  }
283  return result;
284  } else if(Options::warn) {
285  std::cerr << "\n### Warning ### \"VABSMAX\" function of empty array.\n"
286  << std::endl;
287  }
288  return 0.0;
289  }
290 
292  static const ArrayFun tablea[] = {
293  { "VMIN", -1, Mina },
294  { "VMAX", -1, Maxa },
295  { "VRMS", -1, Rmsa },
296  { "VABSMAX", -1, AbsMax },
297  { 0, -1, 0 }
298  };
299 
300 
301  // Internal variables.
302  const Table *currentTable = 0;
304 
305 
306  // FORWARD DECLARATIONS FOR LOCAL FUNCTIONS.
307  // ------------------------------------------------------------------------
308 
309  // Parse an "&&" expression.
311 
312  // Parse an array factor.
314 
315  // Parse an array primary.
317 
318  // Parse an array term.
320 
321  // Parse a token list in brackets (for macro argument and the like).
322  // This method also checks the nesting of parentheses.
323  void parseBracketList
324  (Statement &stat, char close, std::list<Token> &result);
325 
326  // Parse a real factor.
328 
329  // Parse a real primary expression.
331 
332  // Parse a relational expression.
334 
335  // Parse a real term.
337 
338  // Parse a column generator "COLUMN(table,column,range)".
340 
341  // Parse a row generator "ROW(table,place,...)".
343 
344  // Parse a table generator "TABLE(n1:n2:n3,expr)".
346 
347 
348  // PARSE SCALAR EXPRESSIONS.
349  // ------------------------------------------------------------------------
350 
352  PtrToScalar<bool> second;
353  PtrToScalar<bool> result = parseAnd(stat);
354 
355  while(stat.delimiter("||")) {
356  second = parseAnd(stat);
357  result = SBinary<bool, bool>::make(logOr, result, second);
358  }
359 
360  return result;
361  }
362 
363 
365  PtrToScalar<double> result;
366  PtrToScalar<double> second;
367 
368  if(stat.delimiter('+')) {
369  // Unary plus.
370  result = parseTerm(stat);
371  } else if(stat.delimiter('-')) {
372  // Unary minus.
373  result = parseTerm(stat);
374  result = SUnary<double, double>::make(negate, result);
375  } else {
376  result = parseTerm(stat);
377  }
378 
379  while(true) {
380  if(stat.delimiter('+')) {
381  second = parseTerm(stat);
382  result = SBinary<double, double>::make(plus, result, second);
383  } else if(stat.delimiter('-')) {
384  second = parseTerm(stat);
385  result = SBinary<double, double>::make(minus, result, second);
386  } else {
387  break;
388  }
389  }
390 
391  return result;
392  }
393 
394 
395  double parseRealConst(Statement &stat) {
396  PtrToScalar<double> expr = parseReal(stat);
397  return expr->evaluate();
398  }
399 
400 
401  std::string parseString(Statement &stat, const char msg[]) {
402  std::string result = std::string("");
403  std::string temp;
404  bool isWord = stat.word(temp);
405 
406  while(isWord || stat.str(temp)) {
407  if(isWord && temp == "TO_STRING") {
408  parseDelimiter(stat, '(');
409  double value = parseRealConst(stat);
410  parseDelimiter(stat, ')');
411  std::ostringstream os;
412  os << value;
413  result += os.str();
414  } else {
415  result += temp;
416  }
417 
418  if(! stat.delimiter('&')) break;
419  isWord = stat.word(temp);
420  }
421 
422  if(result.empty()) {
423  std::string errorMsg(msg);
424  errorMsg = stat.str() + "\n" + errorMsg;
425  throw ParseError("Expressions::parseString()", errorMsg);
426  } else {
427  return result;
428  }
429  }
430 
431  std::string parseStringValue(Statement &stat, const char msg[]) {
432  std::string result;
433  std::string temp;
434  Object *object = nullptr;
435  bool isWord = stat.word(temp);
436  bool isValidObject = isWord && (object = OpalData::getInstance()->find(temp), object);
437  bool isConversion = isWord && temp == "TO_STRING";
438 
439  while(stat.str(temp) || isValidObject || isConversion) {
440  if (isValidObject) {
441  StringConstant *stringConst = dynamic_cast<StringConstant*>(object);
442  if (stringConst) {
443  result += stringConst->getString();
444  } else {
445  result += temp;
446  break;
447  }
448  } else if (isConversion) {
449  parseDelimiter(stat, '(');
450  double value = parseRealConst(stat);
451  parseDelimiter(stat, ')');
452  std::ostringstream os;
453  os << value;
454  result += os.str();
455  } else {
456  result += temp;
457  }
458 
459  if(! stat.delimiter('&')) {
460  break;
461  }
462 
463  object = nullptr;
464  isWord = stat.word(temp);
465  isValidObject = isWord && (object = OpalData::getInstance()->find(temp), object);
466  isConversion = isWord && temp == "TO_STRING";
467  }
468 
469  if(result.empty()) {
470  std::string errorMsg(msg);
471  errorMsg = stat.str() + "\n" + errorMsg;
472  throw ParseError("Expressions::parseStringValue()", errorMsg);
473  } else {
474  return result;
475  }
476  }
477 
478 
479  // PARSE ARRAY EXPRESSIONS
480  // ------------------------------------------------------------------------
481 
483  ArrayOfPtrs<bool> array;
484 
485  if(stat.delimiter('{')) {
486  // List of boolean expressions within braces.
487  do {
488  array.push_back(parseBool(stat));
489  } while(stat.delimiter(','));
490 
491  parseDelimiter(stat, '}');
492  } else {
493  // A single boolean expression.
494  array.push_back(parseBool(stat));
495  }
496 
497  return new AList<bool>(array);
498  }
499 
501  PtrToArray<double> result;
502  PtrToArray<double> second;
503 
504  if(stat.delimiter('+')) {
505  // Unary plus.
506  result = parseArrayTerm(stat);
507  } else if(stat.delimiter('-')) {
508  // Unary minus.
509  result = parseArrayTerm(stat);
510  result = new AUnary<double, double>(negate, result);
511  } else {
512  result = parseArrayTerm(stat);
513  }
514 
515  while(true) {
516  if(stat.delimiter('+')) {
517  second = parseArrayTerm(stat);
518  result = new ABinary<double, double>(plus, result, second);
519  } else if(stat.delimiter('-')) {
520  second = parseArrayTerm(stat);
521  result = new ABinary<double, double>(minus, result, second);
522  } else {
523  break;
524  }
525  }
526 
527  return result;
528  }
529 
530 
533  std::vector<double> value = arg->evaluate();
534  ArrayOfPtrs<double> array;
535 
536  for(ArrayOfPtrs<double>::size_type i = 0; i < value.size(); ++i) {
537  array.push_back(new SConstant<double>(value[i]));
538  }
539 
540  return new AList<double>(array);
541  }
542 
543 
544  std::vector<std::string> parseStringArray(Statement &stat) {
545  std::vector<std::string> array;
546 
547  if(stat.delimiter('{')) {
548  // List of string values within braces.
549  do {
550  array.push_back(parseStringValue(stat, "String value expected."));
551  } while(stat.delimiter(','));
552 
553  parseDelimiter(stat, '}');
554  } else {
555  // A single string value.
556  array.push_back(parseStringValue(stat, "String value expected."));
557  }
558 
559  return array;
560  }
561 
562 
563  void parseDelimiter(Statement &stat, char delim) {
564  if(! stat.delimiter(delim)) {
565  throw ParseError("Expressions::parseDelimiter()",
566  std::string("Delimiter '") + delim + "' expected.");
567  }
568  }
569 
570 
571  void parseDelimiter(Statement &stat, const char delim[2]) {
572  if(! stat.delimiter(delim)) {
573  throw ParseError("Expressions::parseDelimiter()",
574  std::string("Delimiter '") + delim + "' expected.");
575  }
576  }
577 
578 
580  if(stat.keyword("SELECTED")) {
581  return PlaceRep("SELECTED");
582  } else {
583  PlaceRep pos;
584 
585  do {
586  if(stat.delimiter('#')) {
587  static char msg[] = "Expected 'S' or 'E' after '#'.";
588  if(stat.keyword("S")) {
589  pos.append("#S", 0);
590  } else if(stat.keyword("E")) {
591  pos.append("#E", 0);
592  } else {
593  throw ParseError("Expression::parsePlace()", msg);
594  }
595  break;
596  } else {
597  std::string name = parseString(stat, "Expected <name> or '#'.");
598  int occurrence = 1;
599  if(stat.delimiter('[')) {
600  occurrence = int(std::round(parseRealConst(stat)));
601  parseDelimiter(stat, ']');
602 
603  if(occurrence <= 0) {
604  throw ParseError("Expressions::parsePlace()",
605  "Occurrence counter must be positive.");
606  }
607  }
608  pos.append(name, occurrence);
609  }
610  } while(stat.delimiter("::"));
611 
612  return pos;
613  }
614  }
615 
616 
618  if(stat.keyword("FULL")) {
619  return RangeRep();
620  } else {
621  PlaceRep first = parsePlace(stat);
622  PlaceRep last = first;
623  if(stat.delimiter('/')) last = parsePlace(stat);
624  return RangeRep(first, last);
625  }
626  }
627 
628 
630  std::string objName = parseString(stat, "Object name expected.");
631 
632  // Test for attribute name.
633  std::string attrName;
634 
635  if(stat.delimiter("->")) {
636  // Reference to object attribute.
637  attrName = parseString(stat, "Attribute name expected.");
638  }
639 
640  // Parse an index, if present.
641  int index = 0;
642 
643  if(stat.delimiter('[')) {
644  index = int(std::round(parseRealConst(stat)));
645  parseDelimiter(stat, ']');
646 
647  if(index <= 0) {
648  throw ParseError("Expressions::parseReference()",
649  "Index must be positive.");
650  }
651  }
652 
653  // Build reference and fill in the attribute pointer.
654  return new SRefAttr<double>(objName, attrName, index);
655  }
656 
657 
659  std::string tabName = parseString(stat, "Table name expected.");
660  parseDelimiter(stat, '@');
661  return TableRowRep(tabName, parsePlace(stat));
662  }
663 
664 
665  // ANCILLARY FUNCTIONS.
666  // ------------------------------------------------------------------------
667 
668  PtrToScalar<double>
670  currentTable = t;
671  PtrToScalar<double> result = parseReal(stat);
672  currentTable = 0;
673  return result;
674  }
675 
676 
677  std::list<Token> parseTokenList(Statement &stat) {
678  std::list<Token> result;
679 
680  while(!stat.atEnd()) {
681  stat.mark();
682  Token token = stat.getCurrent();
683 
684  // End of list if one of the following tokens occurs outside
685  // of brackets.
686  if(token.isDel(',') || token.isDel(';') || token.isDel(')') ||
687  token.isDel(']') || token.isDel('}')) {
688  // Must reread the terminating token.
689  stat.restore();
690  break;
691  }
692 
693  result.push_back(token);
694 
695  if(token.isDel('(')) {
696  parseBracketList(stat, ')', result);
697  } else if(token.isDel('[')) {
698  parseBracketList(stat, ']', result);
699  } else if(token.isDel('{')) {
700  parseBracketList(stat, '}', result);
701  }
702  }
703 
704  return result;
705  }
706 
707 
708  std::vector<std::list<Token> > parseTokenListArray(Statement &stat) {
709  std::vector<std::list<Token> > array;
710 
711  if(stat.delimiter('{')) {
712  // List of token lists within braces.
713  do {
714  array.push_back(parseTokenList(stat));
715  } while(stat.delimiter(','));
716 
717  parseDelimiter(stat, '}');
718  } else {
719  // A single token list.
720  array.push_back(parseTokenList(stat));
721  }
722 
723  return array;
724  }
725 
726 
727  // LOCAL FUNCTIONS.
729  PtrToScalar<bool> result = parseRelation(stat);
730  PtrToScalar<bool> second;
731 
732  while(stat.delimiter("&&")) {
733  second = parseRelation(stat);
734  result = SBinary<bool, bool>::make(logAnd, result, second);
735  }
736 
737  return result;
738  }
739 
740 
742  PtrToArray<double> result = parseArrayPrimary(stat);
743  PtrToArray<double> second;
744 
745  if(stat.delimiter('^')) {
746  second = parseArrayPrimary(stat);
747  result = new ABinary<double, double>(power, result, second);
748  }
749 
750  return result;
751  }
752 
753 
755  PtrToArray<double> result;
756  double value;
757 
758  if(stat.delimiter('(')) {
759  result = parseRealArray(stat);
760  parseDelimiter(stat, ')');
761  } else if(stat.delimiter('{')) {
762  ArrayOfPtrs<double> array;
763  do {
764  array.push_back(parseReal(stat));
765  } while(stat.delimiter(','));
766  parseDelimiter(stat, '}');
767  result = new AList<double>(array);
768  } else if(stat.keyword("COLUMN")) {
769  result = parseColumnGenerator(stat);
770  } else if(stat.keyword("ROW")) {
771  result = parseRowGenerator(stat);
772  } else if(stat.keyword("TABLE")) {
773  result = parseTableGenerator(stat);
774  } else if(stat.real(value)) {
775  ArrayOfPtrs<double> array;
776  array.push_back(new SConstant<double>(value));
777  result = new AList<double>(array);
778  } else {
779  std::string frstName = parseString(stat, "Object name expected.");
780  if(stat.delimiter('(')) {
781  // Possible function call.
782  PtrToArray<double> arg1;
783  PtrToArray<double> arg2;
784  if(const TFunction2<double, double> *fun = find(table2, frstName)) {
785  arg1 = parseRealArray(stat);
786  parseDelimiter(stat, ',');
787  arg2 = parseRealArray(stat);
788  result = new ABinary<double, double>(*fun, arg1, arg2);
789  } else if(const TFunction1<double, double> *fun =
790  find(table1, frstName)) {
791  arg1 = parseRealArray(stat);
792  result = new AUnary<double, double>(*fun, arg1);
793  } else if(frstName == "EVAL") {
794  result = parseRealConstArray(stat);
795  } else if(const TFunction0<double> *fun = find(table0, frstName)) {
796  ArrayOfPtrs<double> array;
797  array.push_back(SNull<double>::make(*fun));
798  result = new AList<double>(array);
799  } else if(const ArrayFun *fun = find(tablea, frstName)) {
800  arg1 = parseRealArray(stat);
801  ArrayOfPtrs<double> array;
802  array.push_back(new ASUnary<double>(*fun, arg1));
803  result = new AList<double>(array);
804  } else {
805  throw ParseError("parseArrayPrimary()",
806  "Invalid array function name \"" + frstName +
807  "\".");
808  }
809  parseDelimiter(stat, ')');
810  } else if(stat.delimiter("->")) {
811  std::string scndName = parseString(stat, "Attribute name expected.");
812  result = new ARefExpr<double>(frstName, scndName);
813  } else if(stat.delimiter('@')) {
814  PlaceRep row = parsePlace(stat);
815  // Possible column names.
816  if(stat.delimiter("->")) {
817  std::vector<std::string> cols = parseStringArray(stat);
818  result = new ARow(frstName, row, cols);
819  } else {
820  throw ParseError("Expressions::parseReal()",
821  "Expected a column name.");
822  }
823  } else {
824  result = new ARefExpr<double>(frstName, "");
825  }
826  }
827 
828  return result;
829  }
830 
831 
833  PtrToArray<double> result = parseArrayFactor(stat);
834  PtrToArray<double> second;
835 
836  while(true) {
837  if(stat.delimiter('*')) {
838  second = parseArrayFactor(stat);
839  result = new ABinary<double, double>(times, result, second);
840  } else if(stat.delimiter('/')) {
841  second = parseArrayFactor(stat);
842  result = new ABinary<double, double>(divide, result, second);
843  } else {
844  break;
845  }
846  }
847 
848  return result;
849  }
850 
851 
852  void parseBracketList(Statement &stat, char close, std::list<Token> &result) {
853  while(true) {
854  if(stat.atEnd() || stat.delimiter(';')) {
855  throw ParseError("Expressions::parseBracketList()",
856  "Parentheses, brackets or braces do not nest.");
857  }
858 
859  Token token = stat.getCurrent();
860  result.push_back(token);
861 
862  if(token.isDel('(')) {
863  parseBracketList(stat, ')', result);
864  } else if(token.isDel('[')) {
865  parseBracketList(stat, ']', result);
866  } else if(token.isDel('{')) {
867  parseBracketList(stat, '}', result);
868  } else if(token.isDel(close)) {
869  return;
870  }
871  }
872  }
873 
874 
876  PtrToScalar<double> result = parsePrimary(stat);
877  PtrToScalar<double> second;
878 
879  if(stat.delimiter('^')) {
880  second = parsePrimary(stat);
881  result = SBinary<double, double>::make(power, result, second);
882  }
883 
884  return result;
885  }
886 
887 
889  PtrToScalar<double> arg1;
890  PtrToScalar<double> arg2;
891  PtrToScalar<double> result;
892  double value;
893 
894  if(stat.delimiter('(')) {
895  // Expression in "(...)".
896  result = parseReal(stat);
897  parseDelimiter(stat, ')');
898  } else if(stat.real(value)) {
899  // Litteral constant.
900  result = new SConstant<double>(value);
901  } else if(currentArray.isValid() && stat.delimiter('#')) {
902  // "#" hash expression
903  result = new SHash(*currentArray);
904  } else {
905  // Primary beginning with a name.
906  std::string frstName = parseString(stat, "Real primary expected.");
907 
908  if(stat.delimiter('(')) {
909  // Possible function call.
910  if(const TFunction2<double, double> *fun = find(table2, frstName)) {
911  arg1 = parseReal(stat);
912  parseDelimiter(stat, ',');
913  arg2 = parseReal(stat);
914  result = SBinary<double, double>::make(*fun, arg1, arg2);
915  } else if(const TFunction1<double, double> *fun =
916  find(table1, frstName)) {
917  arg1 = parseReal(stat);
918  result = SUnary<double, double>::make(*fun, arg1);
919  } else if(frstName == "EVAL") {
920  result = new SConstant<double>(parseRealConst(stat));
921  } else if(const TFunction0<double> *fun = find(table0, frstName)) {
922  result = SNull<double>::make(*fun);
923  } else if(const ArrayFun *fun = find(tablea, frstName)) {
924  PtrToArray<double> arg1 = parseRealArray(stat);
925  result = new ASUnary<double>(*fun, arg1);
926  } else {
927  throw ParseError("parsePrimary()",
928  "Unknown function name \"" + frstName + "\".");
929  }
930  parseDelimiter(stat, ')');
931  } else if(stat.delimiter("->")) {
932  // Possible parameter or object->attribute clause.
933  std::string scndName =
934  parseString(stat, "Attribute or element name expected.");
935 
936  // Possible index.
937  if(stat.delimiter('[')) {
938  arg2 = parseReal(stat);
939  parseDelimiter(stat, ']');
940  PtrToArray<double> arg1 =
941  new ARefExpr<double>(frstName, scndName);
942  result = new Indexer<double>(arg1, arg2);
943  } else {
944  result = new SRefExpr<double>(frstName, scndName);
945  }
946  } else if(stat.delimiter('@')) {
947  PlaceRep row = parsePlace(stat);
948  // Possible column name.
949  if(stat.delimiter("->")) {
950  std::string col = parseString(stat, "Column name expected.");
951  result = new SCell(frstName, row, col);
952  } else {
953  throw ParseError("Expressions::parseReal()",
954  "Expected a column name.");
955  }
956  } else {
957  // If the name is indexed, the name must be a global vector.
958  if(stat.delimiter('[')) {
959  arg2 = parseReal(stat);
960  parseDelimiter(stat, ']');
961  PtrToArray<double> arg1 = new ARefExpr<double>(frstName, "");
962  result = new Indexer<double>(arg1, arg2);
963  } else if(currentTable) {
964  // Try making a column expression.
965  result = currentTable->makeColumnExpression(frstName);
966  if(! result.isValid()) {
967  // Could not make a column expression from this name.
968  result = new SRefExpr<double>(frstName, "");
969  }
970  } else {
971  // Simple name must be a global variable.
972  result = new SRefExpr<double>(frstName, "");
973  }
974  }
975  }
976 
977  return result;
978  }
979 
980 
982  PtrToScalar<double> first;
983  PtrToScalar<double> second;
984  PtrToScalar<bool> result;
985  bool value;
986  std::string name;
987 
988  if(stat.delimiter('(')) {
989  result = parseBool(stat);
990  parseDelimiter(stat, ')');
991  } else if(stat.boolean(value)) {
992  result = new SConstant<bool>(value);
993  } else {
994  stat.mark();
995  BoolConstant *bc = 0;
996  if(stat.word(name) &&
997  (bc = dynamic_cast<BoolConstant *>(OpalData::getInstance()->find(name)))) {
998  return new SConstant<bool>(bc->getBool());
999  }
1000 
1001  stat.restore();
1002  first = parseReal(stat);
1003  const TFunction2<bool, double> *code = 0;
1004  if(stat.delimiter('<')) {
1005  code = &less;
1006  } else if(stat.delimiter('>')) {
1007  code = &greater;
1008  } else if(stat.delimiter(">=")) {
1009  code = &greaterEqual;
1010  } else if(stat.delimiter("<=")) {
1011  code = &lessEqual;
1012  } else if(stat.delimiter("==")) {
1013  code = &equal;
1014  } else if(stat.delimiter("!=")) {
1015  code = &notEqual;
1016  } else {
1017  throw ParseError("parseRelation()",
1018  "Invalid boolean expression.");
1019  }
1020  second = parseReal(stat);
1021  result = SBinary<bool, double>::make(*code, first, second);
1022  }
1023 
1024  return result;
1025  }
1026 
1027 
1029  PtrToScalar<double> result = parseFactor(stat);
1030  PtrToScalar<double> second;
1031 
1032  while(true) {
1033  if(stat.delimiter('*')) {
1034  second = parseFactor(stat);
1035  result = SBinary<double, double>::make(times, result, second);
1036  } else if(stat.delimiter('/')) {
1037  second = parseFactor(stat);
1038  result = SBinary<double, double>::make(divide, result, second);
1039  } else {
1040  break;
1041  }
1042  }
1043 
1044  return result;
1045  }
1046 
1047 
1049  // COLUMN function builds an array from a table column.
1050  // format: COLUMN(<table>, <column>) or
1051  // COLUMN(<table>, <column>, <range>).
1052  // The word "COLUMN" has already been seen by the caller.
1053  parseDelimiter(stat, '(');
1054  std::string tabName = parseString(stat, "Table name expected.");
1055 
1056  // Column name.
1057  parseDelimiter(stat, ',');
1058  std::string colName = parseString(stat, "Column name expected.");
1059 
1060  // Optional range specification.
1061  RangeRep range;
1062  if(stat.delimiter(',')) {
1063  range = parseRange(stat);
1064  }
1065 
1066  parseDelimiter(stat, ')');
1067  return new AColumn(tabName, colName, range);
1068  }
1069 
1070 
1072  // ROW function builds an array from a table row.
1073  // format: ROW(<table>, <place>) or
1074  // ROW(<table>, <place>, <columns>).
1075  // The word "ROW" has already been seen by the caller.
1076  parseDelimiter(stat, '(');
1077  std::string tabName = parseString(stat, "Table name expected.");
1078 
1079  // Row position.
1080  parseDelimiter(stat, ',');
1081  PlaceRep row = parsePlace(stat);
1082 
1083  // Optional column specifications.
1084  std::vector<std::string> columns;
1085  if(stat.delimiter(',')) {
1086  columns = parseStringArray(stat);
1087  parseDelimiter(stat, ')');
1088  }
1089 
1090  return new ARow(tabName, row, columns);
1091  }
1092 
1094  // TABLE function generates an array from expressions.
1095  // format: "TABLE(<n>, <real>)" or
1096  // "TABLE(<n1>:<n2>, <real>)" or
1097  // "TABLE(<n1>:<n2>:<dn>, <real>)".
1098  // The word "TABLE" has already been read by the caller.
1099  parseDelimiter(stat, '(');
1100 
1101  // Read the array index set.
1102  int frst = int(std::round(parseRealConst(stat)));
1103  int last = 1;
1104  int step = 1;
1105 
1106  if(stat.delimiter(',')) {
1107  last = frst;
1108  frst = 1;
1109  } else if(stat.delimiter(':')) {
1110  last = int(std::round(parseRealConst(stat)));
1111  if(stat.delimiter(':')) {
1112  step = int(std::round(parseRealConst(stat)));
1113  }
1114  parseDelimiter(stat, ',');
1115  } else {
1116  throw ParseError("Expressions::parseTableGenerator()",
1117  "Index set incorrect or missing.");
1118  }
1119 
1120  // Check the array index set.
1121  if(frst <= 0 || last <= 0 || step <= 0) {
1122  throw ParseError("Expressions::parseTableGenerator()",
1123  "Invalid array index set.");
1124  }
1125 
1126  // Construct the expression generator.
1127  currentArray = new ATable(frst, last, step);
1128  currentArray->defineExpression(parseReal(stat));
1129  parseDelimiter(stat, ')');
1130 
1131  // The call to release() is required because of type constraints.
1132  return currentArray.release();
1133  }
1134 
1135 }
Tps< T > log(const Tps< T > &x)
Natural logarithm.
Definition: TpsMath.h:182
Tps< T > cos(const Tps< T > &x)
Cosine.
Definition: TpsMath.h:129
Tps< T > pow(const Tps< T > &x, int y)
Integer power.
Definition: TpsMath.h:76
Tps< T > tan(const Tps< T > &x)
Tangent.
Definition: TpsMath.h:147
Tps< T > exp(const Tps< T > &x)
Exponential.
Definition: TpsMath.h:165
Tps< T > sin(const Tps< T > &x)
Sine.
Definition: TpsMath.h:111
Tps< T > sqrt(const Tps< T > &x)
Square root.
Definition: TpsMath.h:91
FTps< T, N > erf(const FTps< T, N > &x, int trunc=(FTps< T, N >::EXACT))
Error function.
Definition: FTpsMath.h:385
T::PETE_Expr_t::PETE_Return_t max(const PETE_Expr< T > &expr, NDIndex< D > &loc)
Definition: ReductionLoc.h:84
T::PETE_Expr_t::PETE_Return_t min(const PETE_Expr< T > &expr, NDIndex< D > &loc)
Definition: ReductionLoc.h:76
std::complex< double > a
PETE_TUTree< FnAbs, typename T::PETE_Expr_t > abs(const PETE_Expr< T > &l)
PETE_TBTree< FnFmod, PETE_Scalar< Vektor< T1, Dim > >, typename T2::PETE_Expr_t > fmod(const Vektor< T1, Dim > &l, const PETE_Expr< T2 > &r)
PETE_TBTree< FnArcTan2, PETE_Scalar< Vektor< T1, Dim > >, typename T2::PETE_Expr_t > atan2(const Vektor< T1, Dim > &l, const PETE_Expr< T2 > &r)
arg(a))
PETE_TUTree< FnCeil, typename T::PETE_Expr_t > ceil(const PETE_Expr< T > &l)
Definition: PETE.h:728
PETE_TUTree< FnArcTan, typename T::PETE_Expr_t > atan(const PETE_Expr< T > &l)
Definition: PETE.h:727
PETE_TUTree< FnArcCos, typename T::PETE_Expr_t > acos(const PETE_Expr< T > &l)
Definition: PETE.h:725
PETE_TUTree< FnArcSin, typename T::PETE_Expr_t > asin(const PETE_Expr< T > &l)
Definition: PETE.h:726
PETE_TUTree< FnFloor, typename T::PETE_Expr_t > floor(const PETE_Expr< T > &l)
Definition: PETE.h:733
Inform & endl(Inform &inf)
Definition: Inform.cpp:42
const std::string name
Representation objects and parsers for attribute expressions.
Definition: Expressions.h:64
std::string parseStringValue(Statement &, const char msg[])
bool And(bool a, bool b)
Definition: Expressions.cpp:77
bool Or(bool a, bool b)
Definition: Expressions.cpp:74
double Add(double a, double b)
PtrToScalar< bool > parseBool(Statement &)
Parse boolean expression.
bool Ge(double a, double b)
Definition: Expressions.cpp:86
TFunction1< double, const std::vector< double > & > ArrayFun
PtrToScalar< double > parseReal(Statement &)
Parse real expression.
OwnPtr< ATable > currentArray
bool Lt(double a, double b)
Definition: Expressions.cpp:83
double Min(double a, double b)
PtrToArray< double > parseArrayTerm(Statement &stat)
double Max(double a, double b)
double Neg(double a)
PtrToScalar< bool > parseAnd(Statement &stat)
double Div(double a, double b)
PtrToScalar< double > parseTerm(Statement &stat)
bool Eq(double a, double b)
Definition: Expressions.cpp:92
double Tgauss(double a)
PtrToArray< double > parseRealConstArray(Statement &)
Parse real array constant.
double Rmsa(const std::vector< double > &array)
const T * find(const T table[], const std::string &name)
Look up name.
Definition: TFind.h:34
PtrToArray< double > parseRowGenerator(Statement &stat)
double Mod(double a, double b)
std::vector< std::string > parseStringArray(Statement &)
Parse string array.
RangeRep parseRange(Statement &)
Parse range specification.
PlaceRep parsePlace(Statement &)
Parse place specification.
double ranf()
double Maxa(const std::vector< double > &array)
bool Ne(double a, double b)
Definition: Expressions.cpp:95
SRefAttr< double > * parseReference(Statement &)
Parse variable reference.
std::vector< std::list< Token > > parseTokenListArray(Statement &)
Parse a token list array (for LIST commands).
PtrToArray< double > parseRealArray(Statement &)
Parse real array expression.
PtrToArray< double > parseArrayFactor(Statement &stat)
PtrToArray< double > parseTableGenerator(Statement &stat)
PtrToScalar< double > parseTableExpression(Statement &, const Table *)
Parse table expression (depends on a table's rows).
std::list< Token > parseTokenList(Statement &)
Parse a token list (for macro argument and the like).
double Mpy(double a, double b)
double AbsMax(const std::vector< double > &array)
TableRowRep parseTableRow(Statement &)
Parse a token list (for macro argument and the like).
std::string parseString(Statement &, const char msg[])
Parse string value.
PtrToScalar< bool > parseRelation(Statement &stat)
void parseBracketList(Statement &stat, char close, std::list< Token > &result)
PtrToArray< double > parseArrayPrimary(Statement &stat)
const Table * currentTable
double Mina(const std::vector< double > &array)
void parseDelimiter(Statement &stat, char delim)
Test for one-character delimiter.
PtrToScalar< double > parsePrimary(Statement &stat)
double Sub(double a, double b)
double parseRealConst(Statement &)
Parse real constant.
double Sign(double a)
PtrToArray< bool > parseBoolArray(Statement &)
Parse boolean array expression.
PtrToArray< double > parseColumnGenerator(Statement &stat)
bool Gt(double a, double b)
Definition: Expressions.cpp:89
bool Le(double a, double b)
Definition: Expressions.cpp:80
double getEkin()
PtrToScalar< double > parseFactor(Statement &stat)
double gauss()
bool warn
Warn flag.
Definition: Options.cpp:33
Random rangen
Definition: Options.cpp:36
A pointer to a scalar expression.
Definition: Expressions.h:109
An array of pointers to scalar expressions.
Definition: Expressions.h:127
A pointer to an array expression.
Definition: Expressions.h:180
An attribute defined as a reference to a scalar.
Definition: SRefAttr.h:48
The base class for all OPAL objects.
Definition: Object.h:48
double get_meanKineticEnergy() const
Object * find(const std::string &name)
Find entry.
Definition: OpalData.cpp:565
static OpalData * getInstance()
Definition: OpalData.cpp:195
PartBunchBase< double, 3 > * getPartBunch()
Definition: OpalData.cpp:376
Representation of a place within a beam line or sequence.
Definition: PlaceRep.h:41
void append(const std::string &, int occur)
Add a name/occurrence pair.
Definition: PlaceRep.cpp:59
Representation of a range within a beam line or sequence.
Definition: RangeRep.h:34
The base class for all OPAL tables.
Definition: Table.h:42
virtual Expressions::PtrToScalar< double > makeColumnExpression(const std::string &) const =0
Representation of a table row reference.
Definition: TableRowRep.h:36
A pointer which owns the object pointed at.
Definition: OwnPtr.h:31
bool isValid() const
Test for validity.
Definition: OwnPtr.h:144
Interface for statements.
Definition: Statement.h:38
Token & getCurrent()
Return current token and skip it.
Definition: Statement.cpp:74
bool str(std::string &value)
Return string value.
Definition: Statement.cpp:148
void restore()
Return to marked position.
Definition: Statement.cpp:175
bool keyword(const char *s)
Test for keyword.
Definition: Statement.cpp:121
void mark()
Mark position in command.
Definition: Statement.cpp:170
bool word(std::string &value)
Return word value.
Definition: Statement.cpp:159
bool boolean(bool &value)
Return boolean value.
Definition: Statement.cpp:55
bool real(double &value)
Return real value.
Definition: Statement.cpp:131
bool atEnd() const
Test for end of command.
Definition: Statement.cpp:50
bool delimiter(char c)
Test for delimiter.
Definition: Statement.cpp:101
Representation of a single input token.
Definition: Token.h:33
bool isDel(char del) const
Test for delimiter.
Definition: Token.cpp:92
void gauss(double &gr1, double &gr2)
Gaussian distribution.
double uniform()
Uniform distribution.
Parse exception.
Definition: ParseError.h:32
An array expression with two array operands.
Definition: ABinary.h:41
An array expression defined as a table column.
Definition: AColumn.h:36
An array expression defined by a list of scalar expressions.
Definition: AList.h:36
An expression defined as a reference to an array.
Definition: ARefExpr.h:42
An array expression defined as a table row.
Definition: ARow.h:35
A scalar expression with one array operand.
Definition: ASUnary.h:41
An array expression generated from a TABLE() function.
Definition: ATable.h:38
An array expression with one array operand.
Definition: AUnary.h:40
A scalar expression to retrieve an indexed component from an array.
Definition: Indexer.h:40
static Scalar< T > * make(const TFunction2< T, U > &, PtrToScalar< U > left, PtrToScalar< U > right)
Make a new expression.
Definition: SBinary.h:136
A scalar expression referring to a table cell.
Definition: SCell.h:36
A scalar constant expression.
Definition: SConstant.h:35
static double arcIn()
Return arc length at entrance SI().
Definition: SFunction.cpp:43
static double arcOut()
Return arc length at exit SO().
Definition: SFunction.cpp:65
static double arcCtr()
Return arc length at center SC().
Definition: SFunction.cpp:54
A scalar expression.
Definition: SHash.h:37
A scalar expression without operands.
Definition: SNull.h:38
static Scalar< T > * make(const TFunction0< T > &function)
Make expression.
Definition: SNull.h:124
An expression defined as a reference to a scalar.
Definition: SRefExpr.h:41
static Scalar< T > * make(const TFunction1< T, U > &function, PtrToScalar< U > operand)
Make a new expression.
Definition: SUnary.h:135
An operand-less function returning a T.
Definition: TFunction0.h:31
A function of one U, returning a T.
Definition: TFunction1.h:31
A function of two U's returning a T.
Definition: TFunction2.h:31
virtual bool getBool() const
Return value.
virtual std::string getString() const
Return value.