⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fparser.txt

📁 一个不错的计算符编译器
💻 TXT
📖 第 1 页 / 共 2 页
字号:
  Function parser for C++  v2.7 by Warp.
  =====================================

  Optimization code contributed by Bisqwit (http://iki.fi/bisqwit/)


  The usage license of this library is located at the end of this text file.



  What's new in v2.7
  ------------------
  - Changed precedence rules for unary minus and the power operator (^) to
    make it closer in functionality to the power "operator" in mathematics
    (ie. superscript):
    * Consecutive power operators at the same precedence level are
      evaluated from right to left. That is, for example "2^3^4" is
      now evaluated as if it had been written as "2^(3^4)" (and not
      as "(2^3)^4" like in previous versions).
    * The unary minus in the base of the power has now a lower precedence
      than the power operator. That is, "-2^3" will be evaluated as if
      written as "-(2^3)", ie. the result is "-8" (and not "8" like in
      previous versions). The unary minus in the exponent is still
      evaluated first because of the right-left precedence change above
      (that is, "-2^-3" is evaluated as "-(2^(-3))").
  - Fixed a bug in the copy-on-write engine.



=============================================================================
  - Preface
=============================================================================

  Often people need to ask some mathematical expression from the user and
then evaluate values for that expression. The simplest example is a program
which draws the graphic of a user-defined function on screen.

  This library adds C-style function string parsing to the program. This
means that you can evaluate the string "sqrt(1-x^2+y^2)" with given values
of 'x' and 'y'.

  The library is intended to be very fast. It byte-compiles the function
string at parse time and interpretes this byte-code at evaluation time.
The evaluation is straightforward and no recursions are done (uses stack
arithmetic).
  Empirical tests show that it indeed is very fast (specially compared to
libraries which evaluate functions by just interpreting the raw function
string).

  The library is made in ISO C++ and requires a standard-conforming C++
compiler.


=============================================================================
  - Usage
=============================================================================

  To use the FunctionParser class, you have to include "fparser.hh". When
compiling, you have to compile fparser.cc and link it to the main program.
You can also make a library from the fparser.cc (see the help on your
compiler to see how this is done).


  * Conditional compiling:
    ---------------------

    There is a set of precompiler options at the beginning of fparser.cc
  which can be used for setting certain features on or off. These lines
  can be commented or uncommented depending on the desired behaviour:

  NO_ASINH : (Default on)
       By default the library does not support the asinh(), acosh()
       and atanh() functions because they are not part of the ISO C++
       standard. If your compiler supports them and you want the
       parser to support them as well, comment this line.

  DISABLE_EVAL : (Default off)
       The eval() function can be dangerous because it can cause an
       infinite recursion in the parser when not used properly (which
       causes the function stack created by the compiler to overflow).
       If this possibility should be prevented then the eval() function
       can be disabled completely by uncommenting this line.

  SUPPORT_OPTIMIZER : (Default on)
       If you are not going to use the Optimize() method, you can comment
       this line out to speed-up the compilation of fparser.cc a bit, as
       well as making the binary a bit smaller. (Optimize() can still be
       called, but it will not do anything.)


  * Copying and assignment:
    ----------------------

    The class implements a safe copy constructor and assignment operator.

    It uses the copy-on-write technique for efficiency. This means that
  when copying or assigning a FunctionParser instance, the internal data
  (which in some cases can be quite lengthy) is not immediately copied
  but only when the contents of the copy (or the original) are changed.
    This means that copying/assigning is a very fast operation, and if
  the copies are never modified then actual data copying never happens
  either.

    The Eval() and EvalError() methods of the copy can be called without
  the internal data being copied.
    Calling Parse(), Optimize() or the user-defined constant/function adding
  methods will cause a deep-copy.

    (C++ basics: The copy constructor is called when a new FunctionParser
     instance is initialized with another, ie. like:

       FunctionParser fp2 = fp1; // or: FunctionParser fp2(fp1);

     or when a function takes a FunctionParser instance as parameter, eg:

       void foo(FunctionParser p) // takes an instance of FunctionParser
       { ... }

     The assignment operator is called when a FunctionParser instance is
     assigned to another, like "fp2 = fp1;".)


  * Short descriptions of FunctionParser methods:
    --------------------------------------------

int Parse(const std::string& Function, const std::string& Vars,
          bool useDegrees = false);

    Parses the given function and compiles it to internal format.
    Return value is -1 if successful, else the index value to the location
    of the error.


const char* ErrorMsg(void) const;

    Returns an error message corresponding to the error in Parse(), or 0 if
    no such error occurred.


ParseErrorType GetParseErrorType() const;

    Returns the type of parsing error which occurred. Possible return types
    are described in the long description.


double Eval(const double* Vars);

    Evaluates the function given to Parse().


int EvalError(void) const;

    Returns 0 if no error happened in the previous call to Eval(), else an
    error code >0.


void Optimize();

    Tries to optimize the bytecode for faster evaluation.


bool AddConstant(const std::string& name, double value);

    Add a constant to the parser. Returns false if the name of the constant
    is invalid, else true.


bool AddFunction(const std::string& name,
                 double (*functionPtr)(const double*),
                 unsigned paramsAmount);

    Add a user-defined function to the parser (as a function pointer).
    Returns false if the name of the function is invalid, else true.


bool AddFunction(const std::string& name, FunctionParser&);

    Add a user-defined function to the parser (as a FunctionParser instance).
    Returns false if the name of the function is invalid, else true.



  * Long descriptions of FunctionParser methods:
    -------------------------------------------

---------------------------------------------------------------------------
int Parse(const std::string& Function, const std::string& Vars,
          bool useDegrees = false);
---------------------------------------------------------------------------

      Parses the given function (and compiles it to internal format).
    Destroys previous function. Following calls to Eval() will evaluate
    the given function.
      The strings given as parameters are not needed anymore after parsing.

    Parameters:
      Function  : String containing the function to parse.
      Vars      : String containing the variable names, separated by commas.
                  Eg. "x,y", "VarX,VarY,VarZ,n" or "x1,x2,x3,x4,__VAR__".
      useDegrees: (Optional.) Whether to use degrees or radians in
                  trigonometric functions. (Default: radians)

    Variables can have any size and they are case sensitive (ie. "var",
    "VAR" and "Var" are *different* variable names). Letters, digits and
    underscores can be used in variable names, but the name of a variable
    can't begin with a digit. Each variable name can appear only once in
    the string. Function names are not legal variable names.

    Using longer variable names causes no overhead whatsoever to the Eval()
    method, so it's completely safe to use variable names of any size.

    The third, optional parameter specifies whether angles should be
    interpreted as radians or degrees in trigonometrical functions.
    If not specified, the default value is radians.

    Return values:
    -On success the function returns -1.
    -On error the function returns an index to where the error was found
     (0 is the first character, 1 the second, etc). If the error was not
     a parsing error returns an index to the end of the string + 1.

    Example: parser.Parse("3*x+y", "x,y");


---------------------------------------------------------------------------
const char* ErrorMsg(void) const;
---------------------------------------------------------------------------

    Returns a pointer to an error message string corresponding to the error
    caused by Parse() (you can use this to print the proper error message to
    the user). If no such error has occurred, returns 0.


---------------------------------------------------------------------------
ParseErrorType GetParseErrorType() const;
---------------------------------------------------------------------------

    Returns the type of parse error which occurred.

    This method can be used to get the error type if ErrorMsg() is not
    enough for printing the error message. In other words, this can be
    used for printing customized error messages (eg. in another language).
    If the default error messages suffice, then this method doesn't need
    to be called.

    FunctionParser::ParseErrorType is an enumerated type inside the class
    (ie. its values are accessed like "FunctionParser::SYNTAX_ERROR").

    The possible values for FunctionParser::ParseErrorType are listed below,
    along with their equivalent error message returned by the ErrorMsg()
    method:

FP_NO_ERROR        : If no error occurred in the previous call to Parse().
SYNTAX_ERROR       : "Syntax error"
MISM_PARENTH       : "Mismatched parenthesis"
MISSING_PARENTH    : "Missing ')'"
EMPTY_PARENTH      : "Empty parentheses"
EXPECT_OPERATOR    : "Syntax error: Operator expected"
OUT_OF_MEMORY      : "Not enough memory"
UNEXPECTED_ERROR   : "An unexpected error ocurred. Please make a full bug "
                     "report to warp@iki.fi"
INVALID_VARS       : "Syntax error in parameter 'Vars' given to "
                     "FunctionParser::Parse()"
ILL_PARAMS_AMOUNT  : "Illegal number of parameters to function"
PREMATURE_EOS      : "Syntax error: Premature end of string"
EXPECT_PARENTH_FUNC: "Syntax error: Expecting ( after function"


---------------------------------------------------------------------------
double Eval(const double* Vars);
---------------------------------------------------------------------------

    Evaluates the function given to Parse().
    The array given as parameter must contain the same amount of values as
    the amount of variables given to Parse(). Each value corresponds to each
    variable, in the same order.

    Return values:
    -On success returns the evaluated value of the function given to
     Parse().
    -On error (such as division by 0) the return value is unspecified,
     probably 0.

    Example:

      double Vars[] = {1, -2.5};
      double result = parser.Eval(Vars);


---------------------------------------------------------------------------
int EvalError(void) const;
---------------------------------------------------------------------------

    Used to test if the call to Eval() succeeded.

    Return values:
      If there was no error in the previous call to Eval(), returns 0,
      else returns a positive value as follows:
        1: division by zero
        2: sqrt error (sqrt of a negative value)
        3: log error (logarithm of a negative value)
        4: trigonometric error (asin or acos of illegal value)


---------------------------------------------------------------------------
void Optimize();
---------------------------------------------------------------------------

    This method can be called after calling the Parse() method. It will try
    to simplify the internal bytecode so that it will evaluate faster (it
    tries to reduce the amount of opcodes in the bytecode).

      For example, the bytecode for the function "5+x*y-25*4/8" will be
    reduced to a bytecode equivalent to the function "x*y-7.5" (the original
    11 opcodes will be reduced to 5). Besides calculating constant expressions
    (like in the example), it also performs other types of simplifications
    with variable and function expressions.

      This method is quite slow and the decision of whether to use it or
    not should depend on the type of application. If a function is parsed
    once and evaluated millions of times, then calling Optimize() may speed-up
    noticeably. However, if there are tons of functions to parse and each one
    is evaluated once or just a few times, then calling Optimize() will only
    slow down the program.
      Also, if the original function is expected to be optimal, then calling
    Optimize() would be useless.

      Note: Currently this method does not make any checks (like Eval() does)
    and thus things like "1/0" will cause undefined behaviour. (On the other
    hand, if such expression is given to the parser, Eval() will always give
    an error code, no matter what the parameters.) If caching this type of
    errors is important, a work-around is to call Eval() once before calling
    Optimize() and checking EvalError().

      If the destination application is not going to use this method,
    the compiler constant SUPPORT_OPTIMIZER can be undefined at the beginning

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -