Library for big numbers from http://www.ttmath.org/
Dependents: PIDHeater82 Conceptcontroller_v_1_0 AlarmClockApp COG4050_adxl355_tilt ... more
ttmathparser.h
00001 /* 00002 * This file is a part of TTMath Bignum Library 00003 * and is distributed under the (new) BSD licence. 00004 * Author: Tomasz Sowa <t.sowa@ttmath.org> 00005 */ 00006 00007 /* 00008 * Copyright (c) 2006-2010, Tomasz Sowa 00009 * All rights reserved. 00010 * 00011 * Redistribution and use in source and binary forms, with or without 00012 * modification, are permitted provided that the following conditions are met: 00013 * 00014 * * Redistributions of source code must retain the above copyright notice, 00015 * this list of conditions and the following disclaimer. 00016 * 00017 * * Redistributions in binary form must reproduce the above copyright 00018 * notice, this list of conditions and the following disclaimer in the 00019 * documentation and/or other materials provided with the distribution. 00020 * 00021 * * Neither the name Tomasz Sowa nor the names of contributors to this 00022 * project may be used to endorse or promote products derived 00023 * from this software without specific prior written permission. 00024 * 00025 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00026 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00027 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00028 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 00029 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00030 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00031 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00032 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00033 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00034 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 00035 * THE POSSIBILITY OF SUCH DAMAGE. 00036 */ 00037 00038 00039 00040 #ifndef headerfilettmathparser 00041 #define headerfilettmathparser 00042 00043 /*! 00044 \file ttmathparser.h 00045 \brief A mathematical parser 00046 */ 00047 00048 #include <cstdio> 00049 #include <vector> 00050 #include <map> 00051 #include <set> 00052 00053 #include "ttmath.h" 00054 #include "ttmathobjects.h" 00055 #include "ttmathmisc.h" 00056 00057 00058 00059 namespace ttmath 00060 { 00061 00062 /*! 00063 \brief Mathematical parser 00064 00065 let x will be an input string meaning an expression for converting: 00066 00067 x = [+|-]Value[operator[+|-]Value][operator[+|-]Value]... 00068 where: 00069 an operator can be: 00070 ^ (pow) (the heighest priority) 00071 00072 * (mul) (or multiplication without an operator -- short mul) 00073 / (div) (* and / have the same priority) 00074 00075 + (add) 00076 - (sub) (+ and - have the same priority) 00077 00078 < (lower than) 00079 > (greater than) 00080 <= (lower or equal than) 00081 >= (greater or equal than) 00082 == (equal) 00083 != (not equal) (all above logical operators have the same priority) 00084 00085 && (logical and) 00086 00087 || (logical or) (the lowest priority) 00088 00089 short mul: 00090 if the second Value (Var below) is either a variable or function there might not be 00091 an operator between them, e.g. 00092 "[+|-]Value Var" is treated as "[+|-]Value * Var" and the multiplication 00093 has the same priority as a normal multiplication: 00094 4x = 4 * x 00095 2^3m = (2^3)* m 00096 6h^3 = 6 * (h^3) 00097 2sin(pi) = 2 * sin(pi) 00098 etc. 00099 00100 Value can be: 00101 constant e.g. 100, can be preceded by operators for changing the base (radix): [#|&] 00102 # - hex 00103 & - bin 00104 sample: #10 = 16 00105 &10 = 2 00106 variable e.g. pi 00107 another expression between brackets e.g (x) 00108 function e.g. sin(x) 00109 00110 for example a correct input string can be: 00111 "1" 00112 "2.1234" 00113 "2,1234" (they are the same, by default we can either use a comma or a dot) 00114 "1 + 2" 00115 "(1 + 2) * 3" 00116 "pi" 00117 "sin(pi)" 00118 "(1+2)*(2+3)" 00119 "log(2;1234)" there's a semicolon here (not a comma), we use it in functions 00120 for separating parameters 00121 "1 < 2" (the result will be: 1) 00122 "4 < 3" (the result will be: 0) 00123 "2+x" (of course if the variable 'x' is defined) 00124 "4x+10" 00125 "#20+10" = 32 + 10 = 42 00126 "10 ^ -&101" = 10 ^ -5 = 0.00001 00127 "8 * -&10" = 8 * -2 = -16 00128 etc. 00129 00130 we can also use a semicolon for separating any 'x' input strings 00131 for example: 00132 "1+2;4+5" 00133 the result will be on the stack as follows: 00134 stack[0].value=3 00135 stack[1].value=9 00136 */ 00137 template<class ValueType> 00138 class Parser 00139 { 00140 private: 00141 00142 /*! 00143 there are 5 mathematical operators as follows (with their standard priorities): 00144 add (+) 00145 sub (-) 00146 mul (*) 00147 div (/) 00148 pow (^) 00149 and 'shortmul' used when there is no any operators between 00150 a first parameter and a variable or function 00151 (the 'shortmul' has the same priority as the normal multiplication ) 00152 */ 00153 class MatOperator 00154 { 00155 public: 00156 00157 enum Type 00158 { 00159 none,add,sub,mul,div,pow,lt,gt,let,get,eq,neq,lor,land,shortmul 00160 }; 00161 00162 enum Assoc 00163 { 00164 right, // right-associative 00165 non_right // associative or left-associative 00166 }; 00167 00168 Type GetType() const { return type; } 00169 int GetPriority() const { return priority; } 00170 Assoc GetAssoc() const { return assoc; } 00171 00172 void SetType(Type t) 00173 { 00174 type = t; 00175 assoc = non_right; 00176 00177 switch( type ) 00178 { 00179 case lor: 00180 priority = 4; 00181 break; 00182 00183 case land: 00184 priority = 5; 00185 break; 00186 00187 case eq: 00188 case neq: 00189 case lt: 00190 case gt: 00191 case let: 00192 case get: 00193 priority = 7; 00194 break; 00195 00196 case add: 00197 case sub: 00198 priority = 10; 00199 break; 00200 00201 case mul: 00202 case shortmul: 00203 case div: 00204 priority = 12; 00205 break; 00206 00207 case pow: 00208 priority = 14; 00209 assoc = right; 00210 break; 00211 00212 default: 00213 Error( err_internal_error ); 00214 break; 00215 } 00216 } 00217 00218 MatOperator(): type(none), priority(0), assoc(non_right) 00219 { 00220 } 00221 00222 private: 00223 00224 Type type; 00225 int priority; 00226 Assoc assoc; 00227 }; // end of MatOperator class 00228 00229 00230 00231 public: 00232 00233 00234 00235 /*! 00236 Objects of type 'Item' we are keeping on our stack 00237 */ 00238 struct Item 00239 { 00240 enum Type 00241 { 00242 none, numerical_value, mat_operator, first_bracket, 00243 last_bracket, variable, semicolon 00244 }; 00245 00246 // The kind of type which we're keeping 00247 Type type; 00248 00249 // if type == numerical_value 00250 ValueType value; 00251 00252 // if type == mat_operator 00253 MatOperator moperator; 00254 00255 /* 00256 if type == first_bracket 00257 00258 if 'function' is set to true it means that the first recognized bracket 00259 was the bracket from function in other words we must call a function when 00260 we'll find the 'last' bracket 00261 */ 00262 bool function; 00263 00264 // if function is true 00265 std::string function_name; 00266 00267 /* 00268 the sign of value 00269 00270 it can be for type==numerical_value or type==first_bracket 00271 when it's true it means e.g. that value is equal -value 00272 */ 00273 bool sign; 00274 00275 Item (): type(none), function(false), sign(false) 00276 { 00277 } 00278 00279 }; // end of Item struct 00280 00281 00282 /*! 00283 stack on which we're keeping the Items 00284 00285 at the end of parsing we'll have the result here 00286 the result don't have to be one value, it can be 00287 more than one if we have used a semicolon in the global space 00288 e.g. such input string "1+2;3+4" will generate a result: 00289 stack[0].value=3 00290 stack[1].value=7 00291 00292 you should check if the stack is not empty, because if there was 00293 a syntax error in the input string then we do not have any results 00294 on the stack 00295 */ 00296 std::vector<Item> stack ; 00297 00298 00299 private: 00300 00301 00302 /*! 00303 size of the stack when we're starting parsing of the string 00304 00305 if it's to small while parsing the stack will be automatically resized 00306 */ 00307 const int default_stack_size; 00308 00309 00310 00311 /*! 00312 index of an object in our stack 00313 it's pointing on the place behind the last element 00314 for example at the beginning of parsing its value is zero 00315 */ 00316 unsigned int stack_index; 00317 00318 00319 /*! 00320 code of the last error 00321 */ 00322 ErrorCode error; 00323 00324 00325 /*! 00326 pointer to the currently reading char 00327 when an error has occured it may be used to count the index of the wrong character 00328 */ 00329 const char * pstring; 00330 00331 00332 /*! 00333 the base (radix) of the mathematic system (for example it may be '10') 00334 */ 00335 int base; 00336 00337 00338 /*! 00339 the unit of angles used in: sin,cos,tan,cot,asin,acos,atan,acot 00340 0 - deg 00341 1 - rad (default) 00342 2 - grad 00343 */ 00344 int deg_rad_grad; 00345 00346 00347 00348 /*! 00349 a pointer to an object which tell us whether we should stop calculating or not 00350 */ 00351 const volatile StopCalculating * pstop_calculating; 00352 00353 00354 00355 /*! 00356 a pointer to the user-defined variables' table 00357 */ 00358 const Objects * puser_variables; 00359 00360 /*! 00361 a pointer to the user-defined functions' table 00362 */ 00363 const Objects * puser_functions; 00364 00365 00366 typedef std::map<std::string, ValueType> FunctionLocalVariables; 00367 00368 /*! 00369 a pointer to the local variables of a function 00370 */ 00371 const FunctionLocalVariables * pfunction_local_variables; 00372 00373 00374 /*! 00375 a temporary set using during parsing user defined variables 00376 */ 00377 std::set<std::string> visited_variables; 00378 00379 00380 /*! 00381 a temporary set using during parsing user defined functions 00382 */ 00383 std::set<std::string> visited_functions; 00384 00385 00386 00387 00388 /*! 00389 pfunction is the type of pointer to a mathematic function 00390 00391 these mathematic functions are private members of this class, 00392 they are the wrappers for standard mathematics function 00393 00394 'pstack' is the pointer to the first argument on our stack 00395 'amount_of_arg' tell us how many argument there are in our stack 00396 'result' is the reference for result of function 00397 */ 00398 typedef void (Parser<ValueType>::*pfunction)(int pstack, int amount_of_arg, ValueType & result); 00399 00400 00401 /*! 00402 pfunction is the type of pointer to a method which returns value of variable 00403 */ 00404 typedef void (ValueType::*pfunction_var)(); 00405 00406 00407 /*! 00408 table of mathematic functions 00409 00410 this map consists of: 00411 std::string - function's name 00412 pfunction - pointer to specific function 00413 */ 00414 typedef std::map<std::string, pfunction> FunctionsTable; 00415 FunctionsTable functions_table; 00416 00417 00418 /*! 00419 table of mathematic operators 00420 00421 this map consists of: 00422 std::string - operators's name 00423 MatOperator::Type - type of the operator 00424 */ 00425 typedef std::map<std::string, typename MatOperator::Type> OperatorsTable; 00426 OperatorsTable operators_table; 00427 00428 00429 /*! 00430 table of mathematic variables 00431 00432 this map consists of: 00433 std::string - variable's name 00434 pfunction_var - pointer to specific function which returns value of variable 00435 */ 00436 typedef std::map<std::string, pfunction_var> VariablesTable; 00437 VariablesTable variables_table; 00438 00439 00440 /*! 00441 some coefficients used when calculating the gamma (or factorial) function 00442 */ 00443 CGamma<ValueType> cgamma; 00444 00445 00446 /*! 00447 temporary object for a whole string when Parse(std::wstring) is used 00448 */ 00449 std::string wide_to_ansi; 00450 00451 00452 /*! 00453 group character (used when parsing) 00454 default zero (not used) 00455 */ 00456 int group; 00457 00458 00459 /*! 00460 characters used as a comma 00461 default: '.' and ',' 00462 comma2 can be zero (it means it is not used) 00463 */ 00464 int comma, comma2; 00465 00466 00467 /*! 00468 an additional character used as a separator between function parameters 00469 (semicolon is used always) 00470 */ 00471 int param_sep; 00472 00473 00474 /*! 00475 true if something was calculated (at least one mathematical operator was used or a function or a variable) 00476 */ 00477 bool calculated; 00478 00479 00480 00481 /*! 00482 we're using this method for reporting an error 00483 */ 00484 static void Error(ErrorCode code) 00485 { 00486 throw code; 00487 } 00488 00489 00490 /*! 00491 this method skips the white character from the string 00492 00493 it's moving the 'pstring' to the first no-white character 00494 */ 00495 void SkipWhiteCharacters() 00496 { 00497 while( (*pstring==' ' ) || (*pstring=='\t') ) 00498 ++pstring; 00499 } 00500 00501 00502 /*! 00503 an auxiliary method for RecurrenceParsingVariablesOrFunction(...) 00504 */ 00505 void RecurrenceParsingVariablesOrFunction_CheckStopCondition(bool variable, const std::string & name) 00506 { 00507 if( variable ) 00508 { 00509 if( visited_variables.find(name) != visited_variables.end() ) 00510 Error( err_variable_loop ); 00511 } 00512 else 00513 { 00514 if( visited_functions.find(name) != visited_functions.end() ) 00515 Error( err_functions_loop ); 00516 } 00517 } 00518 00519 00520 /*! 00521 an auxiliary method for RecurrenceParsingVariablesOrFunction(...) 00522 */ 00523 void RecurrenceParsingVariablesOrFunction_AddName(bool variable, const std::string & name) 00524 { 00525 if( variable ) 00526 visited_variables.insert( name ); 00527 else 00528 visited_functions.insert( name ); 00529 } 00530 00531 00532 /*! 00533 an auxiliary method for RecurrenceParsingVariablesOrFunction(...) 00534 */ 00535 void RecurrenceParsingVariablesOrFunction_DeleteName(bool variable, const std::string & name) 00536 { 00537 if( variable ) 00538 visited_variables.erase( name ); 00539 else 00540 visited_functions.erase( name ); 00541 } 00542 00543 00544 /*! 00545 this method returns the value of a variable or function 00546 by creating a new instance of the mathematical parser 00547 and making the standard parsing algorithm on the given string 00548 00549 this method is used only during parsing user defined variables or functions 00550 00551 (there can be a recurrence here therefore we're using 'visited_variables' 00552 and 'visited_functions' sets to make a stop condition) 00553 */ 00554 ValueType RecurrenceParsingVariablesOrFunction(bool variable, const std::string & name, const char * new_string, 00555 FunctionLocalVariables * local_variables = 0) 00556 { 00557 RecurrenceParsingVariablesOrFunction_CheckStopCondition(variable, name); 00558 RecurrenceParsingVariablesOrFunction_AddName(variable, name); 00559 00560 Parser<ValueType> NewParser(*this); 00561 ErrorCode err; 00562 00563 NewParser.pfunction_local_variables = local_variables; 00564 00565 try 00566 { 00567 err = NewParser.Parse(new_string); 00568 } 00569 catch(...) 00570 { 00571 RecurrenceParsingVariablesOrFunction_DeleteName(variable, name); 00572 00573 throw; 00574 } 00575 00576 RecurrenceParsingVariablesOrFunction_DeleteName(variable, name); 00577 00578 if( err != err_ok ) 00579 Error( err ); 00580 00581 if( NewParser.stack.size() != 1 ) 00582 Error( err_must_be_only_one_value ); 00583 00584 if( NewParser.stack[0].type != Item::numerical_value ) 00585 // I think there shouldn't be this error here 00586 Error( err_incorrect_value ); 00587 00588 return NewParser.stack[0].value; 00589 } 00590 00591 00592 public: 00593 00594 00595 /*! 00596 this method returns the user-defined value of a variable 00597 */ 00598 bool GetValueOfUserDefinedVariable (const std::string & variable_name,ValueType & result) 00599 { 00600 if( !puser_variables ) 00601 return false; 00602 00603 const char * string_value; 00604 00605 if( puser_variables->GetValue (variable_name, &string_value) != err_ok ) 00606 return false; 00607 00608 result = RecurrenceParsingVariablesOrFunction(true, variable_name, string_value); 00609 calculated = true; 00610 00611 return true; 00612 } 00613 00614 00615 /*! 00616 this method returns the value of a local variable of a function 00617 */ 00618 bool GetValueOfFunctionLocalVariable (const std::string & variable_name, ValueType & result) 00619 { 00620 if( !pfunction_local_variables ) 00621 return false; 00622 00623 typename FunctionLocalVariables::const_iterator i = pfunction_local_variables->find(variable_name); 00624 00625 if( i == pfunction_local_variables->end() ) 00626 return false; 00627 00628 result = i->second; 00629 00630 return true; 00631 } 00632 00633 00634 /*! 00635 this method returns the value of a variable from variables' table 00636 00637 we make an object of type ValueType then call a method which 00638 sets the correct value in it and finally we'll return the object 00639 */ 00640 ValueType GetValueOfVariable (const std::string & variable_name) 00641 { 00642 ValueType result; 00643 00644 if( GetValueOfFunctionLocalVariable (variable_name, result) ) 00645 return result; 00646 00647 if( GetValueOfUserDefinedVariable (variable_name, result) ) 00648 return result; 00649 00650 00651 typename std::map<std::string, pfunction_var>::iterator i = 00652 variables_table.find(variable_name); 00653 00654 if( i == variables_table.end() ) 00655 Error( err_unknown_variable ); 00656 00657 (result.*(i->second))(); 00658 calculated = true; 00659 00660 return result; 00661 } 00662 00663 00664 private: 00665 00666 /*! 00667 wrappers for mathematic functions 00668 00669 'sindex' is pointing on the first argument on our stack 00670 (the second argument has 'sindex+2' 00671 because 'sindex+1' is guaranted for the 'semicolon' operator) 00672 the third artument has of course 'sindex+4' etc. 00673 00674 'result' will be the result of the function 00675 00676 (we're using exceptions here for example when function gets an improper argument) 00677 */ 00678 00679 00680 /*! 00681 used by: sin,cos,tan,cot 00682 */ 00683 ValueType ConvertAngleToRad(const ValueType & input) 00684 { 00685 if( deg_rad_grad == 1 ) // rad 00686 return input; 00687 00688 ValueType result; 00689 ErrorCode err; 00690 00691 if( deg_rad_grad == 0 ) // deg 00692 result = ttmath::DegToRad (input, &err); 00693 else // grad 00694 result = ttmath::GradToRad (input, &err); 00695 00696 if( err != err_ok ) 00697 Error( err ); 00698 00699 return result; 00700 } 00701 00702 00703 /*! 00704 used by: asin,acos,atan,acot 00705 */ 00706 ValueType ConvertRadToAngle(const ValueType & input) 00707 { 00708 if( deg_rad_grad == 1 ) // rad 00709 return input; 00710 00711 ValueType result; 00712 ErrorCode err; 00713 00714 if( deg_rad_grad == 0 ) // deg 00715 result = ttmath::RadToDeg (input, &err); 00716 else // grad 00717 result = ttmath::RadToGrad (input, &err); 00718 00719 if( err != err_ok ) 00720 Error( err ); 00721 00722 return result; 00723 } 00724 00725 00726 void Gamma(int sindex, int amount_of_args, ValueType & result) 00727 { 00728 if( amount_of_args != 1 ) 00729 Error( err_improper_amount_of_arguments ); 00730 00731 ErrorCode err; 00732 00733 result = ttmath::Gamma (stack [sindex].value, cgamma, &err, pstop_calculating); 00734 00735 if(err != err_ok) 00736 Error( err ); 00737 } 00738 00739 00740 /*! 00741 factorial 00742 result = 1 * 2 * 3 * 4 * .... * x 00743 */ 00744 void Factorial(int sindex, int amount_of_args, ValueType & result) 00745 { 00746 if( amount_of_args != 1 ) 00747 Error( err_improper_amount_of_arguments ); 00748 00749 ErrorCode err; 00750 00751 result = ttmath::Factorial (stack [sindex].value, cgamma, &err, pstop_calculating); 00752 00753 if(err != err_ok) 00754 Error( err ); 00755 } 00756 00757 00758 void Abs(int sindex, int amount_of_args, ValueType & result) 00759 { 00760 if( amount_of_args != 1 ) 00761 Error( err_improper_amount_of_arguments ); 00762 00763 result = ttmath::Abs (stack [sindex].value); 00764 } 00765 00766 void Sin(int sindex, int amount_of_args, ValueType & result) 00767 { 00768 if( amount_of_args != 1 ) 00769 Error( err_improper_amount_of_arguments ); 00770 00771 ErrorCode err; 00772 result = ttmath::Sin ( ConvertAngleToRad(stack [sindex].value), &err ); 00773 00774 if(err != err_ok) 00775 Error( err ); 00776 } 00777 00778 void Cos(int sindex, int amount_of_args, ValueType & result) 00779 { 00780 if( amount_of_args != 1 ) 00781 Error( err_improper_amount_of_arguments ); 00782 00783 ErrorCode err; 00784 result = ttmath::Cos ( ConvertAngleToRad(stack [sindex].value), &err ); 00785 00786 if(err != err_ok) 00787 Error( err ); 00788 } 00789 00790 void Tan(int sindex, int amount_of_args, ValueType & result) 00791 { 00792 if( amount_of_args != 1 ) 00793 Error( err_improper_amount_of_arguments ); 00794 00795 ErrorCode err; 00796 result = ttmath::Tan (ConvertAngleToRad(stack [sindex].value), &err); 00797 00798 if(err != err_ok) 00799 Error( err ); 00800 } 00801 00802 void Cot(int sindex, int amount_of_args, ValueType & result) 00803 { 00804 if( amount_of_args != 1 ) 00805 Error( err_improper_amount_of_arguments ); 00806 00807 ErrorCode err; 00808 result = ttmath::Cot (ConvertAngleToRad(stack [sindex].value), &err); 00809 00810 if(err != err_ok) 00811 Error( err ); 00812 } 00813 00814 void Int(int sindex, int amount_of_args, ValueType & result) 00815 { 00816 if( amount_of_args != 1 ) 00817 Error( err_improper_amount_of_arguments ); 00818 00819 result = ttmath::SkipFraction (stack [sindex].value); 00820 } 00821 00822 00823 void Round(int sindex, int amount_of_args, ValueType & result) 00824 { 00825 if( amount_of_args != 1 ) 00826 Error( err_improper_amount_of_arguments ); 00827 00828 result = stack [sindex].value; 00829 00830 if( result.Round() ) 00831 Error( err_overflow ); 00832 } 00833 00834 00835 void Ln(int sindex, int amount_of_args, ValueType & result) 00836 { 00837 if( amount_of_args != 1 ) 00838 Error( err_improper_amount_of_arguments ); 00839 00840 ErrorCode err; 00841 result = ttmath::Ln (stack [sindex].value, &err); 00842 00843 if(err != err_ok) 00844 Error( err ); 00845 } 00846 00847 void Log(int sindex, int amount_of_args, ValueType & result) 00848 { 00849 if( amount_of_args != 2 ) 00850 Error( err_improper_amount_of_arguments ); 00851 00852 ErrorCode err; 00853 result = ttmath::Log (stack [sindex].value, stack [sindex+2].value, &err); 00854 00855 if(err != err_ok) 00856 Error( err ); 00857 } 00858 00859 void Exp(int sindex, int amount_of_args, ValueType & result) 00860 { 00861 if( amount_of_args != 1 ) 00862 Error( err_improper_amount_of_arguments ); 00863 00864 ErrorCode err; 00865 result = ttmath::Exp (stack [sindex].value, &err); 00866 00867 if(err != err_ok) 00868 Error( err ); 00869 } 00870 00871 00872 void Max(int sindex, int amount_of_args, ValueType & result) 00873 { 00874 if( amount_of_args == 0 ) 00875 { 00876 result.SetMax(); 00877 00878 return; 00879 } 00880 00881 result = stack [sindex].value; 00882 00883 for(int i=1 ; i<amount_of_args ; ++i) 00884 { 00885 if( result < stack [sindex + i*2].value ) 00886 result = stack [sindex + i*2].value; 00887 } 00888 } 00889 00890 00891 void Min(int sindex, int amount_of_args, ValueType & result) 00892 { 00893 if( amount_of_args == 0 ) 00894 { 00895 result.SetMin(); 00896 00897 return; 00898 } 00899 00900 result = stack [sindex].value; 00901 00902 for(int i=1 ; i<amount_of_args ; ++i) 00903 { 00904 if( result > stack [sindex + i*2].value ) 00905 result = stack [sindex + i*2].value; 00906 } 00907 } 00908 00909 00910 void ASin(int sindex, int amount_of_args, ValueType & result) 00911 { 00912 if( amount_of_args != 1 ) 00913 Error( err_improper_amount_of_arguments ); 00914 00915 ErrorCode err; 00916 ValueType temp = ttmath::ASin (stack [sindex].value, &err); 00917 00918 if(err != err_ok) 00919 Error( err ); 00920 00921 result = ConvertRadToAngle(temp); 00922 } 00923 00924 00925 void ACos(int sindex, int amount_of_args, ValueType & result) 00926 { 00927 if( amount_of_args != 1 ) 00928 Error( err_improper_amount_of_arguments ); 00929 00930 ErrorCode err; 00931 ValueType temp = ttmath::ACos (stack [sindex].value, &err); 00932 00933 if(err != err_ok) 00934 Error( err ); 00935 00936 result = ConvertRadToAngle(temp); 00937 } 00938 00939 00940 void ATan(int sindex, int amount_of_args, ValueType & result) 00941 { 00942 if( amount_of_args != 1 ) 00943 Error( err_improper_amount_of_arguments ); 00944 00945 result = ConvertRadToAngle(ttmath::ATan (stack [sindex].value)); 00946 } 00947 00948 00949 void ACot(int sindex, int amount_of_args, ValueType & result) 00950 { 00951 if( amount_of_args != 1 ) 00952 Error( err_improper_amount_of_arguments ); 00953 00954 result = ConvertRadToAngle(ttmath::ACot (stack [sindex].value)); 00955 } 00956 00957 00958 void Sgn(int sindex, int amount_of_args, ValueType & result) 00959 { 00960 if( amount_of_args != 1 ) 00961 Error( err_improper_amount_of_arguments ); 00962 00963 result = ttmath::Sgn (stack [sindex].value); 00964 } 00965 00966 00967 void Mod(int sindex, int amount_of_args, ValueType & result) 00968 { 00969 if( amount_of_args != 2 ) 00970 Error( err_improper_amount_of_arguments ); 00971 00972 if( stack [sindex+2].value.IsZero() ) 00973 Error( err_improper_argument ); 00974 00975 result = stack [sindex].value; 00976 uint c = result.Mod(stack [sindex+2].value); 00977 00978 if( c ) 00979 Error( err_overflow ); 00980 } 00981 00982 00983 void If(int sindex, int amount_of_args, ValueType & result) 00984 { 00985 if( amount_of_args != 3 ) 00986 Error( err_improper_amount_of_arguments ); 00987 00988 00989 if( !stack [sindex].value.IsZero() ) 00990 result = stack [sindex+2].value; 00991 else 00992 result = stack [sindex+4].value; 00993 } 00994 00995 00996 void Or(int sindex, int amount_of_args, ValueType & result) 00997 { 00998 if( amount_of_args < 2 ) 00999 Error( err_improper_amount_of_arguments ); 01000 01001 for(int i=0 ; i<amount_of_args ; ++i) 01002 { 01003 if( !stack [sindex+i*2].value.IsZero() ) 01004 { 01005 result.SetOne(); 01006 return; 01007 } 01008 } 01009 01010 result.SetZero(); 01011 } 01012 01013 01014 void And(int sindex, int amount_of_args, ValueType & result) 01015 { 01016 if( amount_of_args < 2 ) 01017 Error( err_improper_amount_of_arguments ); 01018 01019 for(int i=0 ; i<amount_of_args ; ++i) 01020 { 01021 if( stack [sindex+i*2].value.IsZero() ) 01022 { 01023 result.SetZero(); 01024 return; 01025 } 01026 } 01027 01028 result.SetOne(); 01029 } 01030 01031 01032 void Not(int sindex, int amount_of_args, ValueType & result) 01033 { 01034 if( amount_of_args != 1 ) 01035 Error( err_improper_amount_of_arguments ); 01036 01037 01038 if( stack [sindex].value.IsZero() ) 01039 result.SetOne(); 01040 else 01041 result.SetZero(); 01042 } 01043 01044 01045 void DegToRad(int sindex, int amount_of_args, ValueType & result) 01046 { 01047 ErrorCode err = err_ok; 01048 01049 if( amount_of_args == 1 ) 01050 { 01051 result = ttmath::DegToRad (stack [sindex].value, &err); 01052 } 01053 else 01054 if( amount_of_args == 3 ) 01055 { 01056 result = ttmath::DegToRad ( stack [sindex].value, stack [sindex+2].value, 01057 stack [sindex+4].value, &err); 01058 } 01059 else 01060 Error( err_improper_amount_of_arguments ); 01061 01062 01063 if( err != err_ok ) 01064 Error( err ); 01065 } 01066 01067 01068 void RadToDeg(int sindex, int amount_of_args, ValueType & result) 01069 { 01070 ErrorCode err; 01071 01072 if( amount_of_args != 1 ) 01073 Error( err_improper_amount_of_arguments ); 01074 01075 result = ttmath::RadToDeg (stack [sindex].value, &err); 01076 01077 if( err != err_ok ) 01078 Error( err ); 01079 } 01080 01081 01082 void DegToDeg(int sindex, int amount_of_args, ValueType & result) 01083 { 01084 if( amount_of_args != 3 ) 01085 Error( err_improper_amount_of_arguments ); 01086 01087 ErrorCode err; 01088 result = ttmath::DegToDeg ( stack [sindex].value, stack [sindex+2].value, 01089 stack [sindex+4].value, &err); 01090 01091 if( err != err_ok ) 01092 Error( err ); 01093 } 01094 01095 01096 void GradToRad(int sindex, int amount_of_args, ValueType & result) 01097 { 01098 ErrorCode err; 01099 01100 if( amount_of_args != 1 ) 01101 Error( err_improper_amount_of_arguments ); 01102 01103 result = ttmath::GradToRad (stack [sindex].value, &err); 01104 01105 if( err != err_ok ) 01106 Error( err ); 01107 } 01108 01109 01110 void RadToGrad(int sindex, int amount_of_args, ValueType & result) 01111 { 01112 ErrorCode err; 01113 01114 if( amount_of_args != 1 ) 01115 Error( err_improper_amount_of_arguments ); 01116 01117 result = ttmath::RadToGrad (stack [sindex].value, &err); 01118 01119 if( err != err_ok ) 01120 Error( err ); 01121 } 01122 01123 01124 void DegToGrad(int sindex, int amount_of_args, ValueType & result) 01125 { 01126 ErrorCode err = err_ok; 01127 01128 if( amount_of_args == 1 ) 01129 { 01130 result = ttmath::DegToGrad (stack [sindex].value, &err); 01131 } 01132 else 01133 if( amount_of_args == 3 ) 01134 { 01135 result = ttmath::DegToGrad ( stack [sindex].value, stack [sindex+2].value, 01136 stack [sindex+4].value, &err); 01137 } 01138 else 01139 Error( err_improper_amount_of_arguments ); 01140 01141 01142 if( err != err_ok ) 01143 Error( err ); 01144 } 01145 01146 01147 void GradToDeg(int sindex, int amount_of_args, ValueType & result) 01148 { 01149 ErrorCode err; 01150 01151 if( amount_of_args != 1 ) 01152 Error( err_improper_amount_of_arguments ); 01153 01154 result = ttmath::GradToDeg (stack [sindex].value, &err); 01155 01156 if( err != err_ok ) 01157 Error( err ); 01158 } 01159 01160 01161 void Ceil(int sindex, int amount_of_args, ValueType & result) 01162 { 01163 if( amount_of_args != 1 ) 01164 Error( err_improper_amount_of_arguments ); 01165 01166 ErrorCode err; 01167 result = ttmath::Ceil (stack [sindex].value, &err); 01168 01169 if( err != err_ok ) 01170 Error( err ); 01171 } 01172 01173 01174 void Floor(int sindex, int amount_of_args, ValueType & result) 01175 { 01176 if( amount_of_args != 1 ) 01177 Error( err_improper_amount_of_arguments ); 01178 01179 ErrorCode err; 01180 result = ttmath::Floor (stack [sindex].value, &err); 01181 01182 if( err != err_ok ) 01183 Error( err ); 01184 } 01185 01186 void Sqrt(int sindex, int amount_of_args, ValueType & result) 01187 { 01188 if( amount_of_args != 1 ) 01189 Error( err_improper_amount_of_arguments ); 01190 01191 ErrorCode err; 01192 result = ttmath::Sqrt (stack [sindex].value, &err); 01193 01194 if( err != err_ok ) 01195 Error( err ); 01196 } 01197 01198 01199 void Sinh(int sindex, int amount_of_args, ValueType & result) 01200 { 01201 if( amount_of_args != 1 ) 01202 Error( err_improper_amount_of_arguments ); 01203 01204 ErrorCode err; 01205 result = ttmath::Sinh (stack [sindex].value, &err); 01206 01207 if( err != err_ok ) 01208 Error( err ); 01209 } 01210 01211 01212 void Cosh(int sindex, int amount_of_args, ValueType & result) 01213 { 01214 if( amount_of_args != 1 ) 01215 Error( err_improper_amount_of_arguments ); 01216 01217 ErrorCode err; 01218 result = ttmath::Cosh (stack [sindex].value, &err); 01219 01220 if( err != err_ok ) 01221 Error( err ); 01222 } 01223 01224 01225 void Tanh(int sindex, int amount_of_args, ValueType & result) 01226 { 01227 if( amount_of_args != 1 ) 01228 Error( err_improper_amount_of_arguments ); 01229 01230 ErrorCode err; 01231 result = ttmath::Tanh (stack [sindex].value, &err); 01232 01233 if( err != err_ok ) 01234 Error( err ); 01235 } 01236 01237 01238 void Coth(int sindex, int amount_of_args, ValueType & result) 01239 { 01240 if( amount_of_args != 1 ) 01241 Error( err_improper_amount_of_arguments ); 01242 01243 ErrorCode err; 01244 result = ttmath::Coth (stack [sindex].value, &err); 01245 01246 if( err != err_ok ) 01247 Error( err ); 01248 } 01249 01250 01251 void Root(int sindex, int amount_of_args, ValueType & result) 01252 { 01253 if( amount_of_args != 2 ) 01254 Error( err_improper_amount_of_arguments ); 01255 01256 ErrorCode err; 01257 result = ttmath::Root (stack [sindex].value, stack [sindex+2].value, &err); 01258 01259 if( err != err_ok ) 01260 Error( err ); 01261 } 01262 01263 01264 01265 void ASinh(int sindex, int amount_of_args, ValueType & result) 01266 { 01267 if( amount_of_args != 1 ) 01268 Error( err_improper_amount_of_arguments ); 01269 01270 ErrorCode err; 01271 result = ttmath::ASinh (stack [sindex].value, &err); 01272 01273 if( err != err_ok ) 01274 Error( err ); 01275 } 01276 01277 01278 void ACosh(int sindex, int amount_of_args, ValueType & result) 01279 { 01280 if( amount_of_args != 1 ) 01281 Error( err_improper_amount_of_arguments ); 01282 01283 ErrorCode err; 01284 result = ttmath::ACosh (stack [sindex].value, &err); 01285 01286 if( err != err_ok ) 01287 Error( err ); 01288 } 01289 01290 01291 void ATanh(int sindex, int amount_of_args, ValueType & result) 01292 { 01293 if( amount_of_args != 1 ) 01294 Error( err_improper_amount_of_arguments ); 01295 01296 ErrorCode err; 01297 result = ttmath::ATanh (stack [sindex].value, &err); 01298 01299 if( err != err_ok ) 01300 Error( err ); 01301 } 01302 01303 01304 void ACoth(int sindex, int amount_of_args, ValueType & result) 01305 { 01306 if( amount_of_args != 1 ) 01307 Error( err_improper_amount_of_arguments ); 01308 01309 ErrorCode err; 01310 result = ttmath::ACoth (stack [sindex].value, &err); 01311 01312 if( err != err_ok ) 01313 Error( err ); 01314 } 01315 01316 01317 void BitAnd(int sindex, int amount_of_args, ValueType & result) 01318 { 01319 if( amount_of_args != 2 ) 01320 Error( err_improper_amount_of_arguments ); 01321 01322 uint err; 01323 result = stack [sindex].value; 01324 err = result.BitAnd(stack [sindex+2].value); 01325 01326 switch(err) 01327 { 01328 case 1: 01329 Error( err_overflow ); 01330 break; 01331 case 2: 01332 Error( err_improper_argument ); 01333 break; 01334 } 01335 } 01336 01337 void BitOr(int sindex, int amount_of_args, ValueType & result) 01338 { 01339 if( amount_of_args != 2 ) 01340 Error( err_improper_amount_of_arguments ); 01341 01342 uint err; 01343 result = stack [sindex].value; 01344 err = result.BitOr(stack [sindex+2].value); 01345 01346 switch(err) 01347 { 01348 case 1: 01349 Error( err_overflow ); 01350 break; 01351 case 2: 01352 Error( err_improper_argument ); 01353 break; 01354 } 01355 } 01356 01357 01358 void BitXor(int sindex, int amount_of_args, ValueType & result) 01359 { 01360 if( amount_of_args != 2 ) 01361 Error( err_improper_amount_of_arguments ); 01362 01363 uint err; 01364 result = stack [sindex].value; 01365 err = result.BitXor(stack [sindex+2].value); 01366 01367 switch(err) 01368 { 01369 case 1: 01370 Error( err_overflow ); 01371 break; 01372 case 2: 01373 Error( err_improper_argument ); 01374 break; 01375 } 01376 } 01377 01378 01379 void Sum(int sindex, int amount_of_args, ValueType & result) 01380 { 01381 if( amount_of_args == 0 ) 01382 Error( err_improper_amount_of_arguments ); 01383 01384 result = stack [sindex].value; 01385 01386 for(int i=1 ; i<amount_of_args ; ++i ) 01387 if( result.Add( stack [ sindex + i*2 ].value ) ) 01388 Error( err_overflow ); 01389 } 01390 01391 void Avg(int sindex, int amount_of_args, ValueType & result) 01392 { 01393 if( amount_of_args == 0 ) 01394 Error( err_improper_amount_of_arguments ); 01395 01396 result = stack [sindex].value; 01397 01398 for(int i=1 ; i<amount_of_args ; ++i ) 01399 if( result.Add( stack [ sindex + i*2 ].value ) ) 01400 Error( err_overflow ); 01401 01402 if( result.Div( amount_of_args ) ) 01403 Error( err_overflow ); 01404 } 01405 01406 01407 void Frac(int sindex, int amount_of_args, ValueType & result) 01408 { 01409 if( amount_of_args != 1 ) 01410 Error( err_improper_amount_of_arguments ); 01411 01412 result = stack [sindex].value; 01413 result.RemainFraction(); 01414 } 01415 01416 01417 01418 01419 /*! 01420 we use such a method because 'wvsprintf' is not everywhere defined 01421 */ 01422 void Sprintf(char * buffer, int par) 01423 { 01424 char buf[30]; // char, not wchar_t 01425 int i; 01426 01427 #ifdef _MSC_VER 01428 #pragma warning( disable: 4996 ) 01429 //warning C4996: 'sprintf': This function or variable may be unsafe. 01430 #endif 01431 01432 sprintf(buf, "%d", par); 01433 for(i=0 ; buf[i] != 0 ; ++i) 01434 buffer[i] = buf[i]; 01435 01436 buffer[i] = 0; 01437 01438 #ifdef _MSC_VER 01439 #pragma warning( default: 4996 ) 01440 #endif 01441 } 01442 01443 01444 01445 01446 /*! 01447 this method returns the value from a user-defined function 01448 01449 (look at the description in 'CallFunction(...)') 01450 */ 01451 bool GetValueOfUserDefinedFunction(const std::string & function_name, int amount_of_args, int sindex) 01452 { 01453 if( !puser_functions ) 01454 return false; 01455 01456 const char * string_value; 01457 int param; 01458 01459 if( puser_functions->GetValueAndParam(function_name, &string_value, ¶m) != err_ok ) 01460 return false; 01461 01462 if( param != amount_of_args ) 01463 Error( err_improper_amount_of_arguments ); 01464 01465 01466 FunctionLocalVariables local_variables; 01467 01468 if( amount_of_args > 0 ) 01469 { 01470 char buffer[30]; 01471 01472 // x = x1 01473 buffer[0] = 'x'; 01474 buffer[1] = 0; 01475 local_variables.insert( std::make_pair(buffer, stack [sindex].value) ); 01476 01477 for(int i=0 ; i<amount_of_args ; ++i) 01478 { 01479 buffer[0] = 'x'; 01480 Sprintf(buffer+1, i+1); 01481 local_variables.insert( std::make_pair(buffer, stack [sindex + i*2].value) ); 01482 } 01483 } 01484 01485 stack [sindex-1].value = RecurrenceParsingVariablesOrFunction(false, function_name, string_value, &local_variables); 01486 calculated = true; 01487 01488 return true; 01489 } 01490 01491 01492 /* 01493 we're calling a specific function 01494 01495 function_name - name of the function 01496 amount_of_args - how many arguments there are on our stack 01497 (function must check whether this is a correct value or not) 01498 sindex - index of the first argument on the stack (sindex is greater than zero) 01499 if there aren't any arguments on the stack 'sindex' pointing on 01500 a non existend element (after the first bracket) 01501 01502 result will be stored in 'stack[sindex-1].value' 01503 (we don't have to set the correct type of this element, it'll be set later) 01504 */ 01505 void CallFunction(const std::string & function_name, int amount_of_args, int sindex) 01506 { 01507 if( GetValueOfUserDefinedFunction(function_name, amount_of_args, sindex) ) 01508 return; 01509 01510 typename FunctionsTable::iterator i = functions_table.find( function_name ); 01511 01512 if( i == functions_table.end() ) 01513 Error( err_unknown_function ); 01514 01515 /* 01516 calling the specify function 01517 */ 01518 (this->*(i->second))(sindex, amount_of_args, stack [sindex-1].value); 01519 calculated = true; 01520 } 01521 01522 01523 01524 01525 01526 /*! 01527 inserting a function to the functions' table 01528 01529 function_name - name of the function 01530 pf - pointer to the function (to the wrapper) 01531 */ 01532 void InsertFunctionToTable(const char * function_name, pfunction pf) 01533 { 01534 std::string str; 01535 Misc::AssignString (str, function_name); 01536 01537 functions_table.insert( std::make_pair(str, pf) ); 01538 } 01539 01540 01541 01542 /*! 01543 inserting a function to the variables' table 01544 (this function returns value of variable) 01545 01546 variable_name - name of the function 01547 pf - pointer to the function 01548 */ 01549 void InsertVariableToTable(const char * variable_name, pfunction_var pf) 01550 { 01551 std::string str; 01552 Misc::AssignString (str, variable_name); 01553 01554 variables_table.insert( std::make_pair(str, pf) ); 01555 } 01556 01557 01558 /*! 01559 this method creates the table of functions 01560 */ 01561 void CreateFunctionsTable() 01562 { 01563 InsertFunctionToTable("gamma", &Parser<ValueType>::Gamma ); 01564 InsertFunctionToTable("factorial", &Parser<ValueType>::Factorial ); 01565 InsertFunctionToTable("abs", &Parser<ValueType>::Abs ); 01566 InsertFunctionToTable("sin", &Parser<ValueType>::Sin ); 01567 InsertFunctionToTable("cos", &Parser<ValueType>::Cos ); 01568 InsertFunctionToTable("tan", &Parser<ValueType>::Tan ); 01569 InsertFunctionToTable("tg", &Parser<ValueType>::Tan ); 01570 InsertFunctionToTable("cot", &Parser<ValueType>::Cot ); 01571 InsertFunctionToTable("ctg", &Parser<ValueType>::Cot ); 01572 InsertFunctionToTable("int", &Parser<ValueType>::Int); 01573 InsertFunctionToTable("round", &Parser<ValueType>::Round ); 01574 InsertFunctionToTable("ln", &Parser<ValueType>::Ln ); 01575 InsertFunctionToTable("log", &Parser<ValueType>::Log ); 01576 InsertFunctionToTable("exp", &Parser<ValueType>::Exp ); 01577 InsertFunctionToTable("max", &Parser<ValueType>::Max); 01578 InsertFunctionToTable("min", &Parser<ValueType>::Min); 01579 InsertFunctionToTable("asin", &Parser<ValueType>::ASin ); 01580 InsertFunctionToTable("acos", &Parser<ValueType>::ACos ); 01581 InsertFunctionToTable("atan", &Parser<ValueType>::ATan ); 01582 InsertFunctionToTable("atg", &Parser<ValueType>::ATan ); 01583 InsertFunctionToTable("acot", &Parser<ValueType>::ACot ); 01584 InsertFunctionToTable("actg", &Parser<ValueType>::ACot ); 01585 InsertFunctionToTable("sgn", &Parser<ValueType>::Sgn ); 01586 InsertFunctionToTable("mod", &Parser<ValueType>::Mod ); 01587 InsertFunctionToTable("if", &Parser<ValueType>::If); 01588 InsertFunctionToTable("or", &Parser<ValueType>::Or); 01589 InsertFunctionToTable("and", &Parser<ValueType>::And); 01590 InsertFunctionToTable("not", &Parser<ValueType>::Not); 01591 InsertFunctionToTable("degtorad", &Parser<ValueType>::DegToRad ); 01592 InsertFunctionToTable("radtodeg", &Parser<ValueType>::RadToDeg ); 01593 InsertFunctionToTable("degtodeg", &Parser<ValueType>::DegToDeg ); 01594 InsertFunctionToTable("gradtorad", &Parser<ValueType>::GradToRad ); 01595 InsertFunctionToTable("radtograd", &Parser<ValueType>::RadToGrad ); 01596 InsertFunctionToTable("degtograd", &Parser<ValueType>::DegToGrad ); 01597 InsertFunctionToTable("gradtodeg", &Parser<ValueType>::GradToDeg ); 01598 InsertFunctionToTable("ceil", &Parser<ValueType>::Ceil ); 01599 InsertFunctionToTable("floor", &Parser<ValueType>::Floor ); 01600 InsertFunctionToTable("sqrt", &Parser<ValueType>::Sqrt ); 01601 InsertFunctionToTable("sinh", &Parser<ValueType>::Sinh ); 01602 InsertFunctionToTable("cosh", &Parser<ValueType>::Cosh ); 01603 InsertFunctionToTable("tanh", &Parser<ValueType>::Tanh ); 01604 InsertFunctionToTable("tgh", &Parser<ValueType>::Tanh ); 01605 InsertFunctionToTable("coth", &Parser<ValueType>::Coth ); 01606 InsertFunctionToTable("ctgh", &Parser<ValueType>::Coth ); 01607 InsertFunctionToTable("root", &Parser<ValueType>::Root ); 01608 InsertFunctionToTable("asinh", &Parser<ValueType>::ASinh ); 01609 InsertFunctionToTable("acosh", &Parser<ValueType>::ACosh ); 01610 InsertFunctionToTable("atanh", &Parser<ValueType>::ATanh ); 01611 InsertFunctionToTable("atgh", &Parser<ValueType>::ATanh ); 01612 InsertFunctionToTable("acoth", &Parser<ValueType>::ACoth ); 01613 InsertFunctionToTable("actgh", &Parser<ValueType>::ACoth ); 01614 InsertFunctionToTable("bitand", &Parser<ValueType>::BitAnd); 01615 InsertFunctionToTable("bitor", &Parser<ValueType>::BitOr); 01616 InsertFunctionToTable("bitxor", &Parser<ValueType>::BitXor); 01617 InsertFunctionToTable("band", &Parser<ValueType>::BitAnd); 01618 InsertFunctionToTable("bor", &Parser<ValueType>::BitOr); 01619 InsertFunctionToTable("bxor", &Parser<ValueType>::BitXor); 01620 InsertFunctionToTable("sum", &Parser<ValueType>::Sum); 01621 InsertFunctionToTable("avg", &Parser<ValueType>::Avg); 01622 InsertFunctionToTable("frac", &Parser<ValueType>::Frac); 01623 } 01624 01625 01626 /*! 01627 this method creates the table of variables 01628 */ 01629 void CreateVariablesTable() 01630 { 01631 InsertVariableToTable("pi", &ValueType::SetPi); 01632 InsertVariableToTable("e", &ValueType::SetE); 01633 } 01634 01635 01636 /*! 01637 converting from a big letter to a small one 01638 */ 01639 int ToLowerCase(int c) 01640 { 01641 if( c>='A' && c<='Z' ) 01642 return c - 'A' + 'a'; 01643 01644 return c; 01645 } 01646 01647 01648 /*! 01649 this method read the name of a variable or a function 01650 01651 'result' will be the name of a variable or a function 01652 function return 'false' if this name is the name of a variable 01653 or function return 'true' if this name is the name of a function 01654 01655 what should be returned is tested just by a '(' character that means if there's 01656 a '(' character after a name that function returns 'true' 01657 */ 01658 bool ReadName(std::string & result) 01659 { 01660 int character; 01661 01662 01663 result.erase(); 01664 character = *pstring; 01665 01666 /* 01667 the first letter must be from range 'a' - 'z' or 'A' - 'Z' 01668 */ 01669 if( ! (( character>='a' && character<='z' ) || ( character>='A' && character<='Z' )) ) 01670 Error( err_unknown_character ); 01671 01672 01673 do 01674 { 01675 result += static_cast<char>( character ); 01676 character = * ++pstring; 01677 } 01678 while( (character>='a' && character<='z') || 01679 (character>='A' && character<='Z') || 01680 (character>='0' && character<='9') || 01681 character=='_' ); 01682 01683 01684 SkipWhiteCharacters(); 01685 01686 01687 /* 01688 if there's a character '(' that means this name is a name of a function 01689 */ 01690 if( *pstring == '(' ) 01691 { 01692 ++pstring; 01693 return true; 01694 } 01695 01696 01697 return false; 01698 } 01699 01700 01701 /*! 01702 we're checking whether the first character is '-' or '+' 01703 if it is we'll return 'true' and if it is equally '-' we'll set the 'sign' member of 'result' 01704 */ 01705 bool TestSign(Item & result) 01706 { 01707 SkipWhiteCharacters(); 01708 result.sign = false; 01709 01710 if( *pstring == '-' || *pstring == '+' ) 01711 { 01712 if( *pstring == '-' ) 01713 result.sign = true; 01714 01715 ++pstring; 01716 01717 return true; 01718 } 01719 01720 return false; 01721 } 01722 01723 01724 /*! 01725 we're reading the name of a variable or a function 01726 if is there a function we'll return 'true' 01727 */ 01728 bool ReadVariableOrFunction(Item & result) 01729 { 01730 std::string name; 01731 bool is_it_name_of_function = ReadName(name); 01732 01733 if( is_it_name_of_function ) 01734 { 01735 /* 01736 we've read the name of a function 01737 */ 01738 result.function_name = name; 01739 result.type = Item::first_bracket; 01740 result.function = true; 01741 } 01742 else 01743 { 01744 /* 01745 we've read the name of a variable and we're getting its value now 01746 */ 01747 result.value = GetValueOfVariable ( name ); 01748 } 01749 01750 return is_it_name_of_function; 01751 } 01752 01753 01754 01755 01756 /*! 01757 we're reading a numerical value directly from the string 01758 */ 01759 void ReadValue(Item & result, int reading_base) 01760 { 01761 const char * new_stack_pointer; 01762 bool value_read; 01763 Conv conv; 01764 01765 conv.base = reading_base; 01766 conv.comma = comma; 01767 conv.comma2 = comma2; 01768 conv.group = group; 01769 01770 uint carry = result.value.FromString(pstring, conv, &new_stack_pointer, &value_read); 01771 pstring = new_stack_pointer; 01772 01773 if( carry ) 01774 Error( err_overflow ); 01775 01776 if( !value_read ) 01777 Error( err_unknown_character ); 01778 } 01779 01780 01781 /*! 01782 this method returns true if 'character' is a proper first digit for the value (or a comma -- can be first too) 01783 */ 01784 bool ValueStarts(int character, int base) 01785 { 01786 if( character == comma ) 01787 return true; 01788 01789 if( comma2!=0 && character==comma2 ) 01790 return true; 01791 01792 if( Misc::CharToDigit (character, base) != -1 ) 01793 return true; 01794 01795 return false; 01796 } 01797 01798 01799 /*! 01800 we're reading the item 01801 01802 return values: 01803 0 - all ok, the item is successfully read 01804 1 - the end of the string (the item is not read) 01805 2 - the final bracket ')' 01806 */ 01807 int ReadValueVariableOrFunction(Item & result) 01808 { 01809 bool it_was_sign = false; 01810 int character; 01811 01812 01813 if( TestSign(result) ) 01814 // 'result.sign' was set as well 01815 it_was_sign = true; 01816 01817 SkipWhiteCharacters(); 01818 character = ToLowerCase( *pstring ); 01819 01820 01821 if( character == 0 ) 01822 { 01823 if( it_was_sign ) 01824 // at the end of the string a character like '-' or '+' has left 01825 Error( err_unexpected_end ); 01826 01827 // there's the end of the string here 01828 return 1; 01829 } 01830 else 01831 if( character == '(' ) 01832 { 01833 // we've got a normal bracket (not a function) 01834 result.type = Item::first_bracket; 01835 result.function = false; 01836 ++pstring; 01837 01838 return 0; 01839 } 01840 else 01841 if( character == ')' ) 01842 { 01843 // we've got a final bracket 01844 // (in this place we can find a final bracket only when there are empty brackets 01845 // without any values inside or with a sign '-' or '+' inside) 01846 01847 if( it_was_sign ) 01848 Error( err_unexpected_final_bracket ); 01849 01850 result.type = Item::last_bracket; 01851 01852 // we don't increment 'pstring', this final bracket will be read next by the 01853 // 'ReadOperatorAndCheckFinalBracket(...)' method 01854 01855 return 2; 01856 } 01857 else 01858 if( character == '#' ) 01859 { 01860 ++pstring; 01861 SkipWhiteCharacters(); 01862 01863 // after '#' character we do not allow '-' or '+' (can be white characters) 01864 if( ValueStarts(*pstring, 16) ) 01865 ReadValue( result, 16 ); 01866 else 01867 Error( err_unknown_character ); 01868 } 01869 else 01870 if( character == '&' ) 01871 { 01872 ++pstring; 01873 SkipWhiteCharacters(); 01874 01875 // after '&' character we do not allow '-' or '+' (can be white characters) 01876 if( ValueStarts(*pstring, 2) ) 01877 ReadValue( result, 2 ); 01878 else 01879 Error( err_unknown_character ); 01880 } 01881 else 01882 if( ValueStarts(character, base) ) 01883 { 01884 ReadValue( result, base ); 01885 } 01886 else 01887 if( character>='a' && character<='z' ) 01888 { 01889 if( ReadVariableOrFunction(result) ) 01890 // we've read the name of a function 01891 return 0; 01892 } 01893 else 01894 Error( err_unknown_character ); 01895 01896 01897 01898 /* 01899 we've got a value in the 'result' 01900 this value is from a variable or directly from the string 01901 */ 01902 result.type = Item::numerical_value; 01903 01904 if( result.sign ) 01905 { 01906 result.value.ChangeSign(); 01907 result.sign = false; 01908 } 01909 01910 01911 return 0; 01912 } 01913 01914 01915 void InsertOperatorToTable(const char * name, typename MatOperator::Type type) 01916 { 01917 operators_table.insert( std::make_pair(std::string(name), type) ); 01918 } 01919 01920 01921 /*! 01922 this method creates the table of operators 01923 */ 01924 void CreateMathematicalOperatorsTable() 01925 { 01926 InsertOperatorToTable("||", MatOperator::lor); 01927 InsertOperatorToTable("&&", MatOperator::land); 01928 InsertOperatorToTable("!=", MatOperator::neq); 01929 InsertOperatorToTable("==", MatOperator::eq); 01930 InsertOperatorToTable(">=", MatOperator::get); 01931 InsertOperatorToTable("<=", MatOperator::let); 01932 InsertOperatorToTable(">", MatOperator::gt); 01933 InsertOperatorToTable("<", MatOperator::lt); 01934 InsertOperatorToTable("-", MatOperator::sub); 01935 InsertOperatorToTable("+", MatOperator::add); 01936 InsertOperatorToTable("/", MatOperator::div); 01937 InsertOperatorToTable("*", MatOperator::mul); 01938 InsertOperatorToTable("^", MatOperator::pow); 01939 } 01940 01941 01942 /*! 01943 returns true if 'str2' is the substring of str1 01944 01945 e.g. 01946 true when str1="test" and str2="te" 01947 */ 01948 bool IsSubstring(const std::string & str1, const std::string & str2) 01949 { 01950 if( str2.length() > str1.length() ) 01951 return false; 01952 01953 for(typename std::string::size_type i=0 ; i<str2.length() ; ++i) 01954 if( str1[i] != str2[i] ) 01955 return false; 01956 01957 return true; 01958 } 01959 01960 01961 /*! 01962 this method reads a mathematical (or logical) operator 01963 */ 01964 void ReadMathematicalOperator(Item & result) 01965 { 01966 std::string oper; 01967 typename OperatorsTable::iterator iter_old, iter_new; 01968 01969 iter_old = operators_table.end(); 01970 01971 for( ; true ; ++pstring ) 01972 { 01973 oper += *pstring; 01974 iter_new = operators_table.lower_bound(oper); 01975 01976 if( iter_new == operators_table.end() || !IsSubstring(iter_new->first, oper) ) 01977 { 01978 oper.erase( --oper.end() ); // we've got mininum one element 01979 01980 if( iter_old != operators_table.end() && iter_old->first == oper ) 01981 { 01982 result.type = Item::mat_operator; 01983 result.moperator.SetType( iter_old->second ); 01984 break; 01985 } 01986 01987 Error( err_unknown_operator ); 01988 } 01989 01990 iter_old = iter_new; 01991 } 01992 } 01993 01994 01995 /*! 01996 this method makes a calculation for the percentage operator 01997 e.g. 01998 1000-50% = 1000-(1000*0,5) = 500 01999 */ 02000 void OperatorPercentage() 02001 { 02002 if( stack_index < 3 || 02003 stack [stack_index-1].type != Item::numerical_value || 02004 stack [stack_index-2].type != Item::mat_operator || 02005 stack [stack_index-3].type != Item::numerical_value ) 02006 Error(err_percent_from); 02007 02008 ++pstring; 02009 SkipWhiteCharacters(); 02010 02011 uint c = 0; 02012 c += stack [stack_index-1].value.Div(100); 02013 c += stack [stack_index-1].value.Mul(stack [stack_index-3].value); 02014 02015 if( c ) 02016 Error(err_overflow); 02017 } 02018 02019 02020 /*! 02021 this method reads a mathematic operators 02022 or the final bracket or the semicolon operator 02023 02024 return values: 02025 0 - ok 02026 1 - the string is finished 02027 */ 02028 int ReadOperator(Item & result) 02029 { 02030 SkipWhiteCharacters(); 02031 02032 if( *pstring == '%' ) 02033 OperatorPercentage(); 02034 02035 02036 if( *pstring == 0 ) 02037 return 1; 02038 else 02039 if( *pstring == ')' ) 02040 { 02041 result.type = Item::last_bracket; 02042 ++pstring; 02043 } 02044 else 02045 if( *pstring == ';' || (param_sep!=0 && *pstring==param_sep) ) 02046 { 02047 result.type = Item::semicolon; 02048 ++pstring; 02049 } 02050 else 02051 if( (*pstring>='a' && *pstring<='z') || (*pstring>='A' && *pstring<='Z') ) 02052 { 02053 // short mul (without any operators) 02054 02055 result.type = Item::mat_operator; 02056 result.moperator.SetType( MatOperator::shortmul ); 02057 } 02058 else 02059 ReadMathematicalOperator(result); 02060 02061 return 0; 02062 } 02063 02064 02065 02066 /*! 02067 this method is making the standard mathematic operation like '-' '+' '*' '/' and '^' 02068 02069 the operation is made between 'value1' and 'value2' 02070 the result of this operation is stored in the 'value1' 02071 */ 02072 void MakeStandardMathematicOperation(ValueType & value1, typename MatOperator::Type mat_operator, 02073 const ValueType & value2) 02074 { 02075 uint res; 02076 02077 calculated = true; 02078 02079 switch( mat_operator ) 02080 { 02081 case MatOperator::land: 02082 (!value1.IsZero() && !value2.IsZero()) ? value1.SetOne() : value1.SetZero(); 02083 break; 02084 02085 case MatOperator::lor: 02086 (!value1.IsZero() || !value2.IsZero()) ? value1.SetOne() : value1.SetZero(); 02087 break; 02088 02089 case MatOperator::eq: 02090 (value1 == value2) ? value1.SetOne() : value1.SetZero(); 02091 break; 02092 02093 case MatOperator::neq: 02094 (value1 != value2) ? value1.SetOne() : value1.SetZero(); 02095 break; 02096 02097 case MatOperator::lt: 02098 (value1 < value2) ? value1.SetOne() : value1.SetZero(); 02099 break; 02100 02101 case MatOperator::gt: 02102 (value1 > value2) ? value1.SetOne() : value1.SetZero(); 02103 break; 02104 02105 case MatOperator::let: 02106 (value1 <= value2) ? value1.SetOne() : value1.SetZero(); 02107 break; 02108 02109 case MatOperator::get: 02110 (value1 >= value2) ? value1.SetOne() : value1.SetZero(); 02111 break; 02112 02113 case MatOperator::sub: 02114 if( value1.Sub(value2) ) Error( err_overflow ); 02115 break; 02116 02117 case MatOperator::add: 02118 if( value1.Add(value2) ) Error( err_overflow ); 02119 break; 02120 02121 case MatOperator::mul: 02122 case MatOperator::shortmul: 02123 if( value1.Mul(value2) ) Error( err_overflow ); 02124 break; 02125 02126 case MatOperator::div: 02127 if( value2.IsZero() ) Error( err_division_by_zero ); 02128 if( value1.Div(value2) ) Error( err_overflow ); 02129 break; 02130 02131 case MatOperator::pow: 02132 res = value1.Pow( value2 ); 02133 02134 if( res == 1 ) Error( err_overflow ); 02135 else 02136 if( res == 2 ) Error( err_improper_argument ); 02137 02138 break; 02139 02140 default: 02141 /* 02142 on the stack left an unknown operator but we had to recognize its before 02143 that means there's an error in our algorithm 02144 */ 02145 Error( err_internal_error ); 02146 } 02147 } 02148 02149 02150 02151 02152 /*! 02153 this method is trying to roll the stack up with the operator's priority 02154 02155 for example if there are: 02156 "1 - 2 +" 02157 we can subtract "1-2" and the result store on the place where is '1' and copy the last 02158 operator '+', that means there'll be '-1+' on our stack 02159 02160 but if there are: 02161 "1 - 2 *" 02162 we can't roll the stack up because the operator '*' has greater priority than '-' 02163 */ 02164 void TryRollingUpStackWithOperatorPriority() 02165 { 02166 while( stack_index>=4 && 02167 stack [stack_index-4].type == Item::numerical_value && 02168 stack [stack_index-3].type == Item::mat_operator && 02169 stack [stack_index-2].type == Item::numerical_value && 02170 stack [stack_index-1].type == Item::mat_operator && 02171 ( 02172 ( 02173 // the first operator has greater priority 02174 stack [stack_index-3].moperator.GetPriority() > stack [stack_index-1].moperator.GetPriority() 02175 ) || 02176 ( 02177 // or both operators have the same priority and the first operator is not right associative 02178 stack [stack_index-3].moperator.GetPriority() == stack [stack_index-1].moperator.GetPriority() && 02179 stack [stack_index-3].moperator.GetAssoc() == MatOperator::non_right 02180 ) 02181 ) 02182 ) 02183 { 02184 MakeStandardMathematicOperation(stack [stack_index-4].value, 02185 stack [stack_index-3].moperator.GetType(), 02186 stack [stack_index-2].value); 02187 02188 02189 /* 02190 copying the last operator and setting the stack pointer to the correct value 02191 */ 02192 stack [stack_index-3] = stack[stack_index-1]; 02193 stack_index -= 2; 02194 } 02195 } 02196 02197 02198 /*! 02199 this method is trying to roll the stack up without testing any operators 02200 02201 for example if there are: 02202 "1 - 2" 02203 there'll be "-1" on our stack 02204 */ 02205 void TryRollingUpStack() 02206 { 02207 while( stack_index >= 3 && 02208 stack [stack_index-3].type == Item::numerical_value && 02209 stack [stack_index-2].type == Item::mat_operator && 02210 stack [stack_index-1].type == Item::numerical_value ) 02211 { 02212 MakeStandardMathematicOperation( stack [stack_index-3].value, 02213 stack [stack_index-2].moperator.GetType(), 02214 stack [stack_index-1].value ); 02215 02216 stack_index -= 2; 02217 } 02218 } 02219 02220 02221 /*! 02222 this method is reading a value or a variable or a function 02223 (the normal first bracket as well) and push it into the stack 02224 */ 02225 int ReadValueVariableOrFunctionAndPushItIntoStack(Item & temp) 02226 { 02227 int code = ReadValueVariableOrFunction( temp ); 02228 02229 if( code == 0 ) 02230 { 02231 if( stack_index < stack .size() ) 02232 stack [stack_index] = temp; 02233 else 02234 stack .push_back( temp ); 02235 02236 ++stack_index; 02237 } 02238 02239 if( code == 2 ) 02240 // there was a final bracket, we didn't push it into the stack 02241 // (it'll be read by the 'ReadOperatorAndCheckFinalBracket' method next) 02242 code = 0; 02243 02244 02245 return code; 02246 } 02247 02248 02249 02250 /*! 02251 this method calculate how many parameters there are on the stack 02252 and the index of the first parameter 02253 02254 if there aren't any parameters on the stack this method returns 02255 'size' equals zero and 'index' pointing after the first bracket 02256 (on non-existend element) 02257 */ 02258 void HowManyParameters(int & size, int & index) 02259 { 02260 size = 0; 02261 index = stack_index; 02262 02263 if( index == 0 ) 02264 // we haven't put a first bracket on the stack 02265 Error( err_unexpected_final_bracket ); 02266 02267 02268 if( stack [index-1].type == Item::first_bracket ) 02269 // empty brackets 02270 return; 02271 02272 for( --index ; index>=1 ; index-=2 ) 02273 { 02274 if( stack [index].type != Item::numerical_value ) 02275 { 02276 /* 02277 this element must be 'numerical_value', if not that means 02278 there's an error in our algorithm 02279 */ 02280 Error( err_internal_error ); 02281 } 02282 02283 ++size; 02284 02285 if( stack [index-1].type != Item::semicolon ) 02286 break; 02287 } 02288 02289 if( index<1 || stack [index-1].type != Item::first_bracket ) 02290 { 02291 /* 02292 we haven't put a first bracket on the stack 02293 */ 02294 Error( err_unexpected_final_bracket ); 02295 } 02296 } 02297 02298 02299 /*! 02300 this method is being called when the final bracket ')' is being found 02301 02302 this method's rolling the stack up, counting how many parameters there are 02303 on the stack and if there was a function it's calling the function 02304 */ 02305 void RollingUpFinalBracket() 02306 { 02307 int amount_of_parameters; 02308 int index; 02309 02310 02311 if( stack_index<1 || 02312 (stack [stack_index-1].type != Item::numerical_value && 02313 stack [stack_index-1].type != Item::first_bracket) 02314 ) 02315 Error( err_unexpected_final_bracket ); 02316 02317 02318 TryRollingUpStack(); 02319 HowManyParameters(amount_of_parameters, index); 02320 02321 // 'index' will be greater than zero 02322 // 'amount_of_parameters' can be zero 02323 02324 02325 if( amount_of_parameters==0 && !stack [index-1].function ) 02326 Error( err_unexpected_final_bracket ); 02327 02328 02329 bool was_sign = stack [index-1].sign; 02330 02331 02332 if( stack [index-1].function ) 02333 { 02334 // the result of a function will be on 'stack[index-1]' 02335 // and then at the end we'll set the correct type (numerical value) of this element 02336 CallFunction(stack [index-1].function_name, amount_of_parameters, index); 02337 } 02338 else 02339 { 02340 /* 02341 there was a normal bracket (not a funcion) 02342 */ 02343 if( amount_of_parameters != 1 ) 02344 Error( err_unexpected_semicolon_operator ); 02345 02346 02347 /* 02348 in the place where is the bracket we put the result 02349 */ 02350 stack [index-1] = stack [index]; 02351 } 02352 02353 02354 /* 02355 if there was a '-' character before the first bracket 02356 we change the sign of the expression 02357 */ 02358 stack [index-1].sign = false; 02359 02360 if( was_sign ) 02361 stack [index-1].value.ChangeSign(); 02362 02363 stack [index-1].type = Item::numerical_value; 02364 02365 02366 /* 02367 the pointer of the stack will be pointing on the next (non-existing now) element 02368 */ 02369 stack_index = index; 02370 } 02371 02372 02373 /*! 02374 this method is putting the operator on the stack 02375 */ 02376 02377 void PushOperatorIntoStack(Item & temp) 02378 { 02379 if( stack_index < stack .size() ) 02380 stack [stack_index] = temp; 02381 else 02382 stack .push_back( temp ); 02383 02384 ++stack_index; 02385 } 02386 02387 02388 02389 /*! 02390 this method is reading a operator and if it's a final bracket 02391 it's calling RollingUpFinalBracket() and reading a operator again 02392 */ 02393 int ReadOperatorAndCheckFinalBracket(Item & temp) 02394 { 02395 do 02396 { 02397 if( ReadOperator(temp) == 1 ) 02398 { 02399 /* 02400 the string is finished 02401 */ 02402 return 1; 02403 } 02404 02405 if( temp.type == Item::last_bracket ) 02406 RollingUpFinalBracket(); 02407 02408 } 02409 while( temp.type == Item::last_bracket ); 02410 02411 return 0; 02412 } 02413 02414 02415 /*! 02416 we check wheter there are only numerical value's or 'semicolon' operators on the stack 02417 */ 02418 void CheckIntegrityOfStack() 02419 { 02420 for(unsigned int i=0 ; i<stack_index; ++i) 02421 { 02422 if( stack [i].type != Item::numerical_value && 02423 stack [i].type != Item::semicolon) 02424 { 02425 /* 02426 on the stack we must only have 'numerical_value' or 'semicolon' operator 02427 if there is something another that means 02428 we probably didn't close any of the 'first' bracket 02429 */ 02430 Error( err_stack_not_clear ); 02431 } 02432 } 02433 } 02434 02435 02436 02437 /*! 02438 the main loop of parsing 02439 */ 02440 void Parse() 02441 { 02442 Item item; 02443 int result_code; 02444 02445 02446 while( true ) 02447 { 02448 if( pstop_calculating && pstop_calculating->WasStopSignal() ) 02449 Error( err_interrupt ); 02450 02451 result_code = ReadValueVariableOrFunctionAndPushItIntoStack( item ); 02452 02453 if( result_code == 0 ) 02454 { 02455 if( item.type == Item::first_bracket ) 02456 continue; 02457 02458 result_code = ReadOperatorAndCheckFinalBracket( item ); 02459 } 02460 02461 02462 if( result_code==1 || item.type==Item::semicolon ) 02463 { 02464 /* 02465 the string is finished or the 'semicolon' operator has appeared 02466 */ 02467 02468 if( stack_index == 0 ) 02469 Error( err_nothing_has_read ); 02470 02471 TryRollingUpStack(); 02472 02473 if( result_code == 1 ) 02474 { 02475 CheckIntegrityOfStack(); 02476 02477 return; 02478 } 02479 } 02480 02481 02482 PushOperatorIntoStack( item ); 02483 TryRollingUpStackWithOperatorPriority(); 02484 } 02485 } 02486 02487 /*! 02488 this method is called at the end of the parsing process 02489 02490 on our stack we can have another value than 'numerical_values' for example 02491 when someone use the operator ';' in the global scope or there was an error during 02492 parsing and the parser hasn't finished its job 02493 02494 if there was an error the stack is cleaned up now 02495 otherwise we resize stack and leave on it only 'numerical_value' items 02496 */ 02497 void NormalizeStack() 02498 { 02499 if( error!=err_ok || stack_index==0 ) 02500 { 02501 stack .clear(); 02502 return; 02503 } 02504 02505 02506 /* 02507 'stack_index' tell us how many elements there are on the stack, 02508 we must resize the stack now because 'stack_index' is using only for parsing 02509 and stack has more (or equal) elements than value of 'stack_index' 02510 */ 02511 stack .resize( stack_index ); 02512 02513 for(uint i=stack_index-1 ; i!=uint (-1) ; --i) 02514 { 02515 if( stack [i].type != Item::numerical_value ) 02516 stack .erase( stack .begin() + i ); 02517 } 02518 } 02519 02520 02521 public: 02522 02523 02524 /*! 02525 the default constructor 02526 */ 02527 Parser (): default_stack_size(100) 02528 { 02529 pstop_calculating = 0; 02530 puser_variables = 0; 02531 puser_functions = 0; 02532 pfunction_local_variables = 0; 02533 base = 10; 02534 deg_rad_grad = 1; 02535 error = err_ok; 02536 group = 0; 02537 comma = '.'; 02538 comma2 = ','; 02539 param_sep = 0; 02540 02541 CreateFunctionsTable(); 02542 CreateVariablesTable(); 02543 CreateMathematicalOperatorsTable(); 02544 } 02545 02546 02547 /*! 02548 the assignment operator 02549 */ 02550 Parser<ValueType> & operator= (const Parser<ValueType> & p) 02551 { 02552 pstop_calculating = p.pstop_calculating; 02553 puser_variables = p.puser_variables; 02554 puser_functions = p.puser_functions; 02555 pfunction_local_variables = 0; 02556 base = p.base; 02557 deg_rad_grad = p.deg_rad_grad; 02558 error = p.error; 02559 group = p.group; 02560 comma = p.comma; 02561 comma2 = p.comma2; 02562 param_sep = p.param_sep; 02563 02564 /* 02565 we don't have to call 'CreateFunctionsTable()' etc. 02566 we can only copy these tables 02567 */ 02568 functions_table = p.functions_table; 02569 variables_table = p.variables_table; 02570 operators_table = p.operators_table; 02571 02572 visited_variables = p.visited_variables; 02573 visited_functions = p.visited_functions; 02574 02575 return *this; 02576 } 02577 02578 02579 /*! 02580 the copying constructor 02581 */ 02582 Parser (const Parser<ValueType> & p): default_stack_size(p.default_stack_size) 02583 { 02584 operator= (p); 02585 } 02586 02587 02588 /*! 02589 the new base of mathematic system 02590 default is 10 02591 */ 02592 void SetBase (int b) 02593 { 02594 if( b>=2 && b<=16 ) 02595 base = b; 02596 } 02597 02598 02599 /*! 02600 the unit of angles used in: sin,cos,tan,cot,asin,acos,atan,acot 02601 0 - deg 02602 1 - rad (default) 02603 2 - grad 02604 */ 02605 void SetDegRadGrad (int angle) 02606 { 02607 if( angle >= 0 || angle <= 2 ) 02608 deg_rad_grad = angle; 02609 } 02610 02611 /*! 02612 this method sets a pointer to the object which tell us whether we should stop 02613 calculations 02614 */ 02615 void SetStopObject (const volatile StopCalculating * ps) 02616 { 02617 pstop_calculating = ps; 02618 } 02619 02620 02621 /*! 02622 this method sets the new table of user-defined variables 02623 if you don't want any other variables just put zero value into the 'puser_variables' variable 02624 02625 (you can have only one table at the same time) 02626 */ 02627 void SetVariables (const Objects * pv) 02628 { 02629 puser_variables = pv; 02630 } 02631 02632 02633 /*! 02634 this method sets the new table of user-defined functions 02635 if you don't want any other functions just put zero value into the 'puser_functions' variable 02636 02637 (you can have only one table at the same time) 02638 */ 02639 void SetFunctions (const Objects * pf) 02640 { 02641 puser_functions = pf; 02642 } 02643 02644 02645 /*! 02646 setting the group character 02647 default zero (not used) 02648 */ 02649 void SetGroup (int g) 02650 { 02651 group = g; 02652 } 02653 02654 02655 /*! 02656 setting the main comma operator and the additional comma operator 02657 the additional operator can be zero (which means it is not used) 02658 default are: '.' and ',' 02659 */ 02660 void SetComma (int c, int c2 = 0) 02661 { 02662 comma = c; 02663 comma2 = c2; 02664 } 02665 02666 02667 /*! 02668 setting an additional character which is used as a parameters separator 02669 the main parameters separator is a semicolon (is used always) 02670 02671 this character is used also as a global separator 02672 */ 02673 void SetParamSep (int s) 02674 { 02675 param_sep = s; 02676 } 02677 02678 02679 /*! 02680 the main method using for parsing string 02681 */ 02682 ErrorCode Parse(const char * str) 02683 { 02684 stack_index = 0; 02685 pstring = str; 02686 error = err_ok; 02687 calculated = false; 02688 02689 stack .resize( default_stack_size ); 02690 02691 try 02692 { 02693 Parse(); 02694 } 02695 catch(ErrorCode c) 02696 { 02697 error = c; 02698 calculated = false; 02699 } 02700 02701 NormalizeStack(); 02702 02703 return error; 02704 } 02705 02706 02707 /*! 02708 the main method using for parsing string 02709 */ 02710 ErrorCode Parse(const std::string & str) 02711 { 02712 return Parse(str.c_str()); 02713 } 02714 02715 02716 #ifndef TTMATH_DONT_USE_WCHAR 02717 02718 /*! 02719 the main method using for parsing string 02720 */ 02721 ErrorCode Parse(const wchar_t * str) 02722 { 02723 Misc::AssignString (wide_to_ansi, str); 02724 02725 return Parse(wide_to_ansi.c_str()); 02726 02727 // !! wide_to_ansi clearing can be added here 02728 } 02729 02730 02731 /*! 02732 the main method using for parsing string 02733 */ 02734 ErrorCode Parse(const std::wstring & str) 02735 { 02736 return Parse(str.c_str()); 02737 } 02738 02739 #endif 02740 02741 02742 /*! 02743 this method returns true is something was calculated 02744 (at least one mathematical operator was used or a function or variable) 02745 e.g. true if the string to Parse() looked like this: 02746 "1+1" 02747 "2*3" 02748 "sin(5)" 02749 02750 if the string was e.g. "678" the result is false 02751 */ 02752 bool Calculated () 02753 { 02754 return calculated; 02755 } 02756 02757 02758 /*! 02759 initializing coefficients used when calculating the gamma (or factorial) function 02760 this speed up the next calculations 02761 you don't have to call this method explicitly 02762 these coefficients will be calculated when needed 02763 */ 02764 void InitCGamma () 02765 { 02766 cgamma.InitAll(); 02767 } 02768 02769 02770 }; 02771 02772 02773 02774 } // namespace 02775 02776 02777 #endif 02778
Generated on Tue Jul 12 2022 14:03:18 by 1.7.2