TRUST 1.9.8
HPC thermohydraulic platform
Loading...
Searching...
No Matches
Parser.cpp
1/****************************************************************************
2* Copyright (c) 2026, CEA
3* All rights reserved.
4*
5* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
6* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
7* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
8* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
9*
10* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
11* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
12* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
13*
14*****************************************************************************/
15
16#include <StringTokenizer.h>
17#include <algorithm>
18#include <Parser.h>
19#include <queue>
20
21void debug(StringTokenizer*);
22
23/* Les identificateurs suivants doivent etre definis de maniere unique pour chaque fonction */
24
26{
28 state=0;
29 root=nullptr;
30 str = std::string("0");
31 impuls_tn = -1.;
32 impuls_T = 1.;
33 impuls_t0 = 0.;
34 impuls_tempo = 0.;
35 setNbVar(1);
36}
37
38Parser::Parser(const Parser& p) { set(p); }
39
40Parser::Parser(std::string& s, int n)
41{
43 state=0;
44 root=nullptr;
45 str = s;
46 impuls_tn = -1.;
47 impuls_T = 1.;
48 impuls_t0 = 0.;
49 impuls_tempo = 0.;
50 setNbVar(n);
51}
52
53void Parser::set(const Parser& p)
54{
56 state=p.state;
57 root=nullptr;
58 str = p.str;
64 ivar=p.ivar;
65 for (int i = 0; i < ivar; i++)
66 {
67 les_var[i] = p.les_var[i];
69 }
71}
72
74{
75 srand48(1);
76 map_function_["SIN"] = static_cast<int>(FUNCTION::SIN);
77 map_function_["ASIN"] = static_cast<int>(FUNCTION::ASIN);
78 map_function_["COS"] = static_cast<int>(FUNCTION::COS);
79 map_function_["ACOS"] = static_cast<int>(FUNCTION::ACOS);
80 map_function_["TAN"] = static_cast<int>(FUNCTION::TAN);
81 map_function_["ATAN"] = static_cast<int>(FUNCTION::ATAN);
82 map_function_["LN"] = static_cast<int>(FUNCTION::LN);
83 map_function_["EXP"] = static_cast<int>(FUNCTION::EXP);
84 map_function_["SQRT"] = static_cast<int>(FUNCTION::SQRT);
85 map_function_["INT"] = static_cast<int>(FUNCTION::ENT);
86 map_function_["ERF"] = static_cast<int>(FUNCTION::ERF);
87 map_function_["RND"] = static_cast<int>(FUNCTION::RND);
88 map_function_["COSH"] = static_cast<int>(FUNCTION::COSH);
89 map_function_["SINH"] = static_cast<int>(FUNCTION::SINH);
90 map_function_["TANH"] = static_cast<int>(FUNCTION::TANH);
91 map_function_["NOT"] = static_cast<int>(FUNCTION::NOT);
92 map_function_["ABS"] = static_cast<int>(FUNCTION::ABS);
93 map_function_["SGN"] = static_cast<int>(FUNCTION::SGN);
94 map_function_["ATANH"] = static_cast<int>(FUNCTION::ATANH);
95 c_pi.nommer(Nom("PI"));
96 c_pi.setValue(2*asin(1.));
97 addCst(c_pi);
98}
99
100void destroy(PNode* p)
101{
102 if (p!=nullptr)
103 {
104 if (p->left!=nullptr) destroy(p->left);
105 if (p->right!=nullptr) destroy(p->right);
106 delete p;
107 p=nullptr;
108 }
109}
110
112{
113 if (root !=nullptr) destroy(root);
114}
115
116void Parser::setNbVar(int nvar)
117{
118 maxvar=nvar;
119 ivar=0;
120 les_var.resize(maxvar);
121 les_var_names.dimensionner_force(maxvar);
122}
123
125{
126 if (root!=nullptr) destroy(root);
127 PSTACK(PNode) st_ob(20);
128 STACK(int) st_op(20);
129 StringTokenizer tok(str);
130 if (!tok.check_GRP())
131 {
132 Cerr << "Expression " << str << " does not contain the same number of opening and closing parenthesis." << finl;
134 }
135 state = 0;
136 while ( (tok.nextToken()) != StringTokenizer::EOS)
137 {
138 switch (state)
139 {
140 case 0:
141 parserState0(&tok,&st_ob,&st_op);
142 break;
143 case 1:
144 parserState1(&tok,&st_ob,&st_op);
145 break;
146 case 2:
147 parserState2(&tok,&st_ob,&st_op);
148 break;
149 case 3:
150 break;
151 default :
152 break;
153 }
154 }
155 parserState2(&tok,&st_ob,&st_op);
156 root = (PNode*) *st_ob.getBase();
157
158 // Conversion
159 PNodes.clear();
160 std::unordered_map<PNode*, int> nodeToIndex;
161 std::queue<PNode*> queue;
162 int currentIndex = 0;
163
164 // Start the traversal from the root
165 queue.push(root);
166 nodeToIndex[root] = currentIndex++;
167
168 while (!queue.empty())
169 {
170 PNode* current = queue.front();
171 queue.pop();
172
173 // Create a PNodePod from the current PNode
174 PNodePod pod;
175 pod.type = current->type;
176 pod.value = current->value;
177 pod.nvalue = current->nvalue;
178
179 // Process the left child
180 if (current->left)
181 {
182 if (nodeToIndex.find(current->left) == nodeToIndex.end())
183 {
184 nodeToIndex[current->left] = currentIndex++;
185 queue.push(current->left);
186 }
187 pod.left = nodeToIndex[current->left];
188 }
189 else
190 {
191 pod.left = -1; // Indicate no child
192 }
193
194 // Process the right child
195 if (current->right)
196 {
197 if (nodeToIndex.find(current->right) == nodeToIndex.end())
198 {
199 nodeToIndex[current->right] = currentIndex++;
200 queue.push(current->right);
201 }
202 pod.right = nodeToIndex[current->right];
203 }
204 else
205 {
206 pod.right = -1; // Indicate no child
207 }
208
209 PNodes.push_back(pod);
210 }
211}
212
214{
215 int p=100;
216 if (op == StringTokenizer::ADD)
217 p=1;
218 else if (op == StringTokenizer::SUBTRACT)
219 p=2;
220 else if (op == StringTokenizer::DIVIDE)
221 p=3;
222 else if (op == StringTokenizer::MULTIPLY)
223 p=3;
224 else if (op == StringTokenizer::POWER)
225 p=5;
226 else if (op == StringTokenizer::LT)
227 p=0;
228 else if (op == StringTokenizer::GT)
229 p=0;
230 else if (op == StringTokenizer::LE)
231 p=0;
232 else if (op == StringTokenizer::GE)
233 p=0;
234 else if (op == StringTokenizer::MOD)
235 p=0;
236 else if (op == StringTokenizer::MAX)
237 p=0;
238 else if (op == StringTokenizer::MIN)
239 p=0;
240 else if (op == StringTokenizer::AND)
241 p=0;
242 else if (op == StringTokenizer::OR)
243 p=0;
244 else if (op == StringTokenizer::EQ)
245 p=0;
246 else if (op == StringTokenizer::NEQ)
247 p=0;
248 else if (op == StringTokenizer::GRP)
249 p=-1;
250 else if (op == StringTokenizer::ENDGRP)
251 p=-1;
252 return p;
253}
254
255void Parser::parserState0(StringTokenizer* tokenizer, PSTACK(PNode)* ob, STACK(int)* op)
256{
257
258 if (tokenizer->type == StringTokenizer::STRING)
259 {
260 int trouv = searchVar(tokenizer->getSValue());
261
262 if (trouv>-1)
263 {
264 PNode *node = new PNode();
265 node->type = PNode_type::VAR;
266 node->value = trouv;
267 ob->push(node);
268 state = 2;
269 }
270 else
271 {
272 const std::string& func = tokenizer->getSValue();
273 trouv = searchFunc(func);
274 if (trouv>-1)
275 {
276 op->push(-trouv); // OC 01/2005 : Attention, on stocke l'oppose de l'indice trouve afin de bien dissocier les operateurs binaires des fonctions unaires.
277 state = 0;
278 }
279 else
280 {
281 trouv = searchCst(func);
282 if (trouv>=0)
283 {
284 PNode *node = new PNode();
285 node->type = PNode_type::VALUE;
286 node->nvalue = les_cst(trouv).getValue();
287 ob->push(node);
288 state = 2;
289 }
290 else
291 {
292 Cerr << "Error in Parser::parserState0 during interpretation of the following string :\n ";
293 Cerr << str << "\n";
294 Cerr << " identifier " << func << " unknown " << finl;
295 // permet d avoir 0 erreur valgrind avec cppunit
296 root=(PNode*) *(ob->getBase());
297 Cerr << "List of known var "<<finl;
298 for (auto name : les_var_names)
299 Cerr<<name<< " ";
300 Cerr<<finl;
302 }
303 }
304 }
305 }
306 else if (tokenizer->type == StringTokenizer::NUMBER)
307 {
308 PNode* node;
309 node = new PNode();
310 node->type = PNode_type::VALUE;
311 //Cout << "NODE NUMBER = " << PNode_type::VALUE << finl;
312 node->nvalue = tokenizer->getNValue();
313 ob->push(node);
314 state = 2;
315 }
316 else if (tokenizer->type == StringTokenizer::ADD )
317 {
318 PNode* node;
319 op->push(StringTokenizer::ADD);
320 node = new PNode();
321 node->type = PNode_type::VALUE;
322 node->nvalue = 0.;
323 ob->push(node);
324 state = 1;
325 }
326 else if (tokenizer->type == StringTokenizer::SUBTRACT)
327 {
328 PNode* node;
330 node = new PNode();
331 node->type = PNode_type::VALUE;
332 node->nvalue = 0.;
333 ob->push(node);
334 state = 1;
335 }
336 else if (tokenizer->type == StringTokenizer::GRP )
337 {
338 op->push(StringTokenizer::GRP);
339 state = 0;
340 }
341}
342
343void Parser::parserState1(StringTokenizer* tokenizer, PSTACK(PNode)* ob, STACK(int)* op)
344{
345 if (tokenizer->type == StringTokenizer::STRING)
346 {
347 int trouv = searchVar(tokenizer->getSValue());
348 if (trouv>-1)
349 {
350 //Cerr << "variable = " << trouv << " " << tokenizer->getSValue() << finl;
351 PNode *node = new PNode();
352 node->type = PNode_type::VAR;
353 node->value = trouv;
354 ob->push(node);
355 state = 2;
356 }
357 else
358 {
359 const std::string& func = tokenizer->getSValue();
360 trouv = searchFunc(func);
361 if (trouv>-1)
362 {
363 op->push(-trouv);
364 state = 0;
365 }
366 else
367 {
368 trouv = searchCst(func);
369 if (trouv>=0)
370 {
371 PNode *node = new PNode();
372 node->type = PNode_type::VALUE;
373 node->nvalue = les_cst(trouv).getValue();
374 ob->push(node);
375 state = 2;
376 }
377 else
378 {
379 Cerr << "Error in Parser::parserState1 during interpretation of the following string :\n ";
380 Cerr << str << "\n";
381 Cerr << " identifier " << func << " unknown !! " << finl;
382 Cerr << "List of known var "<<finl;
383 for (auto name : les_var_names)
384 Cerr<<name<< " ";
385 Cerr<<finl;
387 }
388 }
389 }
390 }
391 else if (tokenizer->type == StringTokenizer::NUMBER )
392 {
393 PNode* node = new PNode();
394 node->type = PNode_type::VALUE;
395 node->nvalue = tokenizer->getNValue();
396 ob->push(node);
397 state = 2;
398 }
399 else if (tokenizer->type ==StringTokenizer::GRP)
400 {
401 op->push(StringTokenizer::GRP);
402 state = 0;
403 }
404 else
405 {
406 Cerr << "state 1 error !! " << finl;
408 }
409}
410
412{
413 return ((type == StringTokenizer::ADD )||( type == StringTokenizer::SUBTRACT )||( type == StringTokenizer::MULTIPLY )||( type == StringTokenizer::DIVIDE )||( type == StringTokenizer::POWER )||( type == StringTokenizer::LT )||( type == StringTokenizer::GT )||( type == StringTokenizer::LE )||( type == StringTokenizer::GE )||( type == StringTokenizer::MOD) || ( type == StringTokenizer::MAX) || ( type == StringTokenizer::MIN) || ( type == StringTokenizer::AND)||( type == StringTokenizer::OR)||( type == StringTokenizer::EQ)||( type == StringTokenizer::NEQ));
414}
415
416void Parser::parserState2(StringTokenizer* tokenizer, PSTACK(PNode)* ob, STACK(int)* op)
417{
418 int op_read;
419 if (test_op_binaire( tokenizer->type))
420 {
421 // case StringTokenizer::ADD: case StringTokenizer::SUBTRACT : case StringTokenizer::MULTIPLY: case StringTokenizer::DIVIDE: case StringTokenizer::POWER:
422 op_read = tokenizer->type;
423 //Cerr << "op read = " << (char) op_read << finl;
424 if (!op->isEmpty())
425 {
426 int tmpi = op->peek();
427 //Cerr << "op tmpi = " << (char) tmpi << finl;
428 while (precedence(tmpi) >= precedence(op_read) )
429 {
430 int tmp = op->pop();
431 //Cerr << "op tmp = " << (char) tmp << finl;
432 if (test_op_binaire( tmp)) // c est un operateur binaire
433 {
434 PNode* deux = (PNode*) ob->pop();
435 PNode* un = (PNode*) ob->pop();
436 PNode* node = new PNode();
437 node->type = PNode_type::OP;
438 node->value=tmp;
439 node->left = un;
440 node->right = deux;
441 ob->push(node);
442 }
443 else if (tmp<=0) // c est une fonction unaire
444 {
445 PNode* un = (PNode*) ob->pop();
446 PNode* node = new PNode();
447 node->type=PNode_type::FUNCTION;
448 node->value=tmp;
449 node->left = un;
450 node->right=nullptr;
451 ob->push(node);
452 }
453 else if ( (tmp == StringTokenizer::GRP) || (tmp == StringTokenizer::ENDGRP) )
454 {
455 }
456 else
457 {
458 Cerr << "Unknown operation !!! " << finl;
460 break;
461 }
462 if (!op->isEmpty()) tmpi = op->peek();
463 else break ;
464 }
465 }
466 op->push(op_read);
467 state =1;
468 }
469 else if (tokenizer->type == StringTokenizer::ENDGRP)
470 {
471 op_read = tokenizer->type;
472 if (!op->isEmpty())
473 {
474 int tmp = op->pop();
475 while (tmp != StringTokenizer::GRP )
476 {
477 if (test_op_binaire(tmp)) // c est un operateur binaire
478 {
479 PNode* deux = (PNode*) ob->pop();
480 PNode* un = (PNode*) ob->pop();
481 PNode* node = new PNode();
482 node->type = PNode_type::OP;
483 node->value=tmp;
484 node->left = un;
485 node->right=deux;
486 ob->push(node);
487 }
488 else if (tmp<=0) // c est une fonction unaire
489 {
490 PNode* un = (PNode*) ob->pop();
491 PNode* node = new PNode();
492 node->type=PNode_type::FUNCTION;
493 node->value=tmp;
494 node->left = un;
495 node->right=nullptr;
496 ob->push(node);
497 }
498 else if ( (tmp == StringTokenizer::GRP) || (tmp == StringTokenizer::ENDGRP) )
499 {
500 }
501 else
502 {
503 Cerr << "Unknown operation !!! " << finl;
505 break;
506 }
507
508 if (!op->isEmpty()) tmp = op->pop();
509 else break ;
510 }
511 }
512 state = 2;
513 }
514 else if (tokenizer->type == StringTokenizer::EOS)
515 {
516 while (!op->isEmpty())
517 {
518 //Cout << "fin" << finl;
519 int tmp = op->pop();
520 if (test_op_binaire(tmp))// c est un operateur binaire
521 {
522 PNode* deux = (PNode*) ob->pop();
523 PNode* un = (PNode*) ob->pop();
524 PNode* node = new PNode();
525 node->type = PNode_type::OP;
526 node->value=tmp;
527 node->left = un;
528 node->right=deux;
529 ob->push(node);
530 }
531 else if (tmp<=0) // c est une fonction unaire
532 {
533 PNode* un = (PNode*) ob->pop();
534 PNode* node = new PNode();
535 node->type=PNode_type::FUNCTION;
536 node->value=tmp;
537 node->left = un;
538 node->right=nullptr;
539 ob->push(node);
540 }
541 else if ( (tmp == StringTokenizer::GRP) || (tmp == StringTokenizer::ENDGRP) )
542 {
543 }
544 else
545 {
546 Cerr << "Unknown operation !!! " << finl;
548 break;
549 }
550 }
551 state = 0;
552 }
553 else
554 {
555 Cerr << "Error state 2 !!! " <<tokenizer->type<<" "<<tokenizer->getSValue()<<" "<<tokenizer->getNValue()<< finl;
556 Cerr<<" StringTokenizer::ADD "<<StringTokenizer::ADD<<" StringTokenizer::SUBTRACT "<<StringTokenizer::SUBTRACT<<" StringTokenizer::MULTIPLY "<<StringTokenizer::MULTIPLY;
557 Cerr<<" StringTokenizer::DIVIDE "<<StringTokenizer::DIVIDE<<" StringTokenizer::POWER "<<StringTokenizer::POWER<<" StringTokenizer::LT "<<StringTokenizer::LT<<" StringTokenizer::GT "<<StringTokenizer::GT;
558 Cerr<<" StringTokenizer::LE "<<StringTokenizer::LE<<" StringTokenizer::GE "<<StringTokenizer::GE<<" StringTokenizer::MOD "<<StringTokenizer::MOD<<" ENDStringTokenizer::GRP "<<StringTokenizer::ENDGRP;
559 Cerr<<" StringTokenizer::EOS "<<StringTokenizer::EOS<<" StringTokenizer::NUMBER ";
560 Cerr<<StringTokenizer::NUMBER<<" StringTokenizer::STRING "<<StringTokenizer::STRING<<finl;
562 }
563}
564
565void Parser::addVar(const char *vv)
566{
567 if (searchVar(vv)!=-1)
568 {
569 Cerr<<"Warning in Parser::addVar "<< vv << " already in Parser"<<finl;
570 if (strcmp(vv,"x")==0 || strcmp(vv,"y")==0 || strcmp(vv,"z")==0 || strcmp(vv,"t")==0
571 || strcmp(vv,"X")==0 || strcmp(vv,"Y")==0 || strcmp(vv,"Z")==0 || strcmp(vv,"T")==0)
572 {
574 }
575 }
576 if (ivar<maxvar)
577 {
578 Nom s(vv);
579 s.majuscule();
580 les_var.resize(ivar+1);
581 les_var_names[ivar] = s;
582 ivar++;
583 }
584 else
585 {
586 Cerr << "Maximum " << maxvar << " variables !! " << finl;
588 }
589}
590
591int Parser::searchCst(const std::string& v)
592{
593 int i=0;
594 Nom nv(v);
595 for (auto& itr : les_cst)
596 {
597 Constante& cst = ref_cast(Constante,itr);
598 std::string ss(cst.le_nom());
599 std::transform(ss.begin(), ss.end(), ss.begin(), ::toupper);
600 if (nv == Nom(ss)) return i;
601 i++;
602 }
603 return -1;
604}
605
606
607int Parser::searchFunc(const std::string& f)
608{
609 std::string function_name(f);
610 std::transform(function_name.begin(), function_name.end(), function_name.begin(), ::toupper);
611 auto it = map_function_.find(function_name);
612 if (it != map_function_.end())
613 return it->second + 1; // OC: pour ne pas utiliser le zero car sinon conflit avec la nouvelle numerotation des operateurs binaires.
614 else
615 return -1;
616}
617
618void Parser::addCst(const Constante& cst)
619{
620 les_cst.add(cst);
621}
622
623void debug(StringTokenizer * t)
624{
626 Cout << "STRING : " << t->getSValue() << finl;
627 else if (t->type == StringTokenizer::NUMBER)
628 Cout << "NUMBER : " << t->getNValue() << finl;
629 else if (t->type == StringTokenizer::EOS)
630 Cout << "END " << finl;
631 else
632 Cout << "OP : " << (int)t->type << finl;
633}
634
635
Definit une constante dans le jeu de donnees.
Definition Constante.h:27
const Nom & le_nom() const override
Donne le nom de l'Objet_U Methode a surcharger : renvoie "neant" dans cette implementation.
Definition Constante.h:39
class Nom Une chaine de caractere pour nommer les objets de TRUST
Definition Nom.h:31
Nom & majuscule()
Transforme le nom en majuscules Seules les lettres 'a'-'z' sont modifiees.
Definition Nom.cpp:180
int right
Definition PNode.h:50
int value
Definition PNode.h:52
double nvalue
Definition PNode.h:53
int left
Definition PNode.h:49
int type
Definition PNode.h:51
Definition PNode.h:21
int type
Definition PNode.h:35
int value
Definition PNode.h:36
PNode * left
Definition PNode.h:33
double nvalue
Definition PNode.h:37
PNode * right
Definition PNode.h:34
void addVar(const char *)
Definition Parser.cpp:565
Noms les_var_names
Definition Parser.h:164
Parser()
Definition Parser.cpp:25
int ivar
Definition Parser.h:167
virtual void setNbVar(int nvar)
Definition Parser.cpp:116
std::vector< PNodePod > PNodes
Definition Parser.h:161
double impuls_t0
Definition Parser.h:156
ArrOfDouble les_var
Definition Parser.h:163
Constante c_pi
Definition Parser.h:154
virtual ~Parser()
Definition Parser.cpp:111
std::string str
Definition Parser.h:162
int searchVar(const std::string &s)
Definition Parser.h:149
int maxvar
Definition Parser.h:167
void init_parser()
Definition Parser.cpp:73
double impuls_T
Definition Parser.h:155
PNode * root
Definition Parser.h:160
void parserState1(StringTokenizer *, PSTACK(PNode) *, STACK(int) *)
Definition Parser.cpp:343
void parserState0(StringTokenizer *, PSTACK(PNode) *, STACK(int) *)
Definition Parser.cpp:255
double impuls_tn
Definition Parser.h:157
double impuls_tempo
Definition Parser.h:158
void set(const Parser &)
Definition Parser.cpp:53
int state
Definition Parser.h:153
int searchFunc(const std::string &v)
Definition Parser.cpp:607
int test_op_binaire(int type)
Definition Parser.cpp:411
std::map< std::string, int > map_function_
Definition Parser.h:166
static int precedence(int)
Definition Parser.cpp:213
virtual void parseString()
Definition Parser.cpp:124
int searchCst(const std::string &v)
Definition Parser.cpp:591
void addCst(const Constante &cst)
Definition Parser.cpp:618
void parserState2(StringTokenizer *, PSTACK(PNode) *, STACK(int) *)
Definition Parser.cpp:416
static void exit(int exit_code=-1)
Routine de sortie de TRUST dans une region Kokkos.
Definition Process.cpp:455
static const int AND
const std::string & getSValue()
static const int NUMBER
static const int EOS
static const int STRING
static const int MULTIPLY
static const int MIN
static const int GT
static const int POWER
static const int GRP
static const int GE
static const int LT
static const int LE
static const int MOD
static const int DIVIDE
static const int EQ
static const int ENDGRP
static const int SUBTRACT
static const int ADD
static const int OR
static const int MAX
static const int NEQ