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