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(&ltok->Value(), '.') != -1 && nTok->Value() == ".e+")
473                         nTok->SetValue("e+");
474 
475                     if(IndexOf(&ltok->Value(), '.') != -1 && IndexOf(&nTok->Value(), '.') != -1)
476                         return false;
477                     if(IndexOf(&ltok->Value(), 'e') != -1 && IndexOf(&nTok->Value(), 'e') != -1)
478                         return false;
479                     if(IndexOf(&ltok->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["*"] = "&times;";
1557     ToksHtml["pi"] = "&pi;";
1558     ToksHtml["&"] = "&amp;";
1559     //ToksHtml["|"] = "&brvbar;";
1560     ToksHtml[">>"] = "&raquo;";
1561     ToksHtml["<<"] = "&laquo;";
1562     ToksHtml["sqrt"] = "&radic;";
1563     ToksHtml["terrt"] = "&sup3;&radic;";
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