OOFEM  2.4
OOFEM.org - Object Oriented Finite Element Solver
parser.C
Go to the documentation of this file.
1 /*
2  *
3  * ##### ##### ###### ###### ### ###
4  * ## ## ## ## ## ## ## ### ##
5  * ## ## ## ## #### #### ## # ##
6  * ## ## ## ## ## ## ## ##
7  * ## ## ## ## ## ## ## ##
8  * ##### ##### ## ###### ## ##
9  *
10  *
11  * OOFEM : Object Oriented Finite Element Code
12  *
13  * Copyright (C) 1993 - 2013 Borek Patzak
14  *
15  *
16  *
17  * Czech Technical University, Faculty of Civil Engineering,
18  * Department of Structural Mechanics, 166 29 Prague, Czech Republic
19  *
20  * This library is free software; you can redistribute it and/or
21  * modify it under the terms of the GNU Lesser General Public
22  * License as published by the Free Software Foundation; either
23  * version 2.1 of the License, or (at your option) any later version.
24  *
25  * This program is distributed in the hope that it will be useful,
26  * but WITHOUT ANY WARRANTY; without even the implied warranty of
27  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
28  * Lesser General Public License for more details.
29  *
30  * You should have received a copy of the GNU Lesser General Public
31  * License along with this library; if not, write to the Free Software
32  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
33  */
34 
35 #include "parser.h"
36 #include "error.h"
37 #include "mathfem.h"
38 
39 #include <cctype>
40 #include <cstdlib>
41 #include <cstring>
42 
43 namespace oofem {
44 double Parser :: expr(bool get)
45 {
46  // get indicates whether there is need to to call get_token() to get next token.
47 
48  // expression:
49  // expression + term
50  // expression - term
51  //
52  double left = term(get);
53 
54  for ( ; ; ) { // forever
55  switch ( curr_tok ) {
56  case PLUS:
57  left += term(true);
58  break;
59  case MINUS:
60  left -= term(true);
61  break;
62  default:
63  return left;
64  }
65  }
66 }
67 
68 double Parser :: term(bool get) // multiply and divide
69 {
70  double d, left = prim(get);
71 
72  for ( ; ; ) { // forever
73  switch ( curr_tok ) {
74  case BOOL_EQ:
75  left = ( left == prim(true) );
76  break;
77  case BOOL_LE:
78  left = ( left <= prim(true) );
79  break;
80  case BOOL_LT:
81  left = ( left < prim(true) );
82  break;
83  case BOOL_GE:
84  left = ( left >= prim(true) );
85  break;
86  case BOOL_GT:
87  left = ( left > prim(true) );
88  break;
89  case MUL:
90  left *= prim(true);
91  break;
92  case DIV:
93  if ( ( d = prim(true) ) ) {
94  left /= d;
95  break;
96  }
97  OOFEM_ERROR("divide by 0");
98  return 1;
99 
100  case POW:
101  left = pow( left, prim(true) );
102  break;
103  default:
104  return left;
105  }
106  }
107 }
108 
109 double Parser :: prim(bool get) // handle primaries
110 {
111  if ( get ) {
112  get_token();
113  }
114 
115  switch ( curr_tok ) {
116  case NUMBER:
117  {
118  double v = number_value;
119  get_token();
120  return v;
121  }
122  case NAME:
123  {
124  // double &v = table[string_value];
125  // if (get_token() == ASSIGN) v = expr (true);
126  // return v;
127  if ( get_token() == ASSIGN ) {
128  name *n = insert(string_value);
129  n->value = expr(true);
130  return n->value;
131  }
132 
133  return look(string_value)->value;
134  }
135  case MINUS: // unary minus
136  return -prim(true);
137 
138  case LP:
139  {
140  double e = expr(true);
141  if ( curr_tok != RP ) {
142  OOFEM_ERROR(") expected");
143  return 1;
144  }
145 
146  get_token(); // eat ')'
147  return e;
148  }
149  case SQRT_FUNC:
150  {
151  double e = agr(true);
152  return sqrt(e);
153  }
154  case SIN_FUNC:
155  {
156  double e = agr(true);
157  return sin(e);
158  }
159  case COS_FUNC:
160  {
161  double e = agr(true);
162  return cos(e);
163  }
164  case TAN_FUNC:
165  {
166  double e = agr(true);
167  return tan(e);
168  }
169  case ATAN_FUNC:
170  {
171  double e = agr(true);
172  return atan(e);
173  }
174  case ASIN_FUNC:
175  {
176  double e = agr(true);
177  return asin(e);
178  }
179  case ACOS_FUNC:
180  {
181  double e = agr(true);
182  return acos(e);
183  }
184  case EXP_FUNC:
185  {
186  double e = agr(true);
187  return exp(e);
188  }
189  case HEAVISIDE_FUNC: //Heaviside function
190  {
191  double time = look("t")->value;
192  double e = agr(true);
193 
194  return time < e ? 0 : 1;
195  }
196 
197  default:
198  OOFEM_ERROR("primary expected");
199  return 1;
200  }
201 }
202 
203 double Parser :: agr(bool get)
204 {
205  if ( get ) {
206  get_token();
207  }
208 
209  switch ( curr_tok ) {
210  case LP:
211  {
212  double e = expr(true);
213  if ( curr_tok != RP ) {
214  OOFEM_ERROR(") expected");
215  return 1;
216  }
217 
218  get_token(); // eat ')'
219  return e;
220  }
221  default:
222  OOFEM_ERROR("function argument expected");
223  return 1;
224  }
225 }
226 
227 
229 {
230  char ch = 0;
231  int len;
232 
233  do { // skip whitespaces except '\n'
234  // if (! input->get(ch)) return curr_tok = END;
235  if ( !( ch = * ( parsedLine++ ) ) ) {
236  return curr_tok = END;
237  }
238  } while ( ch != '\n' && isspace(ch) );
239 
240  switch ( ch ) {
241  case 0:
242  case '\n':
243  return curr_tok = END;
244 
245  case ';':
246  return curr_tok = PRINT;
247 
248  case '*':
249  case '/':
250  case '^':
251  case '+':
252  case '-':
253  case '(':
254  case ')':
255  return curr_tok = Token_value(ch);
256 
257  case '=':
258  if ( ( ch = * ( parsedLine++ ) ) == '=' ) {
259  return curr_tok = BOOL_EQ;
260  } else {
261  parsedLine--;
262  return curr_tok = ASSIGN;
263  }
264 
265  case '<':
266  if ( ( ch = * ( parsedLine++ ) ) == '=' ) {
267  return curr_tok = BOOL_LE;
268  } else {
269  parsedLine--;
270  return curr_tok = BOOL_LT;
271  }
272 
273  case '>':
274  if ( ( ch = * ( parsedLine++ ) ) == '=' ) {
275  return curr_tok = BOOL_GE;
276  } else {
277  parsedLine--;
278  return curr_tok = BOOL_GT;
279  }
280 
281  case '0': case '1': case '2': case '3': case '4': case '5':
282  case '6': case '7': case '8': case '9': case '.':
283  //input->putback(ch);
284  parsedLine--;
285  //*input >> number_value;
286  char *endParse;
287  number_value = strtod(parsedLine, & endParse);
288  parsedLine = endParse;
289 
290  return curr_tok = NUMBER;
291 
292  default:
293  if ( isalpha(ch) ) {
294  // string_value = ch;
295  // while (input->get(ch) && isalnum (ch)) string_value += ch;
296  // input->putback (ch);
297  char *p = string_value;
298  * p++ = ch;
299  len = 1;
300  // while (input->get(ch) && isalnum (ch)) *p++ = ch;
301  while ( ( ch = * ( parsedLine++ ) ) && isalnum(ch) ) {
302  * p++ = ch;
303  if ( len++ >= Parser_CMD_LENGTH ) {
304  OOFEM_ERROR("command too long");
305  }
306  }
307 
308  * p = 0;
309  // input->putback(ch);
310  parsedLine--;
311 
312  if ( !strncmp(string_value, "sqrt", 4) ) {
313  return curr_tok = SQRT_FUNC;
314  } else if ( !strncmp(string_value, "sin", 3) ) {
315  return curr_tok = SIN_FUNC;
316  } else if ( !strncmp(string_value, "cos", 3) ) {
317  return curr_tok = COS_FUNC;
318  } else if ( !strncmp(string_value, "tan", 3) ) {
319  return curr_tok = TAN_FUNC;
320  } else if ( !strncmp(string_value, "atan", 4) ) {
321  return curr_tok = ATAN_FUNC;
322  } else if ( !strncmp(string_value, "asin", 4) ) {
323  return curr_tok = ASIN_FUNC;
324  } else if ( !strncmp(string_value, "acos", 4) ) {
325  return curr_tok = ACOS_FUNC;
326  } else if ( !strncmp(string_value, "exp", 4) ) {
327  return curr_tok = EXP_FUNC;
328  } else if ( !strncmp(string_value, "h", 1) ) {
329  return curr_tok = HEAVISIDE_FUNC;
330  } else if ( !strncmp(string_value, "pi", 2) ) {
331  number_value = M_PI;
332  return curr_tok = NUMBER;
333  } else {
334  return curr_tok = NAME;
335  }
336  }
337 
338  OOFEM_ERROR("bad token");
339  return curr_tok = PRINT;
340  }
341 }
342 
343 
344 Parser :: name *Parser :: look(const char *p, int ins)
345 {
346  int ii = 0; // hash
347  const char *pp = p;
348  while ( * pp ) {
349  ii = ii << 1 ^ * pp++;
350  }
351 
352  if ( ii < 0 ) {
353  ii = -ii;
354  }
355 
356  ii %= Parser_TBLSZ;
357 
358  for ( name *n = table [ ii ]; n; n = n->next ) { // search
359  if ( strcmp(p, n->string) == 0 ) {
360  return n;
361  }
362  }
363 
364  if ( ins == 0 ) {
365  OOFEM_ERROR("name not found");
366  }
367 
368  name *nn = new name;
369  nn->string = new char [ strlen(p) + 1 ];
370  strcpy(nn->string, p);
371  nn->value = 0.;
372  nn->next = table [ ii ];
373  table [ ii ] = nn;
374  return nn;
375 }
376 
377 
378 double Parser :: eval(const char *string, int &err)
379 {
380  parsedLine = string;
381  double result;
382  no_of_errors = 0;
383  do {
384  result = expr(true);
385  } while ( curr_tok != END );
386 
387  err = no_of_errors;
388  return result;
389 }
390 
392 {
393  // empty Parser table
394  name *entry, *next;
395  for ( int i = 0; i < Parser_TBLSZ; i++ ) {
396  if ( ( entry = table [ i ] ) ) {
397  do {
398  next = entry->next;
399  delete [] entry->string;
400  delete entry;
401  } while ( ( entry = next ) );
402 
403  table [ i ] = 0;
404  }
405  }
406 }
407 } // end namespace oofem
double expr(bool get)
Definition: parser.C:44
Token_value curr_tok
Definition: parser.h:80
const char * parsedLine
Definition: parser.h:89
int no_of_errors
Definition: parser.h:79
#define Parser_CMD_LENGTH
Definition: parser.h:41
double number_value
Definition: parser.h:87
void reset()
Definition: parser.C:391
name * look(const char *p, int ins=0)
Definition: parser.C:344
double term(bool get)
Definition: parser.C:68
#define M_PI
Definition: mathfem.h:52
double agr(bool get)
Definition: parser.C:203
#define OOFEM_ERROR(...)
Definition: error.h:61
char string_value[Parser_CMD_LENGTH]
Definition: parser.h:88
Token_value get_token()
Definition: parser.C:228
#define Parser_TBLSZ
Definition: parser.h:42
double prim(bool get)
Definition: parser.C:109
name * table[Parser_TBLSZ]
Definition: parser.h:86
the oofem namespace is to define a context or scope in which all oofem names are defined.
name * insert(const char *s)
Definition: parser.h:92
double eval(const char *string, int &err)
Definition: parser.C:378

This page is part of the OOFEM documentation. Copyright (c) 2011 Borek Patzak
Project e-mail: info@oofem.org
Generated at Tue Jan 2 2018 20:07:30 for OOFEM by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2011