OOFEM 3.0
Loading...
Searching...
No Matches
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 - 2025 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
43namespace oofem {
44double 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
68double 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 case MOD:
99 if ( ( d = prim(true) ) ) {
100 left = fmod(left,d);
101 break;
102 }
103 OOFEM_ERROR("divide by 0");
104 case POW:
105 left = pow( left, prim(true) );
106 break;
107 default:
108 return left;
109 }
110 }
111}
112
113double Parser :: prim(bool get) // handle primaries
114{
115 if ( get ) {
116 get_token();
117 }
118
119 switch ( curr_tok ) {
120 case NUMBER:
121 {
122 double v = number_value;
123 get_token();
124 return v;
125 }
126 case NAME:
127 {
128 // double &v = table[string_value];
129 // if (get_token() == ASSIGN) v = expr (true);
130 // return v;
131
132 Token_value next_tok = get_token();
133 char varname [32];
134 strncpy(varname, string_value, 31);
135 varname[31] = 0;
136 int indx = 0; // scalar context
137 if ( next_tok == LB ) {
138 // array access
139 double val = expr(true);
140 if ( curr_tok != RB ) {
141 OOFEM_ERROR("] expected");
142 return 1;
143 }
144
145 next_tok = get_token(); // eat ']'
146 indx = (int)val;
147 }
148 if ( next_tok == ASSIGN ) {
149 // name *n = insert(string_value);
150 // save string_value
151
152 setVariableValue(varname, indx, expr(true));
153 //n->value = expr(true);
154 return getVariableValue(varname, indx);
155 }
156
157 //return look(string_value)->value;
158 return getVariableValue(string_value, indx);
159 }
160 case MINUS: // unary minus
161 return -prim(true);
162
163 case LP:
164 {
165 double e = expr(true);
166 if ( curr_tok != RP ) {
167 OOFEM_ERROR(") expected");
168 }
169
170 get_token(); // eat ')'
171 return e;
172 }
173 case SQRT_FUNC:
174 {
175 double e = agr(true);
176 return sqrt(e);
177 }
178 case SIN_FUNC:
179 {
180 double e = agr(true);
181 return sin(e);
182 }
183 case COS_FUNC:
184 {
185 double e = agr(true);
186 return cos(e);
187 }
188 case TAN_FUNC:
189 {
190 double e = agr(true);
191 return tan(e);
192 }
193 case ATAN_FUNC:
194 {
195 double e = agr(true);
196 return atan(e);
197 }
198 case ASIN_FUNC:
199 {
200 double e = agr(true);
201 return asin(e);
202 }
203 case ACOS_FUNC:
204 {
205 double e = agr(true);
206 return acos(e);
207 }
208 case EXP_FUNC:
209 {
210 double e = agr(true);
211 return exp(e);
212 }
213 case INT_FUNC:
214 {
215 double e = agr(true);
216 return (int)(e);
217 }
218 case HEAVISIDE_FUNC: //Heaviside function
219 {
220 double time = look("t")->doubleValue;
221 double e = agr(true);
222
223 return time < e ? 0 : 1;
224 }
225
226 case HEAVISIDE_FUNC1: //Heaviside function
227 {
228 double e = agr(true);
229
230 return e<0 ? 0 : 1;
231 }
232
233 default:
234 OOFEM_ERROR("primary expected");
235 }
236}
237
238double Parser :: agr(bool get)
239{
240 if ( get ) {
241 get_token();
242 }
243
244 switch ( curr_tok ) {
245 case LP:
246 {
247 double e = expr(true);
248 if ( curr_tok != RP ) {
249 OOFEM_ERROR(") expected");
250 }
251
252 get_token(); // eat ')'
253 return e;
254 }
255 default:
256 OOFEM_ERROR("function argument expected");
257 }
258}
259
260
261Parser :: Token_value Parser :: get_token()
262{
263 char ch = 0;
264 int len;
265
266 do { // skip whitespaces except '\n'
267 // if (! input->get(ch)) return curr_tok = END;
268 if ( !( ch = * ( parsedLine++ ) ) ) {
269 return curr_tok = END;
270 }
271 } while ( ch != '\n' && isspace(ch) );
272
273 switch ( ch ) {
274 case 0:
275 case '\n':
276 return curr_tok = END;
277
278 case ';':
279 return curr_tok = PRINT;
280
281 case '*':
282 case '/':
283 case '^':
284 case '+':
285 case '-':
286 case '(':
287 case ')':
288 case '%':
289 case '[':
290 case ']':
291 return curr_tok = Token_value(ch);
292
293 case '=':
294 if ( ( ch = * ( parsedLine++ ) ) == '=' ) {
295 return curr_tok = BOOL_EQ;
296 } else {
297 parsedLine--;
298 return curr_tok = ASSIGN;
299 }
300
301 case '<':
302 if ( ( ch = * ( parsedLine++ ) ) == '=' ) {
303 return curr_tok = BOOL_LE;
304 } else {
305 parsedLine--;
306 return curr_tok = BOOL_LT;
307 }
308
309 case '>':
310 if ( ( ch = * ( parsedLine++ ) ) == '=' ) {
311 return curr_tok = BOOL_GE;
312 } else {
313 parsedLine--;
314 return curr_tok = BOOL_GT;
315 }
316
317 case '0': case '1': case '2': case '3': case '4': case '5':
318 case '6': case '7': case '8': case '9': case '.':
319 //input->putback(ch);
320 parsedLine--;
321 //*input >> number_value;
322 char *endParse;
323 number_value = strtod(parsedLine, & endParse);
324 parsedLine = endParse;
325
326 return curr_tok = NUMBER;
327
328 default:
329 if ( isalpha(ch) ) {
330 // string_value = ch;
331 // while (input->get(ch) && isalnum (ch)) string_value += ch;
332 // input->putback (ch);
333 char *p = string_value;
334 * p++ = ch;
335 len = 1;
336 // while (input->get(ch) && isalnum (ch)) *p++ = ch;
337 while ( ( ch = * ( parsedLine++ ) ) && isalnum(ch) ) {
338 * p++ = ch;
339 if ( len++ >= Parser_CMD_LENGTH ) {
340 OOFEM_ERROR("command too long");
341 }
342 }
343
344 * p = 0;
345 // input->putback(ch);
346 parsedLine--;
347
348 if ( !strncmp(string_value, "sqrt", 4) ) {
349 return curr_tok = SQRT_FUNC;
350 } else if ( !strncmp(string_value, "sin", 3) ) {
351 return curr_tok = SIN_FUNC;
352 } else if ( !strncmp(string_value, "cos", 3) ) {
353 return curr_tok = COS_FUNC;
354 } else if ( !strncmp(string_value, "tan", 3) ) {
355 return curr_tok = TAN_FUNC;
356 } else if ( !strncmp(string_value, "atan", 4) ) {
357 return curr_tok = ATAN_FUNC;
358 } else if ( !strncmp(string_value, "asin", 4) ) {
359 return curr_tok = ASIN_FUNC;
360 } else if ( !strncmp(string_value, "acos", 4) ) {
361 return curr_tok = ACOS_FUNC;
362 } else if ( !strncmp(string_value, "exp", 3) ) {
363 return curr_tok = EXP_FUNC;
364 } else if ( !strncmp(string_value, "int", 3) ) {
365 return curr_tok = INT_FUNC;
366 } else if ( !strncmp(string_value, "h1", 2) ) {
367 return curr_tok = HEAVISIDE_FUNC1;
368 } else if ( !strncmp(string_value, "h", 1) ) {
369 return curr_tok = HEAVISIDE_FUNC;
370 } else if ( !strncmp(string_value, "pi", 2) ) {
372 return curr_tok = NUMBER;
373 } else {
374 return curr_tok = NAME;
375 }
376 }
377
378 OOFEM_ERROR("bad token");
379 }
380}
381
382
383Parser :: name *Parser :: look(const char *p, int ins)
384{
385 int ii = 0; // hash
386 const char *pp = p;
387 while ( * pp ) {
388 ii = ii << 1 ^ * pp++;
389 }
390
391 if ( ii < 0 ) {
392 ii = -ii;
393 }
394
395 ii %= Parser_TBLSZ;
396
397 for ( name *n = table [ ii ]; n; n = n->next ) { // search
398 if ( strcmp(p, n->string) == 0 ) {
399 return n;
400 }
401 }
402
403 if ( ins == 0 ) {
404 OOFEM_ERROR("name not found");
405 }
406
407 name *nn = new name;
408 nn->string = new char [ strlen(p) + 1 ];
409 strcpy(nn->string, p);
410 nn->doubleValue = 0.;
411 nn->arrayValue.clear();
412 nn->size = -1;
413 nn->next = table [ ii ];
414 table [ ii ] = nn;
415 return nn;
416}
417
418
419double Parser :: eval(const char *string, int &err)
420{
421 parsedLine = string;
422 double result;
423 no_of_errors = 0;
424 do {
425 result = expr(true);
426 } while ( curr_tok != END );
427
428 err = no_of_errors;
429 return result;
430}
431
432
433void Parser :: eval(const char *string, FloatArray& answer, const char* resultName, int &err)
434{
435 parsedLine = string;
436 no_of_errors = 0;
437 do {
438 //double result = expr(true);
439 expr(true);
440 } while ( curr_tok != END );
441
442 err = no_of_errors;
443 name *n = look(resultName, false);
444
445 if ( n->size == 0 ) {
446 answer.resize(1);
447 answer.at(1) = n->doubleValue;
448 } else {
449 answer = n->arrayValue;
450 }
451}
452
453void Parser :: reset()
454{
455 // empty Parser table
456 name *entry, *next;
457 for ( int i = 0; i < Parser_TBLSZ; i++ ) {
458 if ( ( entry = table [ i ] ) ) {
459 do {
460 next = entry->next;
461 delete [] entry->string;
462 delete entry;
463 } while ( ( entry = next ) );
464
465 table [ i ] = 0;
466 }
467 }
468}
469
470void Parser::setVariableValue(const char *vname, int indx, double value) {
471 name *n = look(vname, true);
472 if ( indx == 0 ) {
473 // check if variable context allowed
474 if ( n->size <= 0) {
475 n->doubleValue = value;
476 n->size = 0; // scalar context
477 } else {
478 OOFEM_ERROR("Variable %s: using scalar context of array variable", vname);
479 }
480 } else {
481 if ( n->size == 0 ) {
482 OOFEM_ERROR("Variable %s: using array context of scalar variable", vname);
483 } else {
484 if ( indx > n->size ) {
485 n->arrayValue.resize(indx);
486 n->size = indx;
487 }
488 n->arrayValue.at(indx) = value;
489 }
490 }
491}
492
493double
494Parser::getVariableValue(const char *vname, int indx) {
495 name *n = look(vname, false);
496
497 if ( indx == 0 && n->size == 0 ) {
498 return n->doubleValue;
499 } else if ( indx > 0 && n->size > 0 ) {
500 return n->arrayValue.at(indx);
501 } else {
502 OOFEM_ERROR("Variable %s access error", vname);
503 }
504}
505
506
507} // end namespace oofem
void resize(Index s)
Definition floatarray.C:94
double & at(Index i)
Definition floatarray.h:202
double term(bool get)
Definition parser.C:68
Token_value curr_tok
Definition parser.h:84
int no_of_errors
Definition parser.h:83
double agr(bool get)
Definition parser.C:238
@ HEAVISIDE_FUNC
Definition parser.h:78
@ HEAVISIDE_FUNC1
Definition parser.h:78
double number_value
Definition parser.h:95
void setVariableValue(const char *name, int indx, double value)
Definition parser.C:470
double expr(bool get)
Definition parser.C:44
name * look(const char *p, int ins=0)
Definition parser.C:383
Token_value get_token()
Definition parser.C:261
name * table[Parser_TBLSZ]
Definition parser.h:94
double getVariableValue(const char *name, int indx)
Definition parser.C:494
char string_value[Parser_CMD_LENGTH]
Definition parser.h:96
const char * parsedLine
Definition parser.h:97
double prim(bool get)
Definition parser.C:113
#define OOFEM_ERROR(...)
Definition error.h:79
#define M_PI
Definition mathfem.h:52
#define Parser_CMD_LENGTH
Definition parser.h:42
#define Parser_TBLSZ
Definition parser.h:43
FloatArray arrayValue
Definition parser.h:92
double doubleValue
Definition parser.h:91

This page is part of the OOFEM-3.0 documentation. Copyright Copyright (C) 1994-2025 Borek Patzak Bořek Patzák
Project e-mail: oofem@fsv.cvut.cz
Generated at for OOFEM by doxygen 1.15.0 written by Dimitri van Heesch, © 1997-2011