Bridge++  Ver. 1.1.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 #endif
185 
187 {
188  yy::parser parser(*this);
189 
190  parser.set_debug_level(m_trace);
191 
192  int retv = parser.parse(); // returns 0 if successful.
193 
194  if (retv == 0) {
195  if (m_trace) vout.paranoiac("%s: accept, result = %f\n", __func__, m_result);
196  return m_result;
197  } else {
198  if (m_trace) vout.paranoiac("%s: reject\n", __func__);
199  return double(); // should throw exception or abort.
200  }
201 }
202 
203 
204 void EvalExpr::set_result(double result)
205 {
206  if (m_trace) vout.paranoiac("%s: result = %f\n", __func__, result);
207 
208  m_result = result;
209 }
210 
211 
212 double EvalExpr::get_symbol_value(char const *name)
213 {
215 }
216 
217 
219 {
221 }
222 
223 
224 void EvalExpr::error(const std::string& msg)
225 {
226  vout.general("EvalExpr: %s\n", msg.c_str());
227 }