Library for big numbers from http://www.ttmath.org/

Dependents:   PIDHeater82 Conceptcontroller_v_1_0 AlarmClockApp COG4050_adxl355_tilt ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ttmathparser.h Source File

ttmathparser.h

Go to the documentation of this file.
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, &param) != 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