1 /*  $Id: expr.cpp 500405 2016-05-04 15:18:35Z ivanov $
2  * ===========================================================================
3  *
4  *                            PUBLIC DOMAIN NOTICE
5  *               National Center for Biotechnology Information
6  *
7  *  This software/database is a "United States Government Work" under the
8  *  terms of the United States Copyright Act.  It was written as part of
9  *  the author's official duties as a United States Government employee and
10  *  thus cannot be copyrighted.  This software/database is freely available
11  *  to the public for use. The National Library of Medicine and the U.S.
12  *  Government have not placed any restriction on its use or reproduction.
13  *
14  *  Although all reasonable efforts have been taken to ensure the accuracy
15  *  and reliability of the software and data, the NLM and the U.S.
16  *  Government do not and cannot warrant the performance or results that
17  *  may be obtained by using this software or data. The NLM and the U.S.
18  *  Government disclaim all warranties, express or implied, including
19  *  warranties of performance, merchantability or fitness for any particular
20  *  purpose.
21  *
22  *  Please cite the author in any work or product based on this material.
23  *
24  * ===========================================================================
25  *
26  * Author: Sergey Sikorskiy, Mikhail Zakharov
27  *
28  * File Description:
29  *      Expression parsing and evaluation.
30  *
31  * ===========================================================================
32  */
33 
34 #include <ncbi_pch.hpp>
35 
36 #include <corelib/expr.hpp>
37 
38 #include <math.h>
39 #include <limits>
40 
41 
42 #define BINARY(opd) (opd >= ePOW)
43 
44 
45 BEGIN_NCBI_SCOPE
46 
47 ////////////////////////////////////////////////////////////////////////////////
CExprValue(void)48 CExprValue::CExprValue(void)
49 : ival(0)
50 , m_sval("")
51 , m_Var(NULL)
52 , m_Pos(0)
53 , m_Tag()
54 {
55 }
56 
CExprValue(string value)57 CExprValue::CExprValue(string value)
58 : ival(0),
59 m_sval(value),
60 m_Var(NULL),
61 m_Pos(0),
62 m_Tag(eSTRING)
63 {
64 }
65 
66 
CExprValue(const CExprValue & value)67 CExprValue::CExprValue(const CExprValue& value)
68 : ival(value.ival)
69 , m_sval("")
70 , m_Var(value.m_Var)
71 , m_Pos(value.m_Pos)
72 , m_Tag(value.m_Tag)
73 {
74 }
75 
CExprValue(Uint4 value)76 CExprValue::CExprValue(Uint4 value)
77 : ival(value)
78 , m_sval("")
79 , m_Var(NULL)
80 , m_Pos(0)
81 , m_Tag(eINT)
82 {
83 }
84 
CExprValue(Int4 value)85 CExprValue::CExprValue(Int4 value)
86 : ival(value)
87 , m_sval("")
88 , m_Var(NULL)
89 , m_Pos(0)
90 , m_Tag(eINT)
91 {
92 }
93 
CExprValue(Uint8 value)94 CExprValue::CExprValue(Uint8 value)
95 : ival(0)
96 , m_sval("")
97 , m_Var(NULL)
98 , m_Pos(0)
99 , m_Tag(eINT)
100 {
101     if (static_cast<Uint8>(numeric_limits<Int8>::max()) < value) {
102         NCBI_THROW2(CExprParserException,
103                 eTypeConversionError,
104                 "Value too big to fit in the 8-byte signed integer type",
105                 m_Pos);
106     }
107 
108     ival = static_cast<Int8>(value);
109 }
110 
111 
CExprValue(Int8 value)112 CExprValue::CExprValue(Int8 value)
113 : ival(value)
114 , m_sval("")
115 , m_Var(NULL)
116 , m_Pos(0)
117 , m_Tag(eINT)
118 {
119 }
120 
CExprValue(double value)121 CExprValue::CExprValue(double value)
122 : fval(value)
123 , m_sval("")
124 , m_Var(NULL)
125 , m_Pos(0)
126 , m_Tag(eFLOAT)
127 {
128 }
129 
CExprValue(bool value)130 CExprValue::CExprValue(bool value)
131 : bval(value)
132 , m_sval("")
133 , m_Var(NULL)
134 , m_Pos(0)
135 , m_Tag(eBOOL)
136 {
137 }
138 
139 ////////////////////////////////////////////////////////////////////////////////
CExprSymbol(void)140 CExprSymbol::CExprSymbol(void)
141 : m_Tag()
142 , m_IntFunc1(NULL)
143 , m_Val()
144 , m_Next(NULL)
145 {
146 }
147 
~CExprSymbol(void)148 CExprSymbol::~CExprSymbol(void)
149 {
150     delete m_Next;
151 }
152 
CExprSymbol(const char * name,Uint4 value)153 CExprSymbol::CExprSymbol(const char* name, Uint4 value)
154 : m_Tag(eVARIABLE)
155 , m_IntFunc1(NULL)
156 , m_Val(value)
157 , m_Name(name)
158 , m_Next(NULL)
159 {
160 }
161 
CExprSymbol(const char * name,Int4 value)162 CExprSymbol::CExprSymbol(const char* name, Int4 value)
163 : m_Tag(eVARIABLE)
164 , m_IntFunc1(NULL)
165 , m_Val(value)
166 , m_Name(name)
167 , m_Next(NULL)
168 {
169 }
170 
CExprSymbol(const char * name,Uint8 value)171 CExprSymbol::CExprSymbol(const char* name, Uint8 value)
172 : m_Tag(eVARIABLE)
173 , m_IntFunc1(NULL)
174 , m_Val(value)
175 , m_Name(name)
176 , m_Next(NULL)
177 {
178 }
179 
CExprSymbol(const char * name,Int8 value)180 CExprSymbol::CExprSymbol(const char* name, Int8 value)
181 : m_Tag(eVARIABLE)
182 , m_IntFunc1(NULL)
183 , m_Val(value)
184 , m_Name(name)
185 , m_Next(NULL)
186 {
187 }
188 
CExprSymbol(const char * name,bool value)189 CExprSymbol::CExprSymbol(const char* name, bool value)
190 : m_Tag(eVARIABLE)
191 , m_IntFunc1(NULL)
192 , m_Val(value)
193 , m_Name(name)
194 , m_Next(NULL)
195 {
196 }
197 
CExprSymbol(const char * name,double value)198 CExprSymbol::CExprSymbol(const char* name, double value)
199 : m_Tag(eVARIABLE)
200 , m_IntFunc1(NULL)
201 , m_Val(value)
202 , m_Name(name)
203 , m_Next(NULL)
204 {
205 }
206 
CExprSymbol(const char * name,string value)207 CExprSymbol::CExprSymbol(const char* name, string value)
208 : m_Tag(eVARIABLE)
209 , m_IntFunc1(NULL)
210 , m_Val(value)
211 , m_Name(name)
212 , m_Next(NULL)
213 {
214 }
215 
CExprSymbol(const char * name,FIntFunc1 value)216 CExprSymbol::CExprSymbol(const char* name, FIntFunc1 value)
217 : m_Tag(eIFUNC1)
218 , m_IntFunc1(value)
219 , m_Val((Int8)0)
220 , m_Name(name)
221 , m_Next(NULL)
222 {
223 }
224 
CExprSymbol(const char * name,FIntFunc2 value)225 CExprSymbol::CExprSymbol(const char* name, FIntFunc2 value)
226 : m_Tag(eIFUNC2)
227 , m_IntFunc2(value)
228 , m_Val((Int8)0)
229 , m_Name(name)
230 , m_Next(NULL)
231 {
232 }
233 
CExprSymbol(const char * name,FFloatFunc1 value)234 CExprSymbol::CExprSymbol(const char* name, FFloatFunc1 value)
235 : m_Tag(eFFUNC1)
236 , m_FloatFunc1(value)
237 , m_Val((Int8)0)
238 , m_Name(name)
239 , m_Next(NULL)
240 {
241 }
242 
CExprSymbol(const char * name,FFloatFunc2 value)243 CExprSymbol::CExprSymbol(const char* name, FFloatFunc2 value)
244 : m_Tag(eFFUNC2)
245 , m_FloatFunc2(value)
246 , m_Val((Int8)0)
247 , m_Name(name)
248 , m_Next(NULL)
249 {
250 }
251 
CExprSymbol(const char * name,FBoolFunc1 value)252 CExprSymbol::CExprSymbol(const char* name, FBoolFunc1 value)
253 : m_Tag(eBFUNC1)
254 , m_BoolFunc1(value)
255 , m_Val((Int8)0)
256 , m_Name(name)
257 , m_Next(NULL)
258 {
259 }
260 
CExprSymbol(const char * name,FBoolFunc2 value)261 CExprSymbol::CExprSymbol(const char* name, FBoolFunc2 value)
262 : m_Tag(eBFUNC2)
263 , m_BoolFunc2(value)
264 , m_Val((Int8)0)
265 , m_Name(name)
266 , m_Next(NULL)
267 {
268 }
269 
CExprSymbol(const char * name,FStringFunc1 value)270 CExprSymbol::CExprSymbol(const char* name, FStringFunc1 value)
271 : m_Tag(eSFUNC1)
272 , m_StringFunc1(value)
273 , m_Val((Int8)0)
274 , m_Name(name)
275 , m_Next(NULL)
276 {
277 }
278 
279 ////////////////////////////////////////////////////////////////////////////////
280 static
to_int(Int8 m_Val)281 Int8 to_int(Int8 m_Val)
282 {
283     return m_Val;
284 }
285 
286 static
to_float(double m_Val)287 double to_float(double m_Val)
288 {
289     return m_Val;
290 }
291 
292 static
gcd(Int8 x,Int8 y)293 Int8 gcd(Int8 x, Int8 y)
294 {
295     while (x) {
296         Int8 r = y%x;
297         y=x;
298         x=r;
299     }
300 
301     return y;
302 }
303 
304 static
invmod(Int8 x,Int8 y)305 Int8 invmod(Int8 x, Int8 y)
306 {
307     Int8 m = y;
308     Int8 u = 1, v = 0;
309     Int8 s = 0, t = 1;
310 
311     while (x) {
312         Int8 q = y/x;
313         Int8 r = y%x;
314         Int8 a = s - q*u;
315         Int8 b = t - q*v;
316         y=x; s=u; t=v;
317         x=r; u=a; v=b;
318     }
319 
320     if (y!=1) return 0;
321 
322     while (s<0) s+=m;
323 
324     return s;
325 }
326 
327 static
prime(Int8 n)328 Int8 prime(Int8 n)
329 {
330     if (n <= 3) {
331         return n;
332     }
333     n |= 1;
334     while (true) {
335         Int8 m = (Int8)sqrt((double)n) + 1;
336         Int8 k = 3;
337         while (true) {
338             if (k > m) {
339                 return n;
340             }
341             if (n % k == 0) break;
342             k += 2;
343         }
344         n += 2;
345     }
346 }
347 
348 /*
349 static
350 char*
351 to_bin(int nval, char* pbuf, int nbufsize)
352 {
353     int ncnt;
354     int bcnt;
355     int nlen = sizeof(int) * 8 + sizeof(int);
356 
357     if (pbuf != NULL && nbufsize > nlen)
358     {
359         pbuf[nlen] = '\0';
360         pbuf[nlen - 1] = 'b';
361         for(ncnt = 0, bcnt = nlen - 2; ncnt < nlen; ncnt ++, bcnt --)
362         {
363             if (ncnt > 0 && (ncnt % 8) == 0)
364             {
365                 pbuf[bcnt] = '.';
366                 bcnt --;
367             }
368             pbuf[bcnt] = (nval & (1 << ncnt))? '1' : '0';
369         }
370     }
371 
372     return pbuf;
373 }
374 */
375 
string_hash_function(const char * p)376 unsigned string_hash_function(const char* p)
377 {
378     unsigned h = 0, g;
379     while(*p) {
380         h = (h << 4) + *p++;
381         if ((g = h & 0xF0000000) != 0) {
382             h ^= g >> 24;
383         }
384         h &= ~g;
385     }
386     return h;
387 }
388 
389 ////////////////////////////////////////////////////////////////////////////////
GetErrCodeString(void) const390 const char* CExprParserException::GetErrCodeString(void) const
391 {
392     switch (GetErrCode()) {
393         case eParseError: return "eParseError";
394         case eTypeConversionError: return "eTypeConversionError";
395         default:
396             break;
397     }
398 
399     return CException::GetErrCodeString();
400 }
401 
ReportExtra(ostream & out) const402 void CExprParserException::ReportExtra(ostream& out) const
403 {
404     out << "pos: " << m_Pos;
405 }
406 
x_Assign(const CException & src)407 void CExprParserException::x_Assign(const CException& src)
408 {
409     CException::x_Assign(src);
410 
411     const CExprParserException& other = dynamic_cast<const CExprParserException&>(src);
412     m_Pos = other.m_Pos;
413 }
414 
415 ////////////////////////////////////////////////////////////////////////////////
CExprParser(CExprParser::TParserFlags ParserFlags)416 CExprParser::CExprParser(CExprParser::TParserFlags ParserFlags)
417 : m_Buf(NULL)
418 , m_Pos(0)
419 , m_TmpVarCount(0)
420 , m_ParserFlags(ParserFlags)
421 {
422     memset(hash_table, 0, sizeof(hash_table));
423 
424     AddSymbol("abs",    (CExprSymbol::FFloatFunc1)fabs);
425     AddSymbol("acos",   (CExprSymbol::FFloatFunc1)acos);
426     AddSymbol("asin",   (CExprSymbol::FFloatFunc1)asin);
427     AddSymbol("atan",   (CExprSymbol::FFloatFunc1)atan);
428     AddSymbol("atan2",  (CExprSymbol::FFloatFunc2)atan2);
429     AddSymbol("cos",    (CExprSymbol::FFloatFunc1)cos);
430     AddSymbol("cosh",   (CExprSymbol::FFloatFunc1)cosh);
431     AddSymbol("exp",    (CExprSymbol::FFloatFunc1)exp);
432     AddSymbol("log",    (CExprSymbol::FFloatFunc1)log);
433     AddSymbol("log10",  (CExprSymbol::FFloatFunc1)log10);
434     AddSymbol("sin",    (CExprSymbol::FFloatFunc1)sin);
435     AddSymbol("sinh",   (CExprSymbol::FFloatFunc1)sinh);
436     AddSymbol("tan",    (CExprSymbol::FFloatFunc1)tan);
437     AddSymbol("tanh",   (CExprSymbol::FFloatFunc1)tanh);
438     AddSymbol("sqrt",   (CExprSymbol::FFloatFunc1)sqrt);
439 
440     AddSymbol("float",  to_float);
441     AddSymbol("int",    to_int);
442 
443     AddSymbol("gcd",    gcd);
444     AddSymbol("invmod", invmod);
445 
446     AddSymbol("prime",  prime);
447 
448     AddSymbol("pi",     3.1415926535897932385E0);
449     AddSymbol("e",      2.7182818284590452354E0);
450 }
451 
~CExprParser(void)452 CExprParser::~CExprParser(void)
453 {
454     for (int i = 0; i < hash_table_size; ++i) {
455         delete hash_table[i];
456     }
457 }
458 
459 int CExprParser::sm_lpr[eTERMINALS] = {
460     2, 0, 0, 0,       // eBEGIN, eOPERAND, eERROR, eEND,
461     4, 4,             // eLPAR, eRPAR
462     5, 98, 98,        // eFUNC, ePOSTINC, ePOSTDEC,
463     98, 98, 98, 98, 98, 98, // ePREINC, ePREDEC, ePLUS, eMINUS, eNOT, eCOM,
464     90,               // ePOW,
465     80, 80, 80,       // eMUL, eDIV, eMOD,
466     70, 70,           // eADD, eSUB,
467     60, 60, 60,       // eASL, eASR, eLSR,
468     50, 50, 50, 50,   // eGT, eGE, eLT, eLE,
469     40, 40,           // eEQ, eNE,
470     38,               // eAND,
471     36,               // eXOR,
472     34,               // eOR,
473     20, 20, 20, 20, 20, 20, 20, //eSET, eSETADD, eSETSUB, eSETMUL, eSETDIV, eSETMOD,
474     20, 20, 20, 20, 20, 20, // eSETASL, eSETASR, eSETLSR, eSETAND, eSETXOR, eSETOR,
475     10               // eCOMMA
476 };
477 
478 int CExprParser::sm_rpr[eTERMINALS] = {
479     0, 0, 0, 1,       // eBEGIN, eOPERAND, eERROR, eEND,
480     110, 3,           // eLPAR, eRPAR
481     120, 99, 99,      // eFUNC, ePOSTINC, ePOSTDEC
482     99, 99, 99, 99, 99, 99, // ePREINC, ePREDEC, ePLUS, eMINUS, eNOT, eCOM,
483     95,               // ePOW,
484     80, 80, 80,       // eMUL, eDIV, eMOD,
485     70, 70,           // eADD, eSUB,
486     60, 60, 60,       // eASL, eASR, eLSR,
487     50, 50, 50, 50,   // eGT, eGE, eLT, eLE,
488     40, 40,           // eEQ, eNE,
489     38,               // eAND,
490     36,               // eXOR,
491     34,               // eOR,
492     25, 25, 25, 25, 25, 25, 25, //eSET, eSETADD, eSETSUB, eSETMUL, eSETDIV, eSETMOD,
493     25, 25, 25, 25, 25, 25, // eSETASL, eSETASR, eSETLSR, eSETAND, eSETXOR, eSETOR,
494     15               // eCOMMA
495 };
496 
GetSymbol(const char * name) const497 CExprSymbol* CExprParser::GetSymbol(const char* name) const
498 {
499     unsigned h = string_hash_function(name) % hash_table_size;
500     CExprSymbol* sp = NULL;
501 
502     for (sp = hash_table[h]; sp != NULL; sp = sp->m_Next) {
503         if (sp->m_Name.compare(name) == 0) {
504             return sp;
505         }
506     }
507 
508     return sp;
509 }
510 
511 CExprParser::EOperator
Scan(bool operand)512 CExprParser::Scan(bool operand)
513 {
514     char sym_name[max_expression_length], *np;
515 
516     while (isspace(m_Buf[m_Pos])) m_Pos += 1;
517 
518     switch (m_Buf[m_Pos++]) {
519       case '\0':
520         return eEND;
521       case '(':
522         return eLPAR;
523       case ')':
524         return eRPAR;
525       case '+':
526         if (m_Buf[m_Pos] == '+') {
527             m_Pos += 1;
528             return operand ? ePREINC : ePOSTINC;
529         } else if (m_Buf[m_Pos] == '=') {
530             m_Pos += 1;
531             return eSETADD;
532         }
533         return operand ? ePLUS : eADD;
534       case '-':
535         if (m_Buf[m_Pos] == '-') {
536             m_Pos += 1;
537             return operand ? ePREDEC : ePOSTDEC;
538         } else if (m_Buf[m_Pos] == '=') {
539             m_Pos += 1;
540             return eSETSUB;
541         }
542         return operand ? eMINUS : eSUB;
543       case '!':
544         return IfChar('=', eNE, eNOT);
545       case '~':
546         return eCOM;
547       case '*':
548         return IfLongest2ElseChar('*', '=', eSETPOW, ePOW, eSETMUL, eMUL);
549       case '/':
550         if(LogicalOnly())
551             goto l_SkipDivision;            // goto to default is justified - complete code refactoring otherwise (MZ)
552         return IfChar('=', eSETDIV, eDIV);
553       case '%':
554         return IfChar('=', eSETMOD, eMOD);
555       case '<':
556         return IfLongest2ElseChar('<', '=', eSETASL, eASL, eLE, eLT);
557       case '>':
558         if (m_Buf[m_Pos] == '>') {
559             if (m_Buf[m_Pos+1] == '>') {
560                 if (m_Buf[m_Pos+2] == '=') {
561                     m_Pos += 3;
562                     return eSETLSR;
563                 }
564                 m_Pos += 2;
565                 return eLSR;
566             } else if (m_Buf[m_Pos+1] == '=') {
567                 m_Pos += 2;
568                 return eSETASR;
569             } else {
570                 m_Pos += 1;
571                 return eASR;
572             }
573         } else if (m_Buf[m_Pos] == '=') {
574             m_Pos += 1;
575             return eGE;
576         }
577         return eGT;
578       case '=':
579         return IfChar('=', eEQ, eSET);
580       case '&':
581         return IfElseChar(
582                 '&', eAND,
583                 '=', eSETAND,
584                 eAND);
585       case '|':
586         return IfElseChar(
587                 '|', eOR,
588                 '=', eSETOR,
589                 eOR);
590       case '^':
591         return IfChar('=', eSETXOR, eXOR);
592       case ',':
593         return eCOMMA;
594       case '0': case '1': case '2': case '3': case '4':
595       case '5': case '6': case '7': case '8': case '9':
596         if(LogicalOnly())
597             goto l_SkipDivision;        // goto default justified to avoid code refactoring
598         {
599             Int8 ival;
600             double fval;
601             int ierr, ferr;
602             char *ipos;
603             char *fpos;
604 
605 #ifdef NCBI_OS_MSWIN
606             int n = 0;
607             ierr = sscanf(m_Buf+m_Pos-1, "%I64i%n", &ival, &n) != 1;
608             ipos = const_cast<char*>(m_Buf+m_Pos-1+n);
609 #else
610             errno = 0;
611 #if SIZEOF_LONG == 8
612             ival = strtoul(m_Buf+m_Pos-1, &ipos, 0);
613 #else
614             ival = strtoull(m_Buf+m_Pos-1, &ipos, 0);
615 #endif
616             ierr = errno;
617 #endif
618             errno = 0;
619             fval = strtod(m_Buf+m_Pos-1, &fpos);
620             ferr = errno;
621 
622             if (ierr && ferr) {
623                 ReportError("bad numeric constant");
624                 return eERROR;
625             }
626 
627             if (m_v_sp == max_stack_size) {
628                 ReportError("stack overflow");
629                 return eERROR;
630             }
631 
632             if (!ierr && ipos >= fpos) {
633                 m_VStack[m_v_sp].SetType(CExprValue::eINT);
634                 m_VStack[m_v_sp].ival = ival;
635                 m_Pos = (int)(ipos - m_Buf);
636             } else {
637                 m_VStack[m_v_sp].SetType(CExprValue::eFLOAT);
638                 m_VStack[m_v_sp].fval = fval;
639                 m_Pos = (int)(fpos - m_Buf);
640             }
641 
642             m_VStack[m_v_sp].m_Pos = m_Pos;
643             m_VStack[m_v_sp++].m_Var = NULL;
644 
645             return eOPERAND;
646         }
647 
648       case '"':             // String literal case
649         {
650             string StringConstant(m_Buf+m_Pos);     // Not including the \"
651             size_t pos=StringConstant.find('"');
652 
653             StringConstant = StringConstant.substr(0, pos);
654 
655             m_VStack[m_v_sp].SetType(CExprValue::eSTRING);
656 
657             m_VStack[m_v_sp].m_sval = StringConstant;     //assign string
658             m_Pos += (int)pos+1;                          // move m_Pos
659 
660             m_VStack[m_v_sp].m_Pos = m_Pos;
661             m_VStack[m_v_sp].m_Var = NULL;
662             m_v_sp++;
663 
664             return eOPERAND;
665         }
666 
667       default:
668       l_SkipDivision:
669         m_Pos -= 1;
670         np = sym_name;
671 
672         while (isalnum(m_Buf[m_Pos]) || m_Buf[m_Pos] == '$' || m_Buf[m_Pos] == '_' || (((m_Buf[m_Pos]=='/') || (m_Buf[m_Pos]=='.') ) && LogicalOnly())) {
673             *np++ = m_Buf[m_Pos++];
674         }
675 
676         if (np == m_Buf) {
677             ReportError("Bad character");
678             return eERROR;
679         }
680 
681         *np = '\0';
682 
683         // Check for true/false ...
684         if (strcmp(sym_name, "true") == 0) {
685             m_VStack[m_v_sp].SetType(CExprValue::eBOOL);
686             m_VStack[m_v_sp].bval = true;
687 
688             m_VStack[m_v_sp].m_Pos = m_Pos;
689             m_VStack[m_v_sp++].m_Var = NULL;
690 
691             return eOPERAND;
692         } else if (strcmp(sym_name, "false") == 0) {
693             m_VStack[m_v_sp].SetType(CExprValue::eBOOL);
694             m_VStack[m_v_sp].bval = false;
695 
696             m_VStack[m_v_sp].m_Pos = m_Pos;
697             m_VStack[m_v_sp++].m_Var = NULL;
698 
699             return eOPERAND;
700         }
701 
702         CExprSymbol* sym = NULL;
703 
704         if (AutoCreateVariable() == eAllowAutoVar) {
705             sym = AddSymbol(sym_name, Int8(0));
706         } else {
707             sym = GetSymbol(sym_name);
708             if (!sym) {
709                 ReportError(string("Invalid symbol name: ") + sym_name);
710                 return eERROR;
711             }
712         }
713 
714         if (m_v_sp == max_stack_size) {
715             ReportError("stack overflow");
716             return eERROR;
717         }
718 
719         m_VStack[m_v_sp] = sym->m_Val;
720         m_VStack[m_v_sp].m_Pos = m_Pos;
721         m_VStack[m_v_sp++].m_Var = sym;
722 
723         return (sym->m_Tag == CExprSymbol::eVARIABLE) ? eOPERAND : eFUNC;
724     }
725 }
726 
Assign(void)727 bool CExprParser::Assign(void)
728 {
729     CExprValue& v = m_VStack[m_v_sp-1];
730     if (v.m_Var == NULL) {
731         ReportError(v.m_Pos, "variable expected");
732         return false;
733     } else {
734         v.m_Var->m_Val = v;
735         return true;
736     }
737 }
738 
Parse(const char * str)739 void CExprParser::Parse(const char* str)
740 {
741     // char var_name[16];
742     m_Buf = str;
743     m_v_sp = 0;
744     m_o_sp = 0;
745     m_Pos = 0;
746     m_OStack[m_o_sp++] = eBEGIN;
747     bool operand = true;
748     int n_args = 0;
749 
750     while (true) {
751       next_token:
752         int op_pos = m_Pos;
753 
754         EOperator oper = Scan(operand);
755 
756         if (oper == eERROR) {
757             return;
758         }
759 
760         if (!operand) {
761             if (!BINARY(oper) && oper != eEND && oper != ePOSTINC
762                 && oper != ePOSTDEC && oper != eRPAR)
763             {
764                 ReportError(op_pos, "operator expected");
765                 return;
766             }
767             if (oper != ePOSTINC && oper != ePOSTDEC && oper != eRPAR) {
768                 operand = true;
769             }
770         } else {
771             if (oper == eOPERAND) {
772                 operand = false;
773                 n_args += 1;
774                 continue;
775             }
776             if (BINARY(oper) || oper == eRPAR) {
777                 ReportError(op_pos, "operand expected");
778                 return;
779             }
780         }
781 
782         n_args = 1;
783 
784         while (sm_lpr[m_OStack[m_o_sp-1]] >= sm_rpr[oper]) {
785             int cop = m_OStack[--m_o_sp];
786 
787             switch (cop) {
788               case eBEGIN:
789                 if (oper == eRPAR) {
790                     ReportError("Unmatched ')'");
791                     return;
792                 }
793 
794                 if (oper != eEND) {
795                     ReportError("Unexpected end of input");
796                 }
797 
798                 if (m_v_sp == 1) {
799                     /*
800                     sprintf(var_name, "$%d", ++m_TmpVarCount);
801                     printf("%s = ", var_name);
802                     CExprSymbol::add(CExprSymbol::eVARIABLE, var_name)->m_Val = m_VStack[0];
803                     if (m_VStack[0].GetType() == CExprValue::eINT) {
804                         printf("%" INT_FORMAT "d [%#" INT_FORMAT "x %#" INT_FORMAT "o]\n",
805                                m_VStack[0].ival,  m_VStack[0].ival, m_VStack[0].ival);
806                     } else {
807                         printf("%.10g\n", m_VStack[0].fval);
808                     }
809                     */
810                     return;
811                 } else if (m_v_sp != 0) {
812                     ReportError("Unexpected end of expression");
813                 }
814 
815                 return;
816               case eCOMMA:
817                 n_args += 1;
818                 continue;
819               case eADD:
820               case eSETADD:
821                 if (m_VStack[m_v_sp-1].GetType() == CExprValue::eINT && m_VStack[m_v_sp-2].GetType() == CExprValue::eINT) {
822                     m_VStack[m_v_sp-2].ival += m_VStack[m_v_sp-1].ival;
823                 } else if(m_VStack[m_v_sp-1].GetType() == CExprValue::eSTRING && m_VStack[m_v_sp-2].GetType() == CExprValue::eSTRING) {
824                     m_VStack[m_v_sp-2].m_sval += m_VStack[m_v_sp-1].m_sval;     // string concatenation
825                 } else {
826                     m_VStack[m_v_sp-2].fval =
827                         m_VStack[m_v_sp-2].GetDouble() + m_VStack[m_v_sp-1].GetDouble();
828                     m_VStack[m_v_sp-2].SetType(CExprValue::eFLOAT);
829                 }
830 
831                 m_v_sp -= 1;
832 
833                 if (cop == eSETADD) {
834                     if (!Assign()) return;
835                 }
836 
837                 m_VStack[m_v_sp-1].m_Var = NULL;
838                 break;
839               case eSUB:
840               case eSETSUB:
841                 if (m_VStack[m_v_sp-1].GetType() == CExprValue::eSTRING || m_VStack[m_v_sp-2].GetType() == CExprValue::eSTRING)
842                     ReportError("Can not subtract string literals");
843                 if (m_VStack[m_v_sp-1].GetType() == CExprValue::eINT && m_VStack[m_v_sp-2].GetType() == CExprValue::eINT) {
844                     m_VStack[m_v_sp-2].ival -= m_VStack[m_v_sp-1].ival;
845                 } else {
846                     m_VStack[m_v_sp-2].fval =
847                         m_VStack[m_v_sp-2].GetDouble() - m_VStack[m_v_sp-1].GetDouble();
848                     m_VStack[m_v_sp-2].SetType(CExprValue::eFLOAT);
849                 }
850 
851                 m_v_sp -= 1;
852 
853                 if (cop == eSETSUB) {
854                     if (!Assign()) return;
855                 }
856 
857                 m_VStack[m_v_sp-1].m_Var = NULL;
858 
859                 break;
860               case eMUL:
861               case eSETMUL:
862                 if (m_VStack[m_v_sp-1].GetType() == CExprValue::eSTRING || m_VStack[m_v_sp-2].GetType() == CExprValue::eSTRING)
863                     ReportError("Can not mupltiply string literals");
864 
865                  if (m_VStack[m_v_sp-1].GetType() == CExprValue::eINT && m_VStack[m_v_sp-2].GetType() == CExprValue::eINT) {
866                     m_VStack[m_v_sp-2].ival *= m_VStack[m_v_sp-1].ival;
867                 } else {
868                     m_VStack[m_v_sp-2].fval =
869                         m_VStack[m_v_sp-2].GetDouble() * m_VStack[m_v_sp-1].GetDouble();
870                     m_VStack[m_v_sp-2].SetType(CExprValue::eFLOAT);
871                 }
872 
873                 m_v_sp -= 1;
874 
875                 if (cop == eSETMUL) {
876                     if (!Assign()) return;
877                 }
878                 m_VStack[m_v_sp-1].m_Var = NULL;
879 
880                 break;
881               case eDIV:
882               case eSETDIV:
883                 if (m_VStack[m_v_sp-1].GetType() == CExprValue::eSTRING || m_VStack[m_v_sp-2].GetType() == CExprValue::eSTRING)
884                     ReportError("Can not divide string literals");
885 
886                 if (m_VStack[m_v_sp-1].GetDouble() == 0.0) {
887                     ReportError(m_VStack[m_v_sp-2].m_Pos, "Division by zero");
888                     return;
889                 }
890                 if (m_VStack[m_v_sp-1].GetType() == CExprValue::eINT && m_VStack[m_v_sp-2].GetType() == CExprValue::eINT) {
891                     m_VStack[m_v_sp-2].ival /= m_VStack[m_v_sp-1].ival;
892                 } else {
893                     m_VStack[m_v_sp-2].fval =
894                         m_VStack[m_v_sp-2].GetDouble() / m_VStack[m_v_sp-1].GetDouble();
895                     m_VStack[m_v_sp-2].SetType(CExprValue::eFLOAT);
896                 }
897                 m_v_sp -= 1;
898                 if (cop == eSETDIV) {
899                     if (!Assign()) return;
900                 }
901                 m_VStack[m_v_sp-1].m_Var = NULL;
902                 break;
903               case eMOD:
904               case eSETMOD:
905                 if (m_VStack[m_v_sp-1].GetType() == CExprValue::eSTRING || m_VStack[m_v_sp-2].GetType() == CExprValue::eSTRING)
906                     ReportError("Can not divide string literals");
907 
908                 if (m_VStack[m_v_sp-1].GetDouble() == 0.0) {
909                     ReportError(m_VStack[m_v_sp-2].m_Pos, "Division by zero");
910                     return;
911                 }
912                 if (m_VStack[m_v_sp-1].GetType() == CExprValue::eINT && m_VStack[m_v_sp-2].GetType() == CExprValue::eINT) {
913                     m_VStack[m_v_sp-2].ival %= m_VStack[m_v_sp-1].ival;
914                 } else {
915                     m_VStack[m_v_sp-2].fval =
916                         fmod(m_VStack[m_v_sp-2].GetDouble(), m_VStack[m_v_sp-1].GetDouble());
917                     m_VStack[m_v_sp-2].SetType(CExprValue::eFLOAT);
918                 }
919                 m_v_sp -= 1;
920                 if (cop == eSETMOD) {
921                     if (!Assign()) return;
922                 }
923                 m_VStack[m_v_sp-1].m_Var = NULL;
924                 break;
925               case ePOW:
926               case eSETPOW:
927                 if (m_VStack[m_v_sp-1].GetType() == CExprValue::eSTRING || m_VStack[m_v_sp-2].GetType() == CExprValue::eSTRING)
928                     ReportError("Illegal operation on string literals");
929 
930                 if (m_VStack[m_v_sp-1].GetType() == CExprValue::eINT && m_VStack[m_v_sp-2].GetType() == CExprValue::eINT) {
931                     m_VStack[m_v_sp-2].ival =
932                         (Int8)pow((double)m_VStack[m_v_sp-2].ival,
933                                    (double)m_VStack[m_v_sp-1].ival);
934                 } else {
935                     m_VStack[m_v_sp-2].fval =
936                         pow(m_VStack[m_v_sp-2].GetDouble(), m_VStack[m_v_sp-1].GetDouble());
937                     m_VStack[m_v_sp-2].SetType(CExprValue::eFLOAT);
938                 }
939                 m_v_sp -= 1;
940                 if (cop == eSETPOW) {
941                     if (!Assign()) return;
942                 }
943                 m_VStack[m_v_sp-1].m_Var = NULL;
944                 break;
945               case eAND:
946               case eSETAND:
947                 if (m_VStack[m_v_sp-1].GetType() == CExprValue::eSTRING || m_VStack[m_v_sp-2].GetType() == CExprValue::eSTRING)
948                     ReportError("Illegal operation on string literals");
949 
950                  if (m_VStack[m_v_sp-1].GetType() == CExprValue::eINT && m_VStack[m_v_sp-2].GetType() == CExprValue::eINT) {
951                     m_VStack[m_v_sp-2].ival &= m_VStack[m_v_sp-1].ival;
952                 } else if (m_VStack[m_v_sp-2].GetType() == CExprValue::eBOOL) {
953                     m_VStack[m_v_sp-2].bval =
954                         m_VStack[m_v_sp-2].bval && m_VStack[m_v_sp-1].GetBool();
955                 } else {
956                     m_VStack[m_v_sp-2].ival =
957                         m_VStack[m_v_sp-2].GetInt() & m_VStack[m_v_sp-1].GetInt();
958                     m_VStack[m_v_sp-2].SetType(CExprValue::eINT);
959                 }
960                 m_v_sp -= 1;
961                 if (cop == eSETAND) {
962                     if (!Assign()) return;
963                 }
964                 m_VStack[m_v_sp-1].m_Var = NULL;
965                 break;
966               case eOR:
967               case eSETOR:
968                 if (m_VStack[m_v_sp-1].GetType() == CExprValue::eSTRING || m_VStack[m_v_sp-2].GetType() == CExprValue::eSTRING)
969                     ReportError("Illegal operation on string literals");
970 
971                  if (m_VStack[m_v_sp-1].GetType() == CExprValue::eINT && m_VStack[m_v_sp-2].GetType() == CExprValue::eINT) {
972                     m_VStack[m_v_sp-2].ival |= m_VStack[m_v_sp-1].ival;
973                 } else if (m_VStack[m_v_sp-2].GetType() == CExprValue::eBOOL) {
974                     m_VStack[m_v_sp-2].bval =
975                         m_VStack[m_v_sp-2].bval || m_VStack[m_v_sp-1].GetBool();
976                 } else {
977                     m_VStack[m_v_sp-2].ival =
978                         m_VStack[m_v_sp-2].GetInt() | m_VStack[m_v_sp-1].GetInt();
979                     m_VStack[m_v_sp-2].SetType(CExprValue::eINT);
980                 }
981                 m_v_sp -= 1;
982                 if (cop == eSETOR) {
983                     if (!Assign()) return;
984                 }
985                 m_VStack[m_v_sp-1].m_Var = NULL;
986                 break;
987               case eXOR:
988               case eSETXOR:
989                 if (m_VStack[m_v_sp-1].GetType() == CExprValue::eSTRING || m_VStack[m_v_sp-2].GetType() == CExprValue::eSTRING)
990                     ReportError("Illegal operation on string literals");
991 
992                  if (m_VStack[m_v_sp-1].GetType() == CExprValue::eINT && m_VStack[m_v_sp-2].GetType() == CExprValue::eINT) {
993                     m_VStack[m_v_sp-2].ival ^= m_VStack[m_v_sp-1].ival;
994                 } else if (m_VStack[m_v_sp-2].GetType() == CExprValue::eBOOL) {
995                     m_VStack[m_v_sp-2].bval =
996                         m_VStack[m_v_sp-2].bval != m_VStack[m_v_sp-1].GetBool();
997                 } else {
998                     m_VStack[m_v_sp-2].ival =
999                         m_VStack[m_v_sp-2].GetInt() ^ m_VStack[m_v_sp-1].GetInt();
1000                     m_VStack[m_v_sp-2].SetType(CExprValue::eINT);
1001                 }
1002                 m_v_sp -= 1;
1003                 if (cop == eSETXOR) {
1004                     if (!Assign()) return;
1005                 }
1006                 m_VStack[m_v_sp-1].m_Var = NULL;
1007                 break;
1008               case eASL:
1009               case eSETASL:
1010                 if (m_VStack[m_v_sp-1].GetType() == CExprValue::eSTRING || m_VStack[m_v_sp-2].GetType() == CExprValue::eSTRING)
1011                     ReportError("Illegal operation on string literals");
1012 
1013                  if (m_VStack[m_v_sp-1].GetType() == CExprValue::eINT && m_VStack[m_v_sp-2].GetType() == CExprValue::eINT) {
1014                     m_VStack[m_v_sp-2].ival <<= m_VStack[m_v_sp-1].ival;
1015                 } else {
1016                     m_VStack[m_v_sp-2].ival =
1017                         m_VStack[m_v_sp-2].GetInt() << m_VStack[m_v_sp-1].GetInt();
1018                     m_VStack[m_v_sp-2].SetType(CExprValue::eINT);
1019                 }
1020                 m_v_sp -= 1;
1021                 if (cop == eSETASL) {
1022                     if (!Assign()) return;
1023                 }
1024                 m_VStack[m_v_sp-1].m_Var = NULL;
1025                 break;
1026               case eASR:
1027               case eSETASR:
1028                 if (m_VStack[m_v_sp-1].GetType() == CExprValue::eSTRING || m_VStack[m_v_sp-2].GetType() == CExprValue::eSTRING)
1029                     ReportError("Illegal operation on string literals");
1030 
1031                  if (m_VStack[m_v_sp-1].GetType() == CExprValue::eINT && m_VStack[m_v_sp-2].GetType() == CExprValue::eINT) {
1032                     m_VStack[m_v_sp-2].ival >>= m_VStack[m_v_sp-1].ival;
1033                 } else {
1034                     m_VStack[m_v_sp-2].ival =
1035                         m_VStack[m_v_sp-2].GetInt() >> m_VStack[m_v_sp-1].GetInt();
1036                     m_VStack[m_v_sp-2].SetType(CExprValue::eINT);
1037                 }
1038                 m_v_sp -= 1;
1039                 if (cop == eSETASR) {
1040                     if (!Assign()) return;
1041                 }
1042                 m_VStack[m_v_sp-1].m_Var = NULL;
1043                 break;
1044               case eLSR:
1045               case eSETLSR:
1046                 if (m_VStack[m_v_sp-1].GetType() == CExprValue::eSTRING || m_VStack[m_v_sp-2].GetType() == CExprValue::eSTRING)
1047                     ReportError("Illegal operation on string literals");
1048 
1049                  if (m_VStack[m_v_sp-1].GetType() == CExprValue::eINT && m_VStack[m_v_sp-2].GetType() == CExprValue::eINT) {
1050                     m_VStack[m_v_sp-2].ival =
1051                         (Uint8)m_VStack[m_v_sp-2].ival >> m_VStack[m_v_sp-1].ival;
1052                 } else {
1053                     m_VStack[m_v_sp-2].ival = (Uint8)m_VStack[m_v_sp-2].GetInt()
1054                         >> m_VStack[m_v_sp-1].GetInt();
1055                     m_VStack[m_v_sp-2].SetType(CExprValue::eINT);
1056                 }
1057                 m_v_sp -= 1;
1058                 if (cop == eSETLSR) {
1059                     if (!Assign()) return;
1060                 }
1061                 m_VStack[m_v_sp-1].m_Var = NULL;
1062                 break;
1063               case eEQ:
1064                  if (m_VStack[m_v_sp-1].GetType() == CExprValue::eINT && m_VStack[m_v_sp-2].GetType() == CExprValue::eINT) {
1065                     m_VStack[m_v_sp-2].bval =
1066                         m_VStack[m_v_sp-2].ival == m_VStack[m_v_sp-1].ival;
1067                     m_VStack[m_v_sp-2].SetType(CExprValue::eBOOL);
1068                 } else if (m_VStack[m_v_sp-2].GetType() == CExprValue::eBOOL) {
1069                     m_VStack[m_v_sp-2].bval =
1070                         m_VStack[m_v_sp-2].bval == m_VStack[m_v_sp-1].GetBool();
1071                 } else if (m_VStack[m_v_sp-1].GetType() == CExprValue::eSTRING && m_VStack[m_v_sp-2].GetType() == CExprValue::eSTRING) {
1072                     m_VStack[m_v_sp-2].bval =
1073                         m_VStack[m_v_sp-2].m_sval == m_VStack[m_v_sp-1].GetString();
1074                     m_VStack[m_v_sp-2].SetType(CExprValue::eBOOL);
1075                 } else {
1076                     m_VStack[m_v_sp-2].bval =
1077                         m_VStack[m_v_sp-2].GetDouble() == m_VStack[m_v_sp-1].GetDouble();
1078                     m_VStack[m_v_sp-2].SetType(CExprValue::eBOOL);
1079                 }
1080                 m_v_sp -= 1;
1081                 m_VStack[m_v_sp-1].m_Var = NULL;
1082                 break;
1083               case eNE:
1084                 if (m_VStack[m_v_sp-1].GetType() == CExprValue::eINT && m_VStack[m_v_sp-2].GetType() == CExprValue::eINT) {
1085                     m_VStack[m_v_sp-2].bval =
1086                         m_VStack[m_v_sp-2].ival != m_VStack[m_v_sp-1].ival;
1087                     m_VStack[m_v_sp-2].SetType(CExprValue::eBOOL);
1088                 } else if (m_VStack[m_v_sp-2].GetType() == CExprValue::eBOOL) {
1089                     m_VStack[m_v_sp-2].bval =
1090                         m_VStack[m_v_sp-2].bval != m_VStack[m_v_sp-1].GetBool();
1091                 } else if (m_VStack[m_v_sp-1].GetType() == CExprValue::eSTRING && m_VStack[m_v_sp-2].GetType() == CExprValue::eSTRING) {
1092                     m_VStack[m_v_sp-2].bval =
1093                         m_VStack[m_v_sp-2].m_sval != m_VStack[m_v_sp-1].GetString();
1094                     m_VStack[m_v_sp-2].SetType(CExprValue::eBOOL);
1095                 } else {
1096                     m_VStack[m_v_sp-2].bval =
1097                         m_VStack[m_v_sp-2].GetDouble() != m_VStack[m_v_sp-1].GetDouble();
1098                     m_VStack[m_v_sp-2].SetType(CExprValue::eBOOL);
1099                 }
1100                 m_v_sp -= 1;
1101                 m_VStack[m_v_sp-1].m_Var = NULL;
1102                 break;
1103               case eGT:
1104                 if (m_VStack[m_v_sp-1].GetType() == CExprValue::eSTRING || m_VStack[m_v_sp-2].GetType() == CExprValue::eSTRING)
1105                     ReportError("Illegal operation on string literals");
1106 
1107                 if (m_VStack[m_v_sp-1].GetType() == CExprValue::eINT && m_VStack[m_v_sp-2].GetType() == CExprValue::eINT) {
1108                     m_VStack[m_v_sp-2].bval =
1109                         m_VStack[m_v_sp-2].ival > m_VStack[m_v_sp-1].ival;
1110                     m_VStack[m_v_sp-2].SetType(CExprValue::eBOOL);
1111                 } else if (m_VStack[m_v_sp-2].GetType() == CExprValue::eBOOL) {
1112                     m_VStack[m_v_sp-2].bval =
1113                         m_VStack[m_v_sp-2].bval > m_VStack[m_v_sp-1].GetBool();
1114                 } else {
1115                     m_VStack[m_v_sp-2].bval =
1116                         m_VStack[m_v_sp-2].GetDouble() > m_VStack[m_v_sp-1].GetDouble();
1117                     m_VStack[m_v_sp-2].SetType(CExprValue::eBOOL);
1118                 }
1119                 m_v_sp -= 1;
1120                 m_VStack[m_v_sp-1].m_Var = NULL;
1121                 break;
1122               case eGE:
1123                if (m_VStack[m_v_sp-1].GetType() == CExprValue::eSTRING || m_VStack[m_v_sp-2].GetType() == CExprValue::eSTRING)
1124                     ReportError("Illegal operation on string literals");
1125 
1126                if (m_VStack[m_v_sp-1].GetType() == CExprValue::eINT && m_VStack[m_v_sp-2].GetType() == CExprValue::eINT) {
1127                     m_VStack[m_v_sp-2].bval =
1128                         m_VStack[m_v_sp-2].ival >= m_VStack[m_v_sp-1].ival;
1129                     m_VStack[m_v_sp-2].SetType(CExprValue::eBOOL);
1130                 } else if (m_VStack[m_v_sp-2].GetType() == CExprValue::eBOOL) {
1131                     m_VStack[m_v_sp-2].bval =
1132                         m_VStack[m_v_sp-2].bval >= m_VStack[m_v_sp-1].GetBool();
1133                 } else {
1134                     m_VStack[m_v_sp-2].bval =
1135                         m_VStack[m_v_sp-2].GetDouble() >= m_VStack[m_v_sp-1].GetDouble();
1136                     m_VStack[m_v_sp-2].SetType(CExprValue::eBOOL);
1137                 }
1138                 m_v_sp -= 1;
1139                 m_VStack[m_v_sp-1].m_Var = NULL;
1140                 break;
1141               case eLT:
1142                if (m_VStack[m_v_sp-1].GetType() == CExprValue::eSTRING || m_VStack[m_v_sp-2].GetType() == CExprValue::eSTRING)
1143                     ReportError("Illegal operation on string literals");
1144 
1145                 if (m_VStack[m_v_sp-1].GetType() == CExprValue::eINT && m_VStack[m_v_sp-2].GetType() == CExprValue::eINT) {
1146                     m_VStack[m_v_sp-2].bval =
1147                         m_VStack[m_v_sp-2].ival < m_VStack[m_v_sp-1].ival;
1148                     m_VStack[m_v_sp-2].SetType(CExprValue::eBOOL);
1149                 } else if (m_VStack[m_v_sp-2].GetType() == CExprValue::eBOOL) {
1150                     m_VStack[m_v_sp-2].bval =
1151                         m_VStack[m_v_sp-2].bval < m_VStack[m_v_sp-1].GetBool();
1152                 } else {
1153                     m_VStack[m_v_sp-2].bval =
1154                         m_VStack[m_v_sp-2].GetDouble() < m_VStack[m_v_sp-1].GetDouble();
1155                     m_VStack[m_v_sp-2].SetType(CExprValue::eBOOL);
1156                 }
1157                 m_v_sp -= 1;
1158                 m_VStack[m_v_sp-1].m_Var = NULL;
1159                 break;
1160               case eLE:
1161                 if (m_VStack[m_v_sp-1].GetType() == CExprValue::eSTRING || m_VStack[m_v_sp-2].GetType() == CExprValue::eSTRING)
1162                     ReportError("Illegal operation on string literals");
1163 
1164                if (m_VStack[m_v_sp-1].GetType() == CExprValue::eINT && m_VStack[m_v_sp-2].GetType() == CExprValue::eINT) {
1165                     m_VStack[m_v_sp-2].bval =
1166                         m_VStack[m_v_sp-2].ival <= m_VStack[m_v_sp-1].ival;
1167                     m_VStack[m_v_sp-2].SetType(CExprValue::eBOOL);
1168                 } else if (m_VStack[m_v_sp-2].GetType() == CExprValue::eBOOL) {
1169                     m_VStack[m_v_sp-2].bval =
1170                         m_VStack[m_v_sp-2].bval <= m_VStack[m_v_sp-1].GetBool();
1171                 } else {
1172                     m_VStack[m_v_sp-2].bval =
1173                         m_VStack[m_v_sp-2].GetDouble() <= m_VStack[m_v_sp-1].GetDouble();
1174                     m_VStack[m_v_sp-2].SetType(CExprValue::eBOOL);
1175                 }
1176                 m_v_sp -= 1;
1177                 m_VStack[m_v_sp-1].m_Var = NULL;
1178                 break;
1179               case ePREINC:
1180                 if (m_VStack[m_v_sp-1].GetType() == CExprValue::eSTRING || m_VStack[m_v_sp-2].GetType() == CExprValue::eSTRING)
1181                     ReportError("Illegal operation on string literals");
1182 
1183                if (m_VStack[m_v_sp-1].GetType() == CExprValue::eINT) {
1184                     m_VStack[m_v_sp-1].ival += 1;
1185                 } else {
1186                     m_VStack[m_v_sp-1].fval += 1;
1187                 }
1188                 if (!Assign()) return;
1189                 m_VStack[m_v_sp-1].m_Var = NULL;
1190                 break;
1191               case ePREDEC:
1192                 if (m_VStack[m_v_sp-1].GetType() == CExprValue::eINT) {
1193                     m_VStack[m_v_sp-1].ival -= 1;
1194                 } else {
1195                     m_VStack[m_v_sp-1].fval -= 1;
1196                 }
1197                 if (!Assign()) return;
1198                 m_VStack[m_v_sp-1].m_Var = NULL;
1199                 break;
1200               case ePOSTINC:
1201                 if (m_VStack[m_v_sp-1].GetType() == CExprValue::eSTRING || m_VStack[m_v_sp-2].GetType() == CExprValue::eSTRING)
1202                     ReportError("Illegal operation on string literals");
1203 
1204                if (m_VStack[m_v_sp-1].m_Var == NULL) {
1205                     ReportError(m_VStack[m_v_sp-1].m_Pos, "Varaibale expected");
1206                     return;
1207                 }
1208                 if (m_VStack[m_v_sp-1].m_Var->m_Val.GetType() == CExprValue::eINT) {
1209                     m_VStack[m_v_sp-1].m_Var->m_Val.ival += 1;
1210                 } else {
1211                     m_VStack[m_v_sp-1].m_Var->m_Val.fval += 1;
1212                 }
1213                 m_VStack[m_v_sp-1].m_Var = NULL;
1214                 break;
1215               case ePOSTDEC:
1216                 if (m_VStack[m_v_sp-1].GetType() == CExprValue::eSTRING || m_VStack[m_v_sp-2].GetType() == CExprValue::eSTRING)
1217                     ReportError("Illegal operation on string literals");
1218 
1219                if (m_VStack[m_v_sp-1].m_Var == NULL) {
1220                     ReportError(m_VStack[m_v_sp-1].m_Pos, "Varaibale expected");
1221                     return;
1222                 }
1223                 if (m_VStack[m_v_sp-1].m_Var->m_Val.GetType() == CExprValue::eINT) {
1224                     m_VStack[m_v_sp-1].m_Var->m_Val.ival -= 1;
1225                 } else {
1226                     m_VStack[m_v_sp-1].m_Var->m_Val.fval -= 1;
1227                 }
1228                 m_VStack[m_v_sp-1].m_Var = NULL;
1229                 break;
1230               case eSET:
1231                 if (m_VStack[m_v_sp-2].m_Var == NULL) {
1232                     ReportError(m_VStack[m_v_sp-2].m_Pos, "Variable expected");
1233                     return;
1234                 } else {
1235                     m_VStack[m_v_sp-2]=m_VStack[m_v_sp-2].m_Var->m_Val=m_VStack[m_v_sp-1];
1236                 }
1237                 m_v_sp -= 1;
1238                 m_VStack[m_v_sp-1].m_Var = NULL;
1239                 break;
1240               case eNOT:
1241                 if (m_VStack[m_v_sp-1].GetType() == CExprValue::eSTRING || m_VStack[m_v_sp-2].GetType() == CExprValue::eSTRING)
1242                     ReportError("Illegal operation on string literals");
1243 
1244                if (m_VStack[m_v_sp-1].GetType() == CExprValue::eINT) {
1245                     m_VStack[m_v_sp-1].ival = !m_VStack[m_v_sp-1].ival;
1246                 } else if (m_VStack[m_v_sp-1].GetType() == CExprValue::eBOOL) {
1247                     m_VStack[m_v_sp-1].bval = !m_VStack[m_v_sp-1].bval;
1248                 } else {
1249                     m_VStack[m_v_sp-1].ival = !m_VStack[m_v_sp-1].fval;
1250                     m_VStack[m_v_sp-1].SetType(CExprValue::eINT);
1251                 }
1252                 m_VStack[m_v_sp-1].m_Var = NULL;
1253                 break;
1254               case eMINUS:
1255                if (m_VStack[m_v_sp-1].GetType() == CExprValue::eSTRING || m_VStack[m_v_sp-2].GetType() == CExprValue::eSTRING)
1256                     ReportError("Illegal operation on string literals");
1257 
1258                 if (m_VStack[m_v_sp-1].GetType() == CExprValue::eINT) {
1259                     m_VStack[m_v_sp-1].ival = -m_VStack[m_v_sp-1].ival;
1260                 } else {
1261                     m_VStack[m_v_sp-1].fval = -m_VStack[m_v_sp-1].fval;
1262                 }
1263                 // no break
1264               case ePLUS:
1265                 if (m_VStack[m_v_sp-1].GetType() == CExprValue::eSTRING || m_VStack[m_v_sp-2].GetType() == CExprValue::eSTRING)
1266                     ReportError("Illegal operation on string literals");
1267 
1268                m_VStack[m_v_sp-1].m_Var = NULL;
1269                 break;
1270               case eCOM:
1271                if (m_VStack[m_v_sp-1].GetType() == CExprValue::eSTRING || m_VStack[m_v_sp-2].GetType() == CExprValue::eSTRING)
1272                     ReportError("Illegal operation on string literals");
1273 
1274                 if (m_VStack[m_v_sp-1].GetType() == CExprValue::eINT) {
1275                     m_VStack[m_v_sp-1].ival = ~m_VStack[m_v_sp-1].ival;
1276                 } else {
1277                     m_VStack[m_v_sp-1].ival = ~(int)m_VStack[m_v_sp-1].fval;
1278                     m_VStack[m_v_sp-1].SetType(CExprValue::eINT);
1279                 }
1280                 m_VStack[m_v_sp-1].m_Var = NULL;
1281                 break;
1282               case eRPAR:
1283                 ReportError("mismatched ')'");
1284                 return;
1285               case eFUNC:
1286                 ReportError("'(' expected");
1287                 return;
1288               case eLPAR:
1289                 if (oper != eRPAR) {
1290                     ReportError("')' expected");
1291                     return;
1292                 }
1293                 if (m_OStack[m_o_sp-1] == eFUNC) {
1294                     CExprSymbol* sym = m_VStack[m_v_sp-n_args-1].m_Var;
1295 
1296                     switch(sym->m_Tag) {
1297                     case CExprSymbol::eIFUNC1:
1298                         if (n_args != 1) {
1299                             ReportError(m_VStack[m_v_sp-n_args-1].m_Pos,
1300                                 "Function should take one argument");
1301                             return;
1302                         }
1303                         m_VStack[m_v_sp-2].ival =
1304                         (*sym->m_IntFunc1)(m_VStack[m_v_sp-1].GetInt());
1305                         m_VStack[m_v_sp-2].SetType(CExprValue::eINT);
1306                         m_v_sp -= 1;
1307                         break;
1308                     case CExprSymbol::eIFUNC2:
1309                         if (n_args != 2) {
1310                             ReportError(m_VStack[m_v_sp-n_args-1].m_Pos,
1311                                 "Function should take two arguments");
1312                             return;
1313                         }
1314                         m_VStack[m_v_sp-3].ival =
1315                         (*sym->m_IntFunc2)
1316                         (m_VStack[m_v_sp-2].GetInt(), m_VStack[m_v_sp-1].GetInt());
1317                         m_VStack[m_v_sp-3].SetType(CExprValue::eINT);
1318                         m_v_sp -= 2;
1319                         break;
1320                     case CExprSymbol::eFFUNC1:
1321                         if (n_args != 1) {
1322                             ReportError(m_VStack[m_v_sp-n_args-1].m_Pos,
1323                                 "Function should take one argument");
1324                             return;
1325                         }
1326                         m_VStack[m_v_sp-2].fval =
1327                         (*sym->m_FloatFunc1)(m_VStack[m_v_sp-1].GetDouble());
1328                         m_VStack[m_v_sp-2].SetType(CExprValue::eFLOAT);
1329                         m_v_sp -= 1;
1330                         break;
1331                     case CExprSymbol::eFFUNC2:
1332                         if (n_args != 2) {
1333                             ReportError(m_VStack[m_v_sp-n_args-1].m_Pos,
1334                                 "Function should take two arguments");
1335                             return;
1336                         }
1337                         m_VStack[m_v_sp-3].fval =
1338                             (*sym->m_FloatFunc2)
1339                             (m_VStack[m_v_sp-2].GetDouble(), m_VStack[m_v_sp-1].GetDouble());
1340                         m_VStack[m_v_sp-3].SetType(CExprValue::eFLOAT);
1341                         m_v_sp -= 2;
1342                         break;
1343                     case CExprSymbol::eBFUNC1:
1344                         if (n_args != 1) {
1345                             ReportError(m_VStack[m_v_sp-n_args-1].m_Pos,
1346                                 "Function should take one argument");
1347                             return;
1348                         }
1349                         m_VStack[m_v_sp-2].bval =
1350                         (*sym->m_BoolFunc1)(m_VStack[m_v_sp-1].GetBool());
1351                         m_VStack[m_v_sp-2].SetType(CExprValue::eBOOL);
1352                         m_v_sp -= 1;
1353                         break;
1354                     case CExprSymbol::eBFUNC2:
1355                         if (n_args != 2) {
1356                             ReportError(m_VStack[m_v_sp-n_args-1].m_Pos,
1357                                 "Function should take two arguments");
1358                             return;
1359                         }
1360                         m_VStack[m_v_sp-3].bval =
1361                             (*sym->m_BoolFunc2)
1362                             (m_VStack[m_v_sp-2].GetBool(), m_VStack[m_v_sp-1].GetBool());
1363                         m_VStack[m_v_sp-3].SetType(CExprValue::eBOOL);
1364                         m_v_sp -= 2;
1365                         break;
1366                     case CExprSymbol::eSFUNC1:
1367                         if (n_args != 1) {
1368                             ReportError(m_VStack[m_v_sp-n_args-1].m_Pos,
1369                                 "Function should take one argument");
1370                             return;
1371                         }
1372                         m_VStack[m_v_sp-2].bval =
1373                         (*sym->m_StringFunc1)(m_VStack[m_v_sp-1].GetString());
1374                         m_VStack[m_v_sp-2].SetType(CExprValue::eBOOL);
1375                         m_v_sp -= 1;
1376                         break;
1377 ;
1378                     default:
1379                         ReportError("Invalid expression");
1380                     }
1381 
1382                     m_VStack[m_v_sp-1].m_Var = NULL;
1383                     m_o_sp -= 1;
1384                     n_args = 1;
1385                 } else if (n_args != 1) {
1386                     ReportError("Function call expected");
1387                     return;
1388                 }
1389 
1390                 goto next_token;
1391 
1392               default:
1393                 ReportError("syntax ReportError");
1394             }
1395         }
1396 
1397         if (m_o_sp == max_stack_size) {
1398             ReportError("operator stack overflow");
1399             return;
1400         }
1401 
1402         m_OStack[m_o_sp++] = oper;
1403     }
1404 }
1405 
1406 
1407 END_NCBI_SCOPE
1408