1 #include "calcparser.h"
2
3 #ifndef _QT4
4 #include <sstream>
5 #include <iomanip>
6
7 #ifndef _QT_INTERFACE
8 #define tr(text) gettext(text)
9 #ifdef _UNIX
10 #include </usr/local/include/libintl.h>
11 #else
12 #include "../../gettext/gettext-runtime/include/libintl.h"
13 #endif
14 #else
15 //#include <QObject>
16 //#define tr(text) QObject::tr(QString::fromStdString(text))
17 #define tr(text) (text)
18 #endif
19 #else
20 #include <QObject>
21 #define tr(text) QObject::tr(text)
22 #endif
23
24 #define tr(text) QObject::tr(text)
25
26 String _Errors[] = {tr("Unknown error!"), tr("Syntax error"), tr("Unclosed parenthesis")
27 ,tr("Unknown function"), tr("Division by zero!"),
28 tr("Invalid argument"), tr("Value is too large"), tr("Undefined variable"),
29 tr("Empty parentheses"), tr("Type mismatch"), tr("Readonly variable")};
30
31
32 String Func[] = {"sin(", "cos(", "tan(", "ctan(", "asin(", "acos(",
33 "atan(", "actan(", "sinh(", "cosh(", "tanh(", "ctanh(", "asinh(",
34 "acosh(", "atanh(", "actanh(",
35 "ln(", "log(", "fact(", "max(", "min(", "dms(", "deg(", "sqrt(", "terrt("};
36
37
38 String VarTypes[] = {"float", "string"};
39
40
41
42
43
44
CalcParser(String * pexpr)45 CalcParser::CalcParser(String *pexpr)
46 {
47
48 result = new CValue(FLOAT);
49
50 dec_point = "";
51 eq = "";
52 token_end.SetType(END);
53 token_end.SetValue("END");
54 SetParams(pexpr);
55 InitMapToksHtml();
56
57 SetVariable("pi", DoubleToString(M_PI), FLOAT, true);
58 SetVariable("e", DoubleToString(exp(1)), FLOAT, true);
59 }
60
61
~CalcParser()62 CalcParser::~CalcParser()
63 {
64 Tokens.clear();
65 delete result;
66 }
67
68
SetVariable(String name,String value,e_type_var type,bool readonly)69 void CalcParser::SetVariable(String name, String value, e_type_var type, bool readonly)
70 {
71 if(name.empty() || name == "")
72 return;
73 Variable var(name, value, type);
74 var.read_only = readonly;
75 Vars[var.name] = var;
76 }
77
78
Run(void)79 bool CalcParser::Run(void)
80 {
81 bool res = true;
82 result->SetValue(0);
83 i_toks = Tokens.begin();
84 do
85 {
86 res &= Calculate(result);
87 }while(token->Type() == ENDLINE);
88 return res;
89 }
90
Calculate(CValue * loc_result)91 bool CalcParser::Calculate(CValue *loc_result)
92 {
93 GetToken();
94 while(token->Type() != ENDLINE && token->Type() != END)
95 {
96 result->SetType(FLOAT);
97 Add_exp(loc_result);
98 if(token->Type() != ENDLINE && token->Type() != END)
99 Error(SYNTAX);
100
101 }
102
103 return !HasErr();
104 }
105
106
InitVariableFromExpression()107 bool CalcParser::InitVariableFromExpression()
108 {
109 Token t0, t1;
110 Token *t = token;
111 String var;
112 TokenList::iterator it = i_toks;
113 CValue res;
114 Variable v;
115
116 t0 = *token;
117 if(t0.Type() == VARIABLE)
118 {
119 GetToken();
120 t1 = *token;
121 if(t1.Value() == "=")
122 {
123 var = t0.Value();
124
125 binit_var = true;
126
127 GetToken();
128 Add_exp(&res);
129 if(!this->HasErr())
130 {
131 VarList::const_iterator var_it = Vars.find(var);
132 if(var_it != Vars.end())
133 {
134 v = VariableByIterator(var_it);
135 if(v.read_only)
136 {
137 Error(RO);
138 return false;
139 }
140
141 }
142
143 v.type = t0.type_var;
144 if(v.type != res.Type())
145 {
146 Error(TMS);
147 return false;
148 }
149 v.name = var;
150 if(v.type == FLOAT)
151 v.value = DoubleToString(res.ValueFloat());
152 else
153 v.value = res.ValueString();
154
155 Vars[var] = v;
156 return true;
157 }
158 else
159 return false;
160
161 }
162 }
163 i_toks = it;
164 token = t;
165 return false;
166 }
167
168
InitExpr(String * pexpr)169 void CalcParser::InitExpr(String *pexpr)
170 {
171 binit_var = false;
172 if(pexpr == NULL)
173 expr = "";
174 else
175 expr = *pexpr;
176
177 lc = localeconv();// надо перенести в расчет
178 if(lc)
179 dec_point.insert(0, lc->decimal_point);
180
181 token = &token_end;
182 }
183
SetParams(String * pexpr,int scale,int DRG_mode)184 void CalcParser::SetParams(String *pexpr, int scale, int DRG_mode)
185 {
186 err = -1;
187 result->SetType(FLOAT);
188
189 InitExpr(pexpr);
190
191 SetScale(scale);
192 SetDRG(DRG_mode);
193 LoadTokens();
194
195 }
196
SetScale(int scale)197 void CalcParser::SetScale(int scale)
198 {
199 Token *t;
200 long double number;
201 String s;
202 int prev_scale = this->scale;
203
204 this->scale = scale;
205
206 TokenList::iterator i = Tokens.begin();
207 for(; i != Tokens.end(); ++i)
208 {
209 t = &(*i);
210 if(t->Type() == NUMBER)
211 {
212 number = ScaleToVal(t->Value(), prev_scale);
213 t->SetValue(DoubleToString(number));
214 }
215 }
216 }
217
Scale()218 int CalcParser::Scale()
219 {
220 return scale;
221 }
222
223
SetDRG(int drg_mode)224 void CalcParser::SetDRG(int drg_mode)
225 {
226 if(drg_mode == 0)
227 return;
228 this->DRG_mode = drg_mode;
229 }
230
DRG()231 int CalcParser::DRG()
232 {
233 return DRG_mode;
234 }
235
236
LoadTokens()237 void CalcParser::LoadTokens()
238 {
239 Token *nTok;
240
241 exp_p = expr.begin();
242 Tokens.clear();
243
244 while((nTok = LoadToken()) != NULL)
245 {
246 if(nTok->Type() == VARIABLE)
247 {
248 VarList::const_iterator var_it = Vars.find(nTok->Value());
249 if(var_it != Vars.end())
250 {
251 Variable v = VariableByIterator(var_it);
252 nTok->type_var = v.type;
253 }
254 }
255 if(nTok->Value() == ",")
256 nTok->SetType(COMMA);
257 Tokens.push_back(*nTok);
258 delete nTok;
259 }
260 }
261
262
263
CheckParentheses()264 int CalcParser::CheckParentheses()
265 {
266 int res = 0;
267 TokenList::iterator i = Tokens.begin();
268 Token t;
269
270 while(i != Tokens.end())
271 {
272 t = *i++;
273 if(t.Value() == "(" || t.Type() == FUNCTION)
274 res++;
275 if(t.Value() == ")")
276 res--;
277 }
278 return res;
279 }
280
FindParentheses()281 TokenList::iterator CalcParser::FindParentheses()
282 {
283 int res = 0;
284 TokenList::iterator i = Tokens.end();
285 Token t;
286
287 if(Tokens.empty())
288 return Tokens.end();
289
290 while(i-- != Tokens.begin())
291 {
292 t = *i;
293
294 if(t.Value() == "(" || t.Type() == FUNCTION)
295 res++;
296 if(t.Value() == ")")
297 res--;
298 if(0 == res)
299 break;
300 }
301 if((t.Value() == "(" || t.Type() == FUNCTION) && res == 0)
302 return i;
303 return Tokens.end();
304 }
305
306
InvExpInNumber(Token * tok)307 bool CalcParser::InvExpInNumber(Token* tok)
308 {
309 int index;
310 String value;
311
312 if(!tok)
313 return false;
314 value = tok->Value();
315 if(IndexOf(&value, 'e') == -1)
316 return false;
317
318 index = IndexOf(&value, '+');
319 if(index != -1)
320 {
321 value[index] = '-';
322 tok->SetValue(value);
323 return true;
324 }
325 index = IndexOf(&value, '-');
326 if(index != -1)
327 {
328 value[index] = '+';
329 tok->SetValue(value);
330 return true;
331 }
332 return false;
333 }
334
335
336
AddPrefixInverse()337 bool CalcParser::AddPrefixInverse()
338 {
339 EraseErrors();
340
341 Token *ltok = LastToken();
342 Token before_tok;
343 Token before_before_tok;
344 TokenList::iterator i = Tokens.end();
345 TokenList::iterator before_i;
346
347 if(ltok->Type() == NUMBER || ltok->Value() == ")")
348 {
349 if(ltok->Type() == NUMBER)
350 before_i = --i;
351 else
352 before_i = i = FindParentheses();
353
354 if(i == Tokens.begin())
355 {
356 before_tok = *i;
357 before_before_tok = token_end;
358 }
359 else
360 {
361 before_tok = *--i;
362 if(i == Tokens.begin())
363 before_before_tok = *i;
364 else
365 before_before_tok = *--i;
366 }
367
368 if(before_tok.Value() == "/" && before_before_tok.Value() == "1")
369 {
370 i = Tokens.erase(i);
371 Tokens.erase(i);
372 }
373 else
374 {
375 before_i = Tokens.insert(before_i, *(new Token("/", DELIMITER)));
376 Tokens.insert(before_i, *(new Token("1", NUMBER)));
377 }
378 return true;
379 }
380 return false;
381 }
382
383
384
AddPrefixOp(String op)385 bool CalcParser::AddPrefixOp(String op)
386 {
387 EraseErrors();
388
389 Token *ltok = LastToken();
390 Token before_tok;
391 TokenList::iterator i = Tokens.end();
392 TokenList::iterator before_i;
393
394 if(op == "1/")
395 return AddPrefixInverse();
396
397 if(op == "-" || op == "~")
398 {
399 if(ltok->Type() == NUMBER || ltok->Value() == ")")
400 {
401 if(ltok->Type() == NUMBER)
402 {
403 if(InvExpInNumber(ltok))
404 return true;
405 else
406 before_i = --i;
407 }
408 else
409 before_i = i = FindParentheses();
410
411 if(i == Tokens.begin())
412 before_tok = *i;
413 else
414 before_tok = *(--i);
415
416 if((before_tok.Value() == op || before_tok.Value() == "+") && before_tok.prefix)
417 {
418 Tokens.erase(i);
419 return true;
420 }
421 else
422 {
423 if(before_tok.Value() == "-" && before_tok.prefix && op == "~")
424 return false;
425 if(before_tok.Value() == "~" && before_tok.prefix && op == "-")
426 return false;
427
428 Tokens.insert(before_i, *(new Token(op, DELIMITER, true)));
429 return true;
430 }
431 }
432 }
433 return false;
434 }
435
436
437
AddToken(String * pexpr)438 bool CalcParser::AddToken(String *pexpr)
439 {
440 if(*pexpr == "+/-")
441 return AddPrefixOp("-");
442 if(*pexpr == "1/x")
443 return AddPrefixOp("1/");
444 if(*pexpr == "exp")
445 *pexpr = ".e+";
446
447 InitExpr(pexpr);
448 Token *nTok;
449 Token *ltok;
450 bool res = true;
451
452 EraseErrors();
453 exp_p = expr.begin();
454
455 while((nTok = LoadToken()) != NULL)
456 {
457 if(nTok->Value() == "del") //для отладки
458 {
459 ToBack();
460 }
461 else
462 {
463 ltok = LastToken();
464
465 if(nTok->Type() == NUMBER)
466 {
467 if(nTok->Value() == "." && (ltok->Type() == END || ltok->Type() != NUMBER))
468 nTok->SetValue("0" + nTok->Value());
469
470 if(ltok->Type() == NUMBER)
471 {
472 if(IndexOf(<ok->Value(), '.') != -1 && nTok->Value() == ".e+")
473 nTok->SetValue("e+");
474
475 if(IndexOf(<ok->Value(), '.') != -1 && IndexOf(&nTok->Value(), '.') != -1)
476 return false;
477 if(IndexOf(<ok->Value(), 'e') != -1 && IndexOf(&nTok->Value(), 'e') != -1)
478 return false;
479 if(IndexOf(<ok->Value(), 'i') != -1 && IndexOf(&nTok->Value(), 'i') != -1)
480 return false;
481
482 ltok->Add(nTok->Value());
483 }
484 else
485 {
486 if(!(ltok->Value() == ")" || ltok->Type() == VARIABLE))
487 Tokens.push_back(*nTok);
488 else
489 res = false;
490 }
491 }
492 else
493 if(nTok->Value() == "(")
494 {
495 if(ltok->Type() != NUMBER && ltok->Type() != VARIABLE && ltok->Value() != ")")
496 Tokens.push_back(*nTok);
497 else
498 res = false;
499 }
500 else
501 if(nTok->Value() == ")")
502 {
503 if(ltok->Type() == NUMBER || ltok->Type() == VARIABLE || ltok->Value() == ")")
504 {
505 Tokens.push_back(*nTok);
506 if(CheckParentheses() < 0)
507 {
508 nTok->SetValue("(");
509 Tokens.push_front(*nTok);
510 }
511 }
512 else
513 res = false;
514 }
515 else
516 if(nTok->Type() == FUNCTION || nTok->Type() == VARIABLE)
517 {
518 if(ltok->Type() != NUMBER && ltok->Value() != ")" && ltok->Type() != VARIABLE)
519 Tokens.push_back(*nTok);
520 else
521 res = false;
522 }
523 else
524 if(nTok->Type() == DELIMITER)
525 {
526 if((ltok->Type() != DELIMITER && ltok->Type() != END && ltok->Type() != FUNCTION)
527 || ltok->Value() == ")")
528 {
529 if(nTok->Value() == "~")
530 res = AddPrefixOp(nTok->Value());
531 else
532 Tokens.push_back(*nTok);
533 }
534 else
535 {
536 if((nTok->Value() == "+" || nTok->Value() == "-" || nTok->Value() == "~")
537
538 && (!ltok->prefix))
539 {
540 nTok->prefix = true;
541 Tokens.push_back(*nTok);
542 }
543 else
544 res = false;
545 }
546 }
547 else
548 res = false;
549 }
550 delete nTok;
551 if(!res)
552 break;
553
554 }
555 return res;
556 }
557
LastToken()558 Token* CalcParser::LastToken()
559 {
560 if(Tokens.empty())
561 return &token_end;
562 TokenList::iterator i = Tokens.end();
563 Token *t = &(*--i);
564 return t;
565 }
566
LastTokenValue()567 String CalcParser::LastTokenValue()
568 {
569 return LastToken()->Value();
570 }
571
572
ToBack(bool lastdigit)573 void CalcParser::ToBack(bool lastdigit)
574 {
575 bool cutnumber = false;
576
577 EraseErrors();
578 Token *lastT = LastToken();
579
580 if(lastT->Type() != END)
581 {
582 if(lastdigit)
583 cutnumber = lastT->CutNumber();
584 if(!cutnumber)
585 {
586 if(lastT->Value() == ")")
587 {
588 TokenList::iterator itP = FindParentheses();
589 if(itP == Tokens.begin() && ((Token*)&(*itP))->Type() !=FUNCTION)
590 Tokens.pop_front();
591 }
592
593 Tokens.pop_back();
594 #ifdef _QT4
595 i_toks = Tokens.end() - 1;
596 #endif
597 }
598 }
599 }
600
601
TypeRes()602 e_type_var CalcParser::TypeRes()
603 {
604 return result->Type();
605 }
606
HasErr()607 bool CalcParser::HasErr()
608 {
609 return err != -1;
610 }
611
GetResult()612 long double CalcParser::GetResult()
613 {
614 return result->ValueFloat();
615 }
616
GetResultStr()617 String CalcParser::GetResultStr()
618 {
619 return result->ValueString();
620 }
621
622
ReadVariableToken(Token * loc_token)623 void CalcParser::ReadVariableToken(Token *loc_token)
624 {
625 while(isalpha(*exp_p) || strchr("1234567890", *exp_p))
626 loc_token->Add(*exp_p++);
627 if(*exp_p == '(')
628 {
629 loc_token->SetType(FUNCTION);
630 loc_token->Add(*exp_p++);
631 }
632 else
633 loc_token->SetType(VARIABLE);
634
635 }
636
LoadToken()637 Token* CalcParser::LoadToken()
638 {
639 Token *loc_token;
640
641 while(Space(*exp_p))
642 ++exp_p;
643
644 if (exp_p >= expr.end())
645 return NULL;
646
647 loc_token = new Token();
648
649 if(strchr("*/+-()%^!&|~=", *exp_p))
650 {
651 loc_token->SetType(DELIMITER);
652 loc_token->Add(*exp_p++);
653 //if(loc_token->Value() == "=")
654 // exp_p = expr.end();
655 }
656
657 else
658 if(strchr("<>", *exp_p))
659 {
660 loc_token->SetType(DELIMITER);
661 if(*exp_p == '<' && *(exp_p + 1) == '<')
662 loc_token->Add("<<");
663 else
664 if(*exp_p == '>' && *(exp_p + 1) == '>')
665 loc_token->Add(">>");
666 else
667 Error(SYNTAX, loc_token);
668
669 exp_p += 2;
670 }
671 else
672 if(isalpha(*exp_p))
673 {
674 ReadVariableToken(loc_token);
675 if(loc_token->Type() == VARIABLE)
676 {
677 if(loc_token->Value() == VarTypes[1]) //строковая переменная
678 {
679 loc_token->SetValue("");
680 while(Space(*exp_p) && exp_p != expr.end())
681 ++exp_p;
682
683 if(isalpha(*exp_p))
684 {
685 ReadVariableToken(loc_token);
686 if(loc_token->Type() == VARIABLE)
687 loc_token->type_var = STRING;
688 else
689 Error(SYNTAX, loc_token);
690 }
691 else
692 Error(SYNTAX, loc_token);
693 }
694 }
695 }
696 else
697 if(isdigit(*exp_p) && !strchr("ie+-", *exp_p))
698 {
699 while(isdigit(*exp_p))
700 {
701 if(*exp_p == 'e')
702 {
703 if(strchr("-+",*(exp_p + 1)))
704 loc_token->Add(*exp_p++);
705 else
706 Error(SYNTAX, loc_token);
707 }
708 loc_token->Add(*exp_p++);
709 }
710 loc_token->SetType(NUMBER);
711 }
712 else
713 if(*exp_p == ';')
714 {
715 loc_token->Add(*exp_p++);
716 loc_token->SetType(ENDLINE);
717 }
718 else
719 if(*exp_p == '"')
720 {
721 ++exp_p;
722 while(exp_p != expr.end() && *exp_p != '"')
723 loc_token->Add(*exp_p++);
724
725 if(*exp_p++ != '"')
726 Error(SYNTAX, loc_token);
727
728 loc_token->SetType(TEXT);
729 loc_token->type_var = STRING;
730 }
731 else
732 {
733 loc_token->Add(*exp_p++);
734 loc_token->SetType(UNK);
735 }
736 return loc_token;
737 }
738
739
GetToken()740 void CalcParser::GetToken()
741 {
742 token = &token_end;
743 if(i_toks == Tokens.end())
744 return;
745 token = &(*i_toks++);
746 }
747
748
GetExpression(String eq,bool html)749 String CalcParser::GetExpression(String eq, bool html)
750 {
751 if(binit_var)
752 return "";
753
754 String es = "";
755 String number_color, function_color, delimiter_color, default_color;
756 String b_tag, e_tag;
757 String def_expr = "0";
758 Token t, next_t;
759 bool empty = Tokens.empty();
760 String space;
761 String tokVal;
762 MapStrings::const_iterator mit;
763
764 if(empty)
765 AddToken(&def_expr);
766
767 TokenList::iterator tit = Tokens.begin();
768
769 default_color = GetStrValueVariable("default_color");
770 number_color = GetStrValueVariable("number_color");
771 function_color = GetStrValueVariable("function_color");
772 delimiter_color = GetStrValueVariable("delimiter_color");
773
774 this->eq = eq;
775 while(tit != Tokens.end())
776 {
777 t = *tit++;
778 if(t.Type() != ERR)
779 {
780 tokVal = t.Value();
781
782 b_tag = e_tag = "";
783
784 space = " ";
785 next_t = token_end;
786 if(tit != Tokens.end())
787 {
788 next_t = *tit;
789 if(next_t.Type() == ERR)
790 next_t.SetType(END);
791 }
792
793 if(html)
794 {
795 b_tag = "<FONT color=" + default_color + ">";
796 if(t.Type() == NUMBER || t.prefix)
797 b_tag = "<FONT color=" + number_color + ">";
798 if(t.Type() == FUNCTION)
799 b_tag = "<FONT color=" + function_color + ">";
800 if(t.Type() == DELIMITER && t.Value() != ")" && t.Value() != "(" && !t.prefix)
801 b_tag = "<FONT color=" + delimiter_color + ">";
802 e_tag = "</FONT>";
803
804 if(t.Type() == FUNCTION)
805 //tokVal.erase(tokVal.end() - 1);
806 tokVal.remove('(');
807 mit = ToksHtml.find(tokVal);
808 if(mit != ToksHtml.end())
809 {
810 #ifdef _QT4
811 tokVal = *mit;
812 #else
813 tokVal = mit->second;
814 #endif
815 }
816 if(t.Type() == FUNCTION)
817 tokVal += '(';
818 }
819
820 if(tokVal == "(" || next_t.Value() == ")" || t.Type() == FUNCTION || next_t.Type() == END || t.prefix)
821 space = "";
822
823 es.append(b_tag + tokVal + e_tag + space);
824 }
825 }
826
827 if(t.Value() != "=")
828 es += eq;
829 if(empty)
830 Tokens.clear();
831 return es;
832 }
833
834
Space(Char c)835 bool CalcParser::Space(Char c)
836 {
837 if(c == ' ' || c == ' ' || c == '\n') //пробел или таб или перевод строки
838 return true;
839 return false;
840 }
841
842
strchr(String t,Char c)843 bool CalcParser::strchr(String t, Char c)
844 {
845 if (IndexOf(&t, c) >= 0)
846 return true;
847 return false;
848 }
849
850
Error(int c_err,Token * current_token)851 void CalcParser::Error(int c_err, Token *current_token)
852 {
853 Token t;
854
855 err = c_err;
856 if(!current_token)
857 current_token = token;
858
859 if(current_token->Type() == END)
860 {
861 t.SetType(ERR);
862 t.SetErr(err);
863 t.SetValue("ERR");
864
865 Tokens.push_back(t);
866 i_toks = Tokens.end();
867 }
868 else
869 current_token->SetErr(err);
870 }
871
listErrors()872 const String CalcParser::listErrors()
873 {
874 String errs = "";
875 Token *t;
876
877 for(TokenList::iterator it = Tokens.begin(); it != Tokens.end(); it++)
878 {
879 t = &(*it);
880 if(t->Err() != -1)
881 {
882 if((unsigned int)t->Err() < sizeof(_Errors)/sizeof(String))
883 errs.append(tr(_Errors[t->Err()].toAscii()));
884 else
885 errs.append("?");
886 errs += "\n";
887 }
888 }
889 return errs;
890 }
891
892
EraseErrors()893 void CalcParser::EraseErrors()
894 {
895 // if(err == -1)
896 // return;
897
898 Token *t;
899
900 for(TokenList::iterator it = Tokens.begin(); it != Tokens.end(); ++it)
901 {
902 t = &(*it);
903
904 if(t->Type() == ERR)
905 {
906 it = Tokens.erase(it);
907 --it;
908 continue;
909 }
910 if(t->Err() != -1)
911 t->SetErr(-1);
912 }
913 err = -1;
914 }
915
916
917
918
919
isdigit(Char c)920 bool CalcParser::isdigit(Char c)
921 {
922 if((strchr("0123456789.ie", c) && scale == 10) || (((c >= 'A' && c <= 'F') || strchr("0123456789", c)) && scale == 16) ||
923 (strchr("01", c) && scale == 2) || (strchr("01234567", c) && scale == 8) ||
924 (((c >= 'A' && c <= 'F') || strchr("0123456789.e,", c)) && scale == 0))
925 return true;
926 return false;
927 }
928
929
930
isalpha(Char c)931 bool CalcParser::isalpha(Char c)
932 {
933 if((c >= 'a' && c <= 'z') || c == '_')
934 return true;
935 return false;
936 }
937
938
Add_exp(CValue * res)939 void CalcParser::Add_exp(CValue *res)
940 {
941 CValue temp;
942 Char op;
943
944 Mul_exp(res);
945
946 while(token->Value() == "+" || token->Value() == "-")
947 {
948 op = token->Value()[0];
949 GetToken();
950 Mul_exp(&temp);
951
952 if(temp.Type() != res->Type())
953 Error(TMS);
954
955 if(op == '+')
956 {
957 if(temp.Type() == STRING)
958 res->SetValue(res->ValueString() + temp.ValueString());
959 else
960 res->SetValue(res->ValueFloat() + temp.ValueFloat());
961 }
962 if(op == '-')
963 res->SetValue(res->ValueFloat() - temp.ValueFloat());
964 }
965 }
966
967
Mul_exp(CValue * res)968 void CalcParser::Mul_exp(CValue *res)
969 {
970 CValue temp;
971 Char op;
972 char c_op;
973
974 Step_exp(res);
975
976 while(token->Value() == "*" || token->Value() == "/" || token->Value() == ">>" ||
977 token->Value() == "<<" || token->Value() == "%" ||
978 token->Value() == "&" || token->Value() == "|" || token->Value() == "!")
979 {
980
981 op = token->Value()[0];
982 #ifdef _QT4
983 c_op = (char)(op.toAscii());
984 #else
985 c_op = op;
986 #endif
987
988 GetToken();
989 Step_exp(&temp);
990
991 if(temp.Type() != res->Type())
992 {
993 Error(TMS);
994 break;
995 }
996
997 switch(c_op)
998 {
999 case '*':
1000 res->SetValue(RoundS((res->ValueFloat() * temp.ValueFloat()), PRECISION_FOR_DOUBLE));
1001 break;
1002 case '/':
1003 if(temp.ValueFloat() == 0)
1004 Error(DIVISION);
1005 else
1006 res->SetValue(res->ValueFloat() / temp.ValueFloat());
1007 break;
1008 case '<':
1009 res->SetValue((UINT)res->ValueFloat() << (UINT)temp.ValueFloat());
1010 break;
1011 case '>':
1012 res->SetValue((UINT)res->ValueFloat() >> (UINT)temp.ValueFloat());
1013 break;
1014 case '%':
1015 if(temp.ValueFloat() == 0)
1016 Error(DIVISION);
1017 res->SetValue(fmod(res->ValueFloat(), temp.ValueFloat()));
1018 break;
1019 case '&':
1020 res->SetValue((int)res->ValueFloat() & (int)temp.ValueFloat());
1021 break;
1022 case '|':
1023 res->SetValue((int)res->ValueFloat() | (int)temp.ValueFloat());
1024 break;
1025 case '!':
1026 res->SetValue((int)res->ValueFloat() ^ (int)temp.ValueFloat());
1027 break;
1028 }
1029
1030 }
1031 }
1032
1033
Step_exp(CValue * res)1034 void CalcParser::Step_exp(CValue *res)
1035 {
1036 CValue temp;
1037
1038 Sign_exp(res);
1039
1040 if((token->Type() == DELIMITER) && (token->Value() == "^"))
1041 {
1042 GetToken();
1043 Step_exp(&temp);
1044
1045 if(temp.Type() != res->Type())
1046 Error(TMS);
1047
1048 res->SetValue(RoundS(pow(res->ValueFloat(), temp.ValueFloat()), PRECISION_FOR_DOUBLE));
1049 }
1050 }
1051
1052
Sign_exp(CValue * res)1053 void CalcParser::Sign_exp(CValue *res)
1054 {
1055 Char op = ' ';
1056
1057 if((token->Type() == DELIMITER) &&
1058 (token->Value() == "+" || token->Value() == "-" || token->Value() == "~"))
1059 {
1060 op = token->Value()[0];
1061 GetToken();
1062 }
1063 Scob_exp(res);
1064 if(op == '-')
1065 res->SetValue(-res->ValueFloat());
1066 else
1067 if(op == '~')
1068 res->SetValue(~(int)res->ValueFloat());
1069 }
1070
Scob_exp(CValue * res)1071 void CalcParser::Scob_exp(CValue *res)
1072 {
1073 CValue temp;
1074
1075 if(token->Type() == DELIMITER && token->Value() == "(")
1076 {
1077 GetToken();
1078 if(token->Value() == ")")
1079 Error(EMPTBKT);
1080 else
1081 {
1082 Add_exp(&temp);
1083
1084 if(temp.Type() != res->Type())
1085 Error(TMS);
1086
1087 res->SetValue(temp.ValueFloat());
1088 if(token->Value() != ")")
1089 Error(BKT);
1090
1091 }
1092 GetToken();
1093 if(token->Type() == NUMBER)
1094 Error(SYNTAX);
1095
1096 }
1097 else
1098 GetNumber(res);
1099 }
1100
1101
GetNumber(CValue * res)1102 void CalcParser::GetNumber(CValue *res)
1103 {
1104 CValue temp;
1105 CValue temp1;
1106 unsigned f;
1107 unsigned f_n_par;
1108 String var;
1109 VarList::const_iterator var_it;
1110 Variable v;
1111
1112 switch(token->Type())
1113 {
1114 case NUMBER:
1115 {
1116 res->SetValue(ScaleToVal(token->Value(), scale));
1117 GetToken();
1118 break;
1119 }
1120 case FUNCTION:
1121 {
1122 f = FindFunction(&token->Value(), &f_n_par);
1123 GetToken();
1124 Add_exp(&temp);
1125 switch(f_n_par)
1126 {
1127 case 1:
1128 if(token->Value() != ")")
1129 Error(BKT);
1130 res->SetValue(CalcFunc(f, temp.ValueFloat()));
1131 break;
1132 case 2:
1133 if(token->Type() != COMMA)
1134 {
1135 Error(SYNTAX);
1136 break;
1137 }
1138 GetToken();
1139 Add_exp(&temp1);
1140 if(token->Value() != ")")
1141 {
1142 Error(BKT);
1143 break;
1144 }
1145 res->SetValue(CalcFunc(f, temp.ValueFloat(), f_n_par, temp1.ValueFloat()));
1146 break;
1147 default:
1148 Error(UNKNOWN);
1149 }
1150 GetToken();
1151 break;
1152 }
1153 case VARIABLE:
1154 var = token->Value();
1155 if(!InitVariableFromExpression()) //если выражение содержит инициализацию переменных
1156 GetToken();
1157 var_it = Vars.find(var);
1158 if(var_it != Vars.end())
1159 {
1160 v = VariableByIterator(var_it);
1161 if(v.type == FLOAT)
1162 res->SetValue(ScaleToVal(v.value));
1163 else
1164 {
1165 res->SetType(v.type);
1166 res->SetValue(v.value);
1167 }
1168
1169 }
1170 else
1171 Error(UNKVAR);
1172 break;
1173 case TEXT:
1174 res->SetType(token->type_var);
1175 res->SetValue(token->Value());
1176 GetToken();
1177 break;
1178 default:
1179 Error(SYNTAX);
1180 GetToken();
1181 }
1182 }
1183
1184
GetStrValueVariable(String varname)1185 String CalcParser::GetStrValueVariable(String varname)
1186 {
1187 VarList::const_iterator var_it = Vars.find(varname);
1188 Variable v;
1189 if(var_it != Vars.end())
1190 {
1191 v = VariableByIterator(var_it);
1192 return v.value;
1193 }
1194 return "";
1195 }
1196
1197
FindFunction(const String * func,unsigned * n)1198 unsigned CalcParser::FindFunction(const String *func, unsigned *n)
1199 {
1200 int i;
1201
1202 *n = 1;
1203 for(i = 0; i < NUMFUNC; i++)
1204 if(func->compare(Func[i]) == 0)
1205 {
1206 if(i == FMAX || i == FMIN)
1207 *n = 2;
1208 return i;
1209 }
1210
1211 return -1;
1212 }
1213
1214
1215
ScaleToVal(String s,int scale)1216 long double CalcParser::ScaleToVal(String s, int scale)
1217 {
1218 int len, i, j;
1219 long double res = 0;
1220 String tst = "";
1221 String::iterator val;
1222
1223 if(!dec_point.empty())
1224 {
1225 String::iterator it = s.begin();
1226 for(; it != s.end(); ++it)
1227 if(*it == '.' && dec_point != ".")
1228 *it = dec_point[0];
1229 }
1230
1231
1232 if(10 == scale)
1233 {
1234 if(IndexOf(&s, 'e') != -1)
1235 {
1236 val = s.begin() + IndexOf(&s, 'e') + 1;
1237 for(; val != s.end(); val++)
1238 tst += *val;
1239 s.resize(IndexOf(&s, 'e'));
1240 res = atof(s.toAscii()) * pow(10, atoi(tst.toAscii()));
1241
1242 }
1243 else
1244 res = atof(s.toAscii());
1245 }
1246 else
1247 {
1248 res = 0;
1249 len = s.size();
1250 j = 0;
1251 for(i = len - 1; i >= 0; i--)
1252 {
1253 tst = "";
1254 if(*(s.begin() + i) > '9')
1255 {
1256 if(*(s.begin() + i) == 'A')
1257 tst += "10";
1258 if(*(s.begin() + i) == 'B')
1259 tst += "11";
1260 if(*(s.begin() + i) == 'C')
1261 tst += "12";
1262 if(*(s.begin() + i) == 'D')
1263 tst += "13";
1264 if(*(s.begin() + i) == 'E')
1265 tst += "14";
1266 if(*(s.begin() + i) == 'F')
1267 tst += "15";
1268 }
1269 else
1270 tst += *(s.begin() + i);
1271
1272 res += pow(scale, j) * atoi(tst.toAscii());
1273 j++;
1274 }
1275 }
1276 return res;
1277 }
1278
1279
CalcFunc(unsigned f,long double arg,unsigned n,long double arg1)1280 long double CalcParser::CalcFunc(unsigned f, long double arg, unsigned n, long double arg1)
1281 {
1282 long double res = 0;
1283
1284 switch(f){
1285 case SIN:
1286 arg = ChoiceArg(arg);
1287 res = sin(arg);
1288 break;
1289 case COS:
1290 arg = ChoiceArg(arg);
1291 res = cos(arg);
1292 break;
1293 case TAN:
1294 arg = ChoiceArg(arg);
1295 res = tan(arg);
1296 break;
1297 case CTN:
1298 arg = ChoiceArg(arg);
1299 res = 1/tan(arg);
1300 break;
1301 case ARCSIN:
1302 if(fabs(arg) > 1)
1303 {
1304 Error(INVALID);
1305 break;
1306 }
1307 res = asin(arg);
1308 res = ChoiceRes(res);
1309 break;
1310 case ARCCOS:
1311 if(fabs(arg) > 1)
1312 {
1313 Error(INVALID);
1314 break;
1315 }
1316 res = acos(arg);
1317 res = ChoiceRes(res);
1318 break;
1319 case ARCTAN:
1320 res = atan(arg);
1321 res = ChoiceRes(res);
1322 break;
1323 case ARCCTN:
1324 res = 1 / atan(arg);
1325 res = ChoiceRes(res);
1326 break;
1327 case SINH:
1328 arg = ChoiceArg(arg);
1329 res = sinh(arg);
1330 break;
1331 case COSH:
1332 arg = ChoiceArg(arg);
1333 res = cosh(arg);
1334 break;
1335 case TANH:
1336 arg = ChoiceArg(arg);
1337 res = tanh(arg);
1338 break;
1339 case CTANH:
1340 arg = ChoiceArg(arg);
1341 res = 1 / tanh(arg);
1342 break;
1343 case ASINH:
1344 res = asinh(arg);
1345 res = ChoiceRes(res);
1346 break;
1347 case ACOSH:
1348 res = acosh(arg);
1349 res = ChoiceRes(res);
1350 break;
1351 case ATANH:
1352 res = atanh(arg);
1353 res = ChoiceRes(res);
1354 break;
1355 case ACTNH:
1356 res = 1 / atanh(arg);
1357 res = ChoiceRes(res);
1358 break;
1359 case LN:
1360 res = log(arg);
1361 break;
1362 case LOG:
1363 res= log10(arg);
1364 break;
1365 case FACT:
1366 if(arg < 0)
1367 {
1368 Error(INVALID);
1369 break;
1370 }
1371 res = Factorial((long int)arg);
1372 break;
1373 case FMAX:
1374 if(n != 2)
1375 {
1376 Error(UNKNOWN);
1377 break;
1378 }
1379 res = arg > arg1? arg: arg1;
1380 break;
1381 case FMIN:
1382 if(n != 2)
1383 {
1384 Error(UNKNOWN);
1385 break;
1386 }
1387 res = arg < arg1? arg: arg1;
1388 break;
1389 case DMS:
1390 res = Dms(arg, false);
1391 break;
1392 case DEG:
1393 res = Dms(arg, true);
1394 break;
1395 case SQRT:
1396 if(arg < 0)
1397 {
1398 Error(INVALID);
1399 break;
1400 }
1401 res = sqrt(arg);
1402 break;
1403 case TERRT:
1404 if(arg < 0)
1405 {
1406 Error(INVALID);
1407 break;
1408 }
1409 res = pow(arg, 1.0 / 3.0);
1410 break;
1411 default:
1412 Error(UNDEFINED);
1413 }
1414 return CheckNumberZero(res);
1415 }
1416
1417
1418
Dms(long double arg,bool invert)1419 long double CalcParser::Dms(long double arg, bool invert)
1420 {
1421 long double m = 0, s = 0, res;
1422 long double koeff = 0.6;
1423 String temp;
1424
1425 if(invert)
1426 koeff = 1;
1427
1428 //45.1348
1429
1430 m = modfl(arg, &arg);
1431 m *= koeff * 100;
1432 s = modfl(m, &m);
1433
1434 if(s > 0.9999)
1435 {
1436 s = 0;
1437 m++;
1438 }
1439
1440 s *= koeff;
1441 if(invert)
1442 res = arg + m / 60 + s / 36;
1443 else
1444 res = arg + (m + s) / 100;
1445
1446 return RoundS(res, PRECISION_FOR_DOUBLE);
1447 }
1448
1449
RoundS(long double arg,int precision)1450 long double CalcParser::RoundS(long double arg, int precision)
1451 {
1452 if(-1 == precision)
1453 return arg;
1454 String s = DoubleToString(arg, precision); // округление через строки...
1455 return ScaleToVal(s, scale);
1456 }
1457
1458
Factorial(long int arg)1459 long double CalcParser::Factorial(long int arg)
1460 {
1461
1462 if(arg == 0)
1463 return 1;
1464 return Factorial(arg - 1) * arg;
1465 }
1466
1467
ChoiceArg(long double arg)1468 long double CalcParser::ChoiceArg(long double arg)
1469 {
1470 long double temp = arg / (180 / M_PI);
1471 if(DRG_mode == RDEG)
1472 return temp;
1473 else
1474 if(DRG_mode == RGRAD)
1475 return temp * 0.9;
1476 return arg;
1477 }
1478
1479
ChoiceRes(long double res)1480 long double CalcParser::ChoiceRes(long double res)
1481 {
1482 long double temp = (180 / M_PI) * res;
1483
1484 if(DRG_mode == RDEG)
1485 return temp;
1486 else
1487 if(DRG_mode == RGRAD)
1488 return temp / 0.9;
1489 return res;
1490 }
1491
1492
IndexOf(const String * s,Char c)1493 int CalcParser::IndexOf(const String* s, Char c)
1494 {
1495 Char ch = c;
1496 #ifdef _QT4
1497 return s->indexOf(ch);
1498 #else
1499 return s->find(ch);
1500 #endif
1501 }
1502
DoubleToString(long double n,int precision)1503 String CalcParser::DoubleToString(long double n, int precision)
1504 {
1505 String res;
1506
1507 n = CheckNumberZero(n);
1508
1509 #ifdef _QT4
1510 if(10 == scale)
1511 res = String::number(n, 'g', precision);
1512 else
1513 {
1514 res = String::number((ulong)n, scale);
1515 res = res.toUpper();
1516 }
1517 #else
1518 std::stringstream str_stream;
1519
1520 if(10 == scale)
1521 str_stream << std::setprecision(precision) << n;
1522 if(16 == scale)
1523 str_stream << std::hex << (unsigned int)n;
1524 if(8 == scale)
1525 str_stream << std::oct << (unsigned int)n;
1526 if(2 == scale)
1527 {
1528 scale = 16;
1529 str_stream << HexToBinString(DoubleToString(n));
1530 scale = 2;
1531 }
1532
1533 str_stream >> res;
1534 for (size_t i = 0; i < res.length(); ++i)
1535 res[i] = std::toupper(res[i]);
1536
1537 #endif
1538 return res;
1539 }
1540
1541
1542
VariableByIterator(VarList::const_iterator vit)1543 Variable CalcParser::VariableByIterator(VarList::const_iterator vit)
1544 {
1545 Variable v;
1546 #ifdef _QT4
1547 v = *vit;
1548 #else
1549 v = vit->second;
1550 #endif
1551 return v;
1552 }
1553
InitMapToksHtml()1554 void CalcParser::InitMapToksHtml()
1555 {
1556 ToksHtml["*"] = "×";
1557 ToksHtml["pi"] = "π";
1558 ToksHtml["&"] = "&";
1559 //ToksHtml["|"] = "¦";
1560 ToksHtml[">>"] = "»";
1561 ToksHtml["<<"] = "«";
1562 ToksHtml["sqrt"] = "√";
1563 ToksHtml["terrt"] = "³√";
1564 }
1565
1566
InitHex2Bin()1567 void CalcParser::InitHex2Bin()
1568 {
1569 Char Hex[] = {'0', '1', '2', '3', '4', '5',
1570 '6', '7', '8', '9', 'A', 'B',
1571 'C', 'D', 'E', 'F'};
1572 String Bin[] = {"0000", "0001", "0010", "0011", "0100", "0101",
1573 "0110", "0111", "1000", "1001", "1010", "1011",
1574 "1100", "1101", "1110", "1111"};
1575 if(Hex2Bin.empty())
1576 {
1577 for(int i = 0; i < 16; ++i)
1578 Hex2Bin[Hex[i]] = Bin[i];
1579 }
1580
1581 }
1582
1583
HexToBinString(String s)1584 String CalcParser::HexToBinString(String s)
1585 {
1586 InitHex2Bin();
1587 String result = "";
1588 Char h;
1589 String b;
1590 MapCharString::iterator mit;
1591 String::const_iterator it = s.begin();
1592 for(; it != s.end(); it++)
1593 {
1594 h = *it;
1595 mit = Hex2Bin.find(h);
1596 if(mit != Hex2Bin.end())
1597 #ifdef _QT4
1598 b = *mit;
1599 #else
1600 b = mit->second;
1601 #endif
1602 else
1603 b = "";
1604 result.append(b);
1605 };
1606 return result;
1607 }
1608
CheckNumberZero(long double n)1609 long double CalcParser::CheckNumberZero(long double n)
1610 {
1611 if(fabs(n) < (1.0 * pow(10.0, -15)))
1612 return 0;
1613 return n;
1614 }
1615
RefTokens(void)1616 const TokenList& CalcParser::RefTokens(void)
1617 {
1618 return Tokens;
1619 }
1620