Bridge++  Ver. 1.2.x
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
evalexpr.cpp
Go to the documentation of this file.
1 
13 #include "evalexpr.h"
14 
15 // global symbol entries
16 namespace {
17  struct _init_function
18  {
19  char const *name;
20  function_t func;
21  };
22 
23  struct _init_variable
24  {
25  char const *name;
26  double val;
27  };
28 }
29 
30 // import global symbol definitions
31 #include "evalexpr_global.h"
32 
33 // register global symbols
34 namespace {
35  SymbolTable init_global_symbol()
36  {
37  SymbolTable table;
38 
39  for (int i = 0; arithmetic_functions[i].name != 0; ++i) {
40  table.put_symbol(arithmetic_functions[i].name, arithmetic_functions[i].func);
41  }
42 
43  for (int i = 0; predefined_constants[i].name != 0; ++i) {
44  table.put_symbol(predefined_constants[i].name, predefined_constants[i].val);
45  }
46 
47  return table;
48  }
49 }
50 
51 SymbolTable EvalExpr::global_symbol_table = init_global_symbol();
52 
53 
54 // lexer interface for parser
55 int yylex(EvalExpr::semantic_type *yylval, EvalExpr& driver)
56 {
57  return driver.next_token(*yylval);
58 }
59 
60 
62 {
63  if (m_trace) vout.paranoiac("%s: pos = %d, length = %zu\n", __func__, m_pos, m_src.length());
64 
65  char *p = const_cast<char *>(m_src.c_str()) + m_pos;
66 
67  int c = *p;
68 
69  // skip spaces
70  while ((c == ' ') || (c == '\t'))
71  {
72  c = *++p;
73  ++m_pos;
74  }
75 
76  if (c == '\0') return 0;
77 
78  if (c == '\n') return token::EOL;
79 
80  // find number [0-9](.[0-9]*)(e[+-]?[0-9]+)
81  if (isdigit(c)) {
82  enum
83  {
84  IN_INT, IN_FRAC, IN_EXP, IN_EXP_DIGIT
85  }
86  state = IN_INT;
87 
88  int i;
89  for (i = 0; ; c = p[++i]) {
90  if (state == IN_INT) {
91  if (isdigit(c)) {
92  } else if (c == '.') {
93  state = IN_FRAC;
94  } else if (c == 'e') {
95  state = IN_EXP;
96  } else {
97  break; // accept
98  }
99  } else if (state == IN_FRAC) {
100  if (isdigit(c)) {
101  } else if (c == 'e') {
102  state = IN_EXP;
103  } else {
104  break; // accept
105  }
106  } else if ((state == IN_EXP) || (state == IN_EXP_DIGIT)) {
107  if (isdigit(c)) {
108  } else if ((state == IN_EXP) && ((c == '+') || (c == '-'))) {
109  state = IN_EXP_DIGIT;
110  } else {
111  break; // accept
112  }
113  } else {
114  abort();
115  }
116  }
117 
118  double x = atof(p);
119 
120 #ifdef __PGI
121  char *symbol = strdup(p);
122 #else
123  char *symbol = strndup(p, i + 1);
124 #endif
125  symbol[i] = '\0';
126 
127  if (m_trace) vout.paranoiac("%s: accept: number: \"%s\"(%d), %f\n", __func__, symbol, i, x);
128 
129  free(symbol);
130 
131  yylval.val = x;
132  m_pos += i;
133 
134  return token::NUMBER;
135  }
136 
137  // find identifier [a-zA-Z]([.a-zA-Z0-9]*)
138  if (isalpha(c)) {
139  int i;
140  for (i = 0; isalnum(p[i]) || p[i] == '.'; ++i) {
141  continue;
142  }
143 
144 #ifdef __PGI
145  char *symbol = strdup(p);
146 #else
147  char *symbol = strndup(p, i + 1);
148 #endif
149  symbol[i] = '\0';
150 
151  if (m_trace) vout.paranoiac("%s: accept: identifier: \"%s\" (%d)\n", __func__, symbol, i);
152 
153  yylval.sym = symbol;
154  m_pos += i;
155 
156  return token::IDENTIFIER;
157  }
158 
159  ++m_pos;
160 
161  return c;
162 }
163 
164 
165 #if 0
166 bool EvalExpr::parse(double& result)
167 {
168  yy::parser parser(*this);
169 
170  parser.set_debug_level(m_trace);
171 
172  int retv = parser.parse(); // returns 0 if successful.
173 
174  if (retv == 0) {
175  if (m_trace) vout.paranoiac("%s: accept, result = %f\n", __func__, m_result);
176  result = m_result;
177  } else {
178  if (m_trace) vout.paranoiac("%s: reject\n", __func__);
179  result = double();
180  }
181 
182  return retv == 0;
183 }
184 
185 
186 #endif
187 
189 {
190  yy::parser parser(*this);
191 
192  parser.set_debug_level(m_trace);
193 
194  int retv = parser.parse(); // returns 0 if successful.
195 
196  if (retv == 0) {
197  if (m_trace) vout.paranoiac("%s: accept, result = %f\n", __func__, m_result);
198  return m_result;
199  } else {
200  if (m_trace) vout.paranoiac("%s: reject\n", __func__);
201  return double(); // should throw exception or abort.
202  }
203 }
204 
205 
206 void EvalExpr::set_result(double result)
207 {
208  if (m_trace) vout.paranoiac("%s: result = %f\n", __func__, result);
209 
210  m_result = result;
211 }
212 
213 
214 double EvalExpr::get_symbol_value(char const *name)
215 {
217 }
218 
219 
221 {
223 }
224 
225 
226 void EvalExpr::error(const std::string& msg)
227 {
228  vout.general("EvalExpr: %s\n", msg.c_str());
229 }
function_t get_symbol_function(const std::string &name) const
bool put_symbol(const std::string &name, const double value)
BridgeIO vout
Definition: bridgeIO.cpp:207
void error(const std::string &msg)
Definition: evalexpr.cpp:226
double get_symbol_value(const std::string &name) const
function_t get_symbol_function(char const *name)
Definition: evalexpr.cpp:220
void general(const char *format,...)
Definition: bridgeIO.cpp:38
virtual int parse()
double parse()
Definition: evalexpr.cpp:188
static SymbolTable global_symbol_table
Definition: evalexpr.h:73
int yylex(EvalExpr::semantic_type *yylval, EvalExpr &driver)
Definition: evalexpr.cpp:55
unsigned int m_pos
Definition: evalexpr.h:68
bool m_trace
Definition: evalexpr.h:71
void set_debug_level(debug_level_type l)
Set the current debugging level.
Symbol semantic values.
EvalExpr class for algebraic expression in parameter strings.
Definition: evalexpr.h:38
void paranoiac(const char *format,...)
Definition: bridgeIO.cpp:62
double m_result
Definition: evalexpr.h:69
double get_symbol_value(char const *name)
Definition: evalexpr.cpp:214
double(* function_t)(double)
void set_result(double result)
Definition: evalexpr.cpp:206
A Bison parser.
int next_token(semantic_type &yylval)
Definition: evalexpr.cpp:61
const std::string m_src
Definition: evalexpr.h:67