ajout de la lib muparser version 2.2.5
This commit is contained in:
parent
b5dbc42a67
commit
d9faf87e86
25 changed files with 10733 additions and 0 deletions
557
muparser-2.2.5_GR/Changes.txt
Executable file
557
muparser-2.2.5_GR/Changes.txt
Executable file
|
@ -0,0 +1,557 @@
|
|||
#######################################################################
|
||||
# #
|
||||
# #
|
||||
# __________ #
|
||||
# _____ __ __\______ \_____ _______ ______ ____ _______ #
|
||||
# / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ #
|
||||
# | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ #
|
||||
# |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| #
|
||||
# \/ \/ \/ \/ #
|
||||
# Fast math parser Library #
|
||||
# #
|
||||
# Copyright (C) 2015 Ingo Berg #
|
||||
# #
|
||||
# Web: muparser.beltoforion.de #
|
||||
# e-mail: muparser@beltoforion.de #
|
||||
# #
|
||||
# #
|
||||
#######################################################################
|
||||
|
||||
|
||||
History:
|
||||
--------
|
||||
|
||||
Rev 2.2.5: 27.04.2015
|
||||
---------------------
|
||||
Changes:
|
||||
* example2 extended to work with UNICODE character set
|
||||
* Applied patch from Issue 9
|
||||
|
||||
Bugfixes:
|
||||
* muChar_t in muParserDLL.h was not set properly when UNICODE was used
|
||||
* muparser.dll did not build on UNICODE systems
|
||||
|
||||
Rev 2.2.4: 02.10.2014
|
||||
---------------------
|
||||
Changes:
|
||||
* explicit positive sign allowed
|
||||
|
||||
Bugfixes:
|
||||
* Fix for Issue 6 (https://code.google.com/p/muparser/issues/detail?id=6)
|
||||
* String constants did not work properly. Using more than a single one
|
||||
was impossible.
|
||||
* Project Files for VS2008 and VS2010 removed from the repository
|
||||
* Fix for Issue 4 (https://code.google.com/p/muparser/issues/detail?id=4)
|
||||
* Fix for VS2013 64 bit build option
|
||||
* return type of ParserError::GetPos changed to int
|
||||
* OpenMP support enabled in the VS2013 project files and precompiled windows DLL's
|
||||
* Bulkmode did not evaluate properly if "=" and "," operator was used in the expression
|
||||
|
||||
Rev 2.2.3: 22.12.2012
|
||||
---------------------
|
||||
|
||||
Removed features:
|
||||
* build files for msvc2005, borland and watcom compiler were removed
|
||||
|
||||
Bugfixes:
|
||||
* Bugfix for Intel Compilers added: The power operator did not work properly
|
||||
with Intel C++ composer XE 2011.
|
||||
(see https://sourceforge.net/projects/muparser/forums/forum/462843/topic/5117983/index/page/1)
|
||||
* Issue 3509860: Callbacks of functions with string parameters called twice
|
||||
(see http://sourceforge.net/tracker/?func=detail&aid=3509860&group_id=137191&atid=737979)
|
||||
* Issue 3570423: example1 shows slot number in hexadecimal
|
||||
(see https://sourceforge.net/tracker/?func=detail&aid=3570423&group_id=137191&atid=737979)
|
||||
* Fixes for compiling with the "MUP_MATH_EXCEPTIONS" macro definition:
|
||||
- division by zero in constant expressions was reported with the code "ec_GENERIC"
|
||||
instead of "ecDIV_BY_ZERO"
|
||||
- added throwing of "ecDOMAIN_ERROR" to sqrt and log functions
|
||||
|
||||
|
||||
Rev 2.2.2: 18.02.2012
|
||||
---------------------
|
||||
Bugfixes:
|
||||
* Optimizer did'nt work properly for division:
|
||||
(see https://sourceforge.net/projects/muparser/forums/forum/462843/topic/5037825)
|
||||
|
||||
Rev 2.2.1: 22.01.2012
|
||||
---------------------
|
||||
Bugfixes:
|
||||
* Optimizer bug in 64 bit systems fixed
|
||||
(see https://sourceforge.net/projects/muparser/forums/forum/462843/topic/4977977/index/page/1)
|
||||
|
||||
Rev 2.2.0: 22.01.2012
|
||||
---------------------
|
||||
Improvements:
|
||||
* Optimizer rewritten and improved. In general: more optimizations are
|
||||
now applied to the bytecode. The downside is that callback Functions
|
||||
can no longer be flagged as non-optimizable. (The flag is still present
|
||||
but ignored) This is necessary since the optimizer had to call the
|
||||
functions in order to precalculate the result (see Bugfixes). These calls
|
||||
posed a problems for callback functions with side effects and if-then-else
|
||||
clauses in general since they undermined the shortcut evaluation prinziple.
|
||||
|
||||
Bugfixes:
|
||||
* Infix operators where not properly detected in the presence of a constant
|
||||
name starting with an underscore which is a valid character for infix
|
||||
operators too (i.e. "-_pi").
|
||||
* Issue 3463353: Callback functions are called twice during the first call to eval.
|
||||
* Issue 3447007: GetUsedVar unnecessaryly executes callback functions.
|
||||
|
||||
|
||||
Rev 2.1.0: 19.11.2011
|
||||
---------------------
|
||||
New feature:
|
||||
* Function atan2 added
|
||||
|
||||
Bugfixes:
|
||||
* Issue 3438380: Changed behaviour of tellg with GCC >4.6 led to failures
|
||||
in value detection callbacks.
|
||||
* Issue 3438715: only "double" is a valid MUP_BASETYPE
|
||||
MUP_BASETYPE can now be any of:
|
||||
float,
|
||||
double,
|
||||
long double,
|
||||
short,
|
||||
unsigned short,
|
||||
unsigned int,
|
||||
long,
|
||||
unsigned long.
|
||||
Previousely only floating point types were allowed.
|
||||
Using "int" is still not allowed!
|
||||
* Compiler issues with GCC 4.6 fixed
|
||||
* Custom value recognition callbacks added with AddValIdent had lower
|
||||
priority than built in functions. This was causing problems with
|
||||
hex value recognition since detection of non hex values had priority
|
||||
over the detection of hex values. The "0" in the hex prefix "0x" would
|
||||
be read as a separate non-hex number leaving the rest of the expression
|
||||
unparseable.
|
||||
|
||||
Rev 2.0.0: 04.09.2011
|
||||
---------------------
|
||||
This release introduces a new version numbering scheme in order to make
|
||||
future changes in the ABI apparent to users of the library. The number is
|
||||
now based on the SONAME property as used by GNU/Linux.
|
||||
|
||||
Changes:
|
||||
* Beginning with this version all version numbers will be SONAME compliant
|
||||
* Project files for MSVC2010 added
|
||||
* Project files for MSVC2003 removed
|
||||
* Bytecode parsing engine cleaned up and rewritten
|
||||
* Retrieving all results of expressions made up of comma separate
|
||||
subexpressions is now possible with a new Eval overload.
|
||||
* Callback functions with fixed number of arguments can now have up to 10
|
||||
Parameters (previous limit was 5)
|
||||
|
||||
New features:
|
||||
* ternary if-then-else operator added (C++ like; "(...) ? ... : ..." )
|
||||
* new intrinsic binary operators: "&&", "||" (logical and, or)
|
||||
* A new bulkmode allows submitting large arrays as variables to compute large
|
||||
numbers of expressions with a single call. This can drastically improve
|
||||
parsing performance when interfacing the library from managed languages like
|
||||
C#. (It doesn't bring any performance benefit for C++ users though...)
|
||||
|
||||
Removed features:
|
||||
* intrinsic "and", "or" and "xor" operators have been removed. I'd like to let
|
||||
users the freedom of defining them on their own versions (either as logical or bitwise
|
||||
operators).
|
||||
* Implementation for complex numbers removed. This was merely a hack. If you
|
||||
need complex numbers try muParserX which provides native support for them.
|
||||
(see: http://beltoforion.de/muparserx/math_expression_parser_en.html)
|
||||
|
||||
Bugfixes:
|
||||
* User defined operators could collide with built in operators that entirely
|
||||
contained their identifier. i.e. user defined "&" would not work with the built
|
||||
in "&&" operator since the user defined operator was detected with a higher
|
||||
priority resulting in a syntax error.
|
||||
* Detection of unknown variables did not work properly in case a postfix operator
|
||||
was defined which was part of the undefined variable.
|
||||
i.e. If a postfix operator "m" was defined expressions like "multi*1.0" did
|
||||
not detect "multi" as an undefined variable.
|
||||
(Reference: http://sourceforge.net/tracker/index.php?func=detail&aid=3343891&group_id=137191&atid=737979)
|
||||
* Postfix operators sharing the first few characters were causing bogus parsing exception.
|
||||
(Reference: https://sourceforge.net/tracker/?func=detail&aid=3358571&group_id=137191&atid=737979)
|
||||
|
||||
Rev 1.34: 04.09.2010
|
||||
--------------------
|
||||
Changes:
|
||||
* The prefix needed for parsing hex values is now "0x" and no longer "$".
|
||||
* AddValIdent reintroduced into the DLL interface
|
||||
|
||||
New features:
|
||||
* The associativity of binary operators can now be changed. The pow operator
|
||||
is now right associative. (This is what Mathematica is using)
|
||||
* Seperator can now be used outside of functions. This allows compound
|
||||
expressions like:
|
||||
"a=10,b=20,c=a*b" The last "argument" will be taken as the return value
|
||||
|
||||
Bugfixes:
|
||||
* The copy constructor did not copy binary operator definitions. Those were lost
|
||||
in the copied parser instance.
|
||||
* Mixing special characters and alphabetic characters in binary operator names
|
||||
led to inconsistent parsing behaviour when parsing expressions like "a ++ b"
|
||||
and "a++b" when "++" is defined as a binary operator. Binary operators must
|
||||
now consist entirely of special characters or of alphabetic ones.
|
||||
(original bug report: https://sourceforge.net/projects/muparser/forums/forum/462843/topic/3696881/index/page/1)
|
||||
* User defined operators were not exactly handled like built in operators. This
|
||||
led to inconsistencies in expression evaluation when using them. The results
|
||||
differed due to slightly different precedence rules.
|
||||
* Using empty string arguments ("") would cause a crash of muParser
|
||||
|
||||
|
||||
Rev 1.32: 29.01.2010
|
||||
--------------------
|
||||
|
||||
Changes:
|
||||
* "example3" renamed to "example2"
|
||||
* Project/Makefiles files are now provided for:
|
||||
- msvc2003
|
||||
- msvc2005
|
||||
- msvc2008
|
||||
- watcom (makefile)
|
||||
- mingw (makefile)
|
||||
- bcc (makefile)
|
||||
* Project files for borland cpp builder were removed
|
||||
|
||||
|
||||
New features:
|
||||
* Added function returning muparsers version number
|
||||
* Added function for resetting the locale
|
||||
|
||||
|
||||
Bugfixes:
|
||||
* Changes example1 in order to fix issues with irritating memory leak reports.
|
||||
Added conditional code for memory leak detection with MSVC in example1.
|
||||
(see: http://www.codeproject.com/KB/recipes/FastMathParser.aspx?msg=3286367#xx3286367xx)
|
||||
* Fixed some warnings for gcc
|
||||
|
||||
|
||||
|
||||
Rev 1.31cp: 15.01.2010 (Maintainance release for CodeProject)
|
||||
----------------------
|
||||
|
||||
Changes:
|
||||
* Archive structure changed
|
||||
* C# wrapper added
|
||||
* Fixed issued that prevented compiling with VS2010 Beta2
|
||||
|
||||
|
||||
Rev 1.30: 09.06.2008
|
||||
--------------------
|
||||
|
||||
Changes:
|
||||
* Epsilon of the numerical differentiation algorithm changed to allow greater accuracy.
|
||||
|
||||
New features:
|
||||
* Setting thousands separator and decimal separator is now possible
|
||||
|
||||
Bugfixes:
|
||||
* The dll interface did not provide a callback for functions without any arguments.
|
||||
|
||||
|
||||
Rev 1.29: Januar 2008
|
||||
---------------------
|
||||
|
||||
Unrelease Version available only via SVN.
|
||||
|
||||
|
||||
Rev 1.28: 02. July, 2007
|
||||
---------------------------
|
||||
|
||||
Library changes:
|
||||
* Interface for the dynamic library changed and extended to create an interface
|
||||
using pure C functions only.
|
||||
* mupInit() removed
|
||||
|
||||
Build system:
|
||||
* MSVC7 Project files removed in favor of MSVC8
|
||||
|
||||
Bugfixes:
|
||||
* The dynamic library did not build on other systems than linux due to a misplaced
|
||||
preprocessor definition. This is fixed now.
|
||||
|
||||
|
||||
Rev 1.27:
|
||||
---------------------------
|
||||
|
||||
Build system:
|
||||
* Modified build\ directory layout introducing some subfolders
|
||||
for the various IDE supported
|
||||
* Project files for BCB and MSVC7 added
|
||||
* Switched to use bakefile 0.2.1 which now correctly creates the
|
||||
"make uninstall" target for autoconf's Makefile.in
|
||||
* Now the library debug builds are named "muparserd" instead of "muparser"
|
||||
to allow multiple mixed release/debug builds to coexist; so e.g. on Windows
|
||||
when building with DEBUG=1, you'll get "muparserd.lib" instead of "muparser.lib"
|
||||
|
||||
New Features:
|
||||
* Factory functions can now take a user defined pointer
|
||||
* String functions can now be used with up to two additional
|
||||
double parameters
|
||||
* Support for UNICODE character types added
|
||||
* Infix operator priority can now be changed by the user
|
||||
|
||||
Bugfixes:
|
||||
* An internal error was raised when evaluating an empty
|
||||
expressions
|
||||
* The error message raised in case of name collisions between
|
||||
implicitely defined variables and postfix operators did contain
|
||||
misleading data.
|
||||
|
||||
|
||||
Rev 1.26: (unofficial release)
|
||||
------------------------------
|
||||
|
||||
New Features:
|
||||
* Unary operator precedence can now be changed by the user.
|
||||
|
||||
|
||||
Rev 1.25: 5. February, 2006
|
||||
---------------------------
|
||||
|
||||
Build system: (special thanks to Francesco Montorsi for implementing it!)
|
||||
* created a bakefile-based build system which adds support for the following win32 compilers:
|
||||
-> MS visual C++ (6 and .NET)
|
||||
-> BorlandC++ (5 or greater)
|
||||
-> Mingw32 (tested with gcc 3.2)
|
||||
-> Watcom (not tested)
|
||||
and for GCC on Unix (using a standard autoconf's configure script).
|
||||
|
||||
Compatibility improvements:
|
||||
* fixed some small warnings when using -Wall with GCC on Unix
|
||||
* added inclusion guards for win32-specific portions of code
|
||||
* added fixes that remove compiler warnings on Intel C++ and the Solaris C++ compiler.
|
||||
|
||||
|
||||
Rev 1.24: 29. October, 2005
|
||||
---------------------------
|
||||
|
||||
Changes:
|
||||
|
||||
Compatibility improvements:
|
||||
* parser now works on 64 bit compilers
|
||||
* (bytecode base datatype can now be changed freely)
|
||||
|
||||
|
||||
Rev 1.23: 19. October, 2005
|
||||
---------------------------
|
||||
|
||||
Changes:
|
||||
|
||||
Bugfixes:
|
||||
* Variable factory examples in Example1.cpp and Example3.cpp contained a subtle bug.
|
||||
|
||||
New features:
|
||||
* Added a MSVC6 project file and introduced muParserFixes.h in order to make it compile with MSVC6
|
||||
|
||||
|
||||
Rev 1.22: October, 2005
|
||||
-----------------------
|
||||
|
||||
Release notes:
|
||||
|
||||
All features of Version 1.22 are similar to Version 1.21. Version 1.22 fixes a compilation issue with
|
||||
gcc 4.0. In order to fix this issue I rewrote part of the library to remove some unnecessary templates.
|
||||
This should make the code cleaner. The Borland Project files were removed. If you want to use it
|
||||
with Borland either use the dll version or create your own project files. I can't support it since I don't
|
||||
have this compiler at hand.
|
||||
|
||||
Changes:
|
||||
|
||||
Project Changes:
|
||||
* Borland project files removed
|
||||
(The code should still compile with BCB but I cant provide you with project files)
|
||||
|
||||
Internal Changes:
|
||||
* unnecessary template files have been removed:
|
||||
- new files: muParserError.cpp, muParserTokenReader.cpp, muParserCallback.cpp
|
||||
- removed Files: muIParserTypes.h
|
||||
|
||||
|
||||
Rev 1.2 / 1.21: April, 2005
|
||||
---------------------------
|
||||
|
||||
Release Notes:
|
||||
First of all the interface has changed so this version is not backwards compatible.
|
||||
After receiving a couple of questions about it, this version features support for
|
||||
user defined binary operators. Consequently the built in operators can now be
|
||||
turned off, thus you can deactivate them and write complete customized parser
|
||||
subclasses that only contain the functionality you want. Another new feature is
|
||||
the introduction of callback functions taking string arguments, implicit
|
||||
generation of variables and the Assignement operator.
|
||||
|
||||
Functionality
|
||||
* New built in operator: xor; Logical xor.
|
||||
* New built in operator: Assignement operator; Defining variables in terms of
|
||||
other variables/constants
|
||||
* New feature: Strings as arguments for callback functions
|
||||
* New feature: User defined binary operators
|
||||
* New feature: ParserInt a class with a sample implementation for
|
||||
integer numbers.
|
||||
* New feature: Callbacks to value regognition functions.
|
||||
|
||||
* Removed: all predefined postfix operators have been removed.
|
||||
* New project file: Now comes with a ready to use windows DLL.
|
||||
* New project file: Makefile for cygwin now included.
|
||||
* New example: Example3 shows usage of the DLL.
|
||||
|
||||
Interface changes
|
||||
* New member function: DefineOprt For adding user defined binary operators.
|
||||
* New member function: EnableBuiltInOprt(bool) Enables/Disables built in
|
||||
binary operators.
|
||||
* New member function: AddValIdent(...) to add callbacks for custom value
|
||||
recognition functions.
|
||||
* Removed: SetVar(), SetConst().
|
||||
* Renamed: Most interface functions have been renamed
|
||||
* Changed: The type for multiargument callbacks multfun_type has changed.
|
||||
It no longer takes a std::vector as input.
|
||||
|
||||
Internal changes
|
||||
* new class muParserTokenReader.h encapsulates the token identification
|
||||
and token assignement.
|
||||
* Internal handling of function callbacks unified as a result the performance
|
||||
of the bytecode evaluation increased.
|
||||
|
||||
|
||||
Rev 1.10 : December 30, 2004
|
||||
----------------------------
|
||||
|
||||
Release Notes:
|
||||
This version does not contain major new feature compared to V1.07 but its internal structure has
|
||||
changed significantly. The String parsing routine is slower than the one of V1.07 but bytecode
|
||||
parsing is equally fast. On the other hand the error messages of V1.09 are more flexible and you
|
||||
can change its value datatype. It should work on 64-bit systems. For this reason I supply both
|
||||
versions for download. If you use V1.07 and are happy with it there is no need for updating
|
||||
your version.
|
||||
|
||||
* New example program: Archive now contains two demo programs: One for standard C++ and one for
|
||||
managed C++.
|
||||
* New member function: RemoveVar(...) can be used for removing a single variable from the internal
|
||||
storage.
|
||||
* New member function: GetVar() can be used for querying the variable names and pointers of all
|
||||
variables defined in the parser.
|
||||
* New member function: GetConst() can be used for querying all defined constants and their values.
|
||||
* New member function: GetFunDef() can be used for querying all defined functions and the number of
|
||||
arguments they expect.
|
||||
* Internal structure changed; hanging base datatype at compile time is now possible.
|
||||
* Bugfix: Postfix operator parsing could fail in certain cases; This has been fixed now.
|
||||
* Bugfix: Variable names must will now be tested if they conflict with constant or function names.
|
||||
* Internal change: Removed most dependencies from the C-string libraries.
|
||||
* Internal change: Bytecode is now stored in a separate class: ParserByteCode.h
|
||||
* Internal change: GetUsedVar() does no longer require that variables are defined at time of call.
|
||||
* Internal change: Error treatment changed. ParserException is no longer derived from
|
||||
std::runtime_error; Internal treatment of Error messages changed.
|
||||
* New functions in Parser interface: ValidNameChars(), ValidOprtChars() and ValidPrefixOprtChars()
|
||||
they are used for defining the charset allowed for variable-, operator- and
|
||||
function names.
|
||||
|
||||
|
||||
Rev 1.09 : November 20, 2004
|
||||
----------------------------
|
||||
|
||||
* New member function: RemoveVar(...) can be used for removing a single variable from the internal
|
||||
storage.
|
||||
* Internal structure changed; changing base datatype at compile time is now possible.
|
||||
* Bug fix: Postfix operator parsing could fail in certain cases; This has been fixed now.
|
||||
* Internal change: Removed most dependencies from the C-string libraries.
|
||||
* Internal change: Bytecode is now stored in a seperate class: ParserByteCode.h.
|
||||
* Internal change: GetUsedVar() does no longer require that variables are defined at time of call.
|
||||
* Internal change: Error treatment changed. ParserException is no longer derived from
|
||||
std::runtime_error; Internal treatment of Error messages changed.
|
||||
* New functions in Parser interface; ValidNameChars(), ValidOprtChars() and ValidPrefixOprtChars()
|
||||
they are used for defining the charset allowed for variable-, operator- and function names.
|
||||
|
||||
|
||||
Rev 1.08 : November, 2004
|
||||
-------------------------
|
||||
|
||||
* unpublished; experimental template version with respect to data type and underlying string
|
||||
type (string <-> widestring). The idea was dropped...
|
||||
|
||||
|
||||
Rev 1.07 : September 4 2004
|
||||
---------------------------
|
||||
|
||||
* Improved portability; Changes to make life for MSVC 6 user easier, there are probably still some
|
||||
issues left.
|
||||
* Improved portability; Changes in order to allow compiling on BCB.
|
||||
* New function; value_type Diff(value_type *a_Var, value_type a_fPos) 4th order Differentiation with
|
||||
respect to a certain variable; added in muParser.h.
|
||||
|
||||
|
||||
Rev 1.06 : August 20 2004
|
||||
-------------------------
|
||||
|
||||
* Volatile functions added; All overloaded AddFun(...) functions can now take a third parameter
|
||||
indicating that the function can not be optimized.
|
||||
* Internal changes: muParserStack.h simplified; refactorings
|
||||
* Parser is now distributed under the MIT License; all comments changed accordingly.
|
||||
|
||||
|
||||
Rev 1.05 : August 20 2004
|
||||
-------------------------
|
||||
|
||||
* Variable/constant names will now be checked for invalid characters.
|
||||
* Querying the names of all variables used in an expression is now possible; new function: GetUsedVar().
|
||||
* Disabling bytecode parsing is now possible; new function: EnableByteCode(bool bStat).
|
||||
* Predefined functions with variable number of arguments added: sum, avg, min, max.
|
||||
* Unary prefix operators added; new functions: AddPrefixOp(...), ClearPrefixOp().
|
||||
* Postfix operator interface names changed; new function names: AddPostfixOp(...), ClearPostfixOp().
|
||||
* Hardcoded sign operators removed in favor of prefix operators; bytecode format changed accordingly.
|
||||
* Internal changes: static array removed in Command code calculation routine; misc. changes.
|
||||
|
||||
|
||||
Rev 1.04 : August 16 2004
|
||||
-------------------------
|
||||
|
||||
* Support for functions with variable number of arguments added.
|
||||
* Internal structure changed; new: ParserBase.h, ParserBase.cpp; removed: ParserException.h;
|
||||
changed: Parser.h, Parser.cpp.
|
||||
* Bug in the bytecode calculation function fixed (affected the unary minus operator).
|
||||
* Optimizer can be deactivated; new function: EnableOptimizer(bool bStat).
|
||||
|
||||
|
||||
Rev 1.03 : August 10 2004
|
||||
-------------------------
|
||||
|
||||
* Support for user-defined unary postfix operators added; new functions: AddPostOp(), InitPostOp(),
|
||||
ClearPostOp().
|
||||
* Minor changes to the bytecode parsing routine.
|
||||
* User defined functions can now have up to four parameters.
|
||||
* Performance optimized: simple formula optimization added; (precalculation of constant parts of the
|
||||
expression).
|
||||
* Bug fixes: Multi-arg function parameters, constant name lookup and unary minus did not work properly.
|
||||
|
||||
|
||||
Rev 1.02 : July 30 2004
|
||||
-----------------------
|
||||
|
||||
* Support for user defined constants added; new functions: InitConst(), AddConst(), SetConst(),
|
||||
ClearConst().
|
||||
* Single variables can now be added using AddVar(); you have now the choice of adding them either
|
||||
one by one or all at the same time using SetVar(const varmap_type &a_vVar).
|
||||
* Internal handling of variables changed, is now similar to function handling.
|
||||
* Virtual destructor added; InitFun(), InitConst() are now virtual too thus making it possible to
|
||||
derive new parsers with a modified set of default functions and constants.
|
||||
* Support for user defined functions with 2 or 3 parameters added; bytecode format changed to hold
|
||||
function parameter count.
|
||||
|
||||
|
||||
Rev 1.01 : July 23 2004
|
||||
-----------------------
|
||||
|
||||
* Support for user defined functions has been added; new functions: AddFun(), ClearFun(),
|
||||
InitFunctions().
|
||||
* Built in constants have been removed; the parser contained undocumented built in
|
||||
constants pi, e.
|
||||
There was the possibility of name conflicts with user defined variables.
|
||||
* Setting multiple variables with SetVar can now be done with a map of names and pointers as the only
|
||||
argument. For this reason, a new type Parser::varmap_type was added. The old version that took 3
|
||||
arguments (array of names, array of pointers, and array length) is now marked as deprecated.
|
||||
* The names of logarithm functions have changed. The new names are: log2 for base 2, log10 or log for
|
||||
base 10, and ln for base e.
|
||||
|
||||
|
||||
Rev 1.00 : July 21 2004
|
||||
-----------------------
|
||||
|
||||
* Initial release
|
35
muparser-2.2.5_GR/License.txt
Executable file
35
muparser-2.2.5_GR/License.txt
Executable file
|
@ -0,0 +1,35 @@
|
|||
#######################################################################
|
||||
# #
|
||||
# #
|
||||
# __________ #
|
||||
# _____ __ __\______ \_____ _______ ______ ____ _______ #
|
||||
# / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ #
|
||||
# | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ #
|
||||
# |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| #
|
||||
# \/ \/ \/ \/ #
|
||||
# Fast math parser Library #
|
||||
# #
|
||||
# Copyright (C) 2011 Ingo Berg #
|
||||
# #
|
||||
# Web: muparser.beltoforion.de #
|
||||
# e-mail: muparser@beltoforion.de #
|
||||
# #
|
||||
# #
|
||||
#######################################################################
|
||||
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||
software and associated documentation files (the "Software"), to deal in the Software
|
||||
without restriction, including without limitation the rights to use, copy, modify,
|
||||
merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or
|
||||
substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
|
||||
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
OR OTHER DEALINGS IN THE SOFTWARE.
|
115
muparser-2.2.5_GR/include/muParser.h
Executable file
115
muparser-2.2.5_GR/include/muParser.h
Executable file
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
__________
|
||||
_____ __ __\______ \_____ _______ ______ ____ _______
|
||||
/ \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
|
||||
| Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
|
||||
|__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
|
||||
\/ \/ \/ \/
|
||||
Copyright (C) 2013 Ingo Berg
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||
software and associated documentation files (the "Software"), to deal in the Software
|
||||
without restriction, including without limitation the rights to use, copy, modify,
|
||||
merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or
|
||||
substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
|
||||
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef MU_PARSER_H
|
||||
#define MU_PARSER_H
|
||||
|
||||
//--- Standard includes ------------------------------------------------------------------------
|
||||
#include <vector>
|
||||
|
||||
//--- Parser includes --------------------------------------------------------------------------
|
||||
#include "muParserBase.h"
|
||||
#include "muParserTemplateMagic.h"
|
||||
|
||||
/** \file
|
||||
\brief Definition of the standard floating point parser.
|
||||
*/
|
||||
|
||||
namespace mu
|
||||
{
|
||||
/** \brief Mathematical expressions parser.
|
||||
|
||||
Standard implementation of the mathematical expressions parser.
|
||||
Can be used as a reference implementation for subclassing the parser.
|
||||
|
||||
<small>
|
||||
(C) 2011 Ingo Berg<br>
|
||||
muparser(at)beltoforion.de
|
||||
</small>
|
||||
*/
|
||||
/* final */ class Parser : public ParserBase
|
||||
{
|
||||
public:
|
||||
|
||||
Parser();
|
||||
|
||||
virtual void InitCharSets();
|
||||
virtual void InitFun();
|
||||
virtual void InitConst();
|
||||
virtual void InitOprt();
|
||||
virtual void OnDetectVar(string_type *pExpr, int &nStart, int &nEnd);
|
||||
|
||||
value_type Diff(value_type *a_Var,
|
||||
value_type a_fPos,
|
||||
value_type a_fEpsilon = 0) const;
|
||||
|
||||
protected:
|
||||
|
||||
// Trigonometric functions
|
||||
static value_type Sin(value_type);
|
||||
static value_type Cos(value_type);
|
||||
static value_type Tan(value_type);
|
||||
static value_type Tan2(value_type, value_type);
|
||||
// arcus functions
|
||||
static value_type ASin(value_type);
|
||||
static value_type ACos(value_type);
|
||||
static value_type ATan(value_type);
|
||||
static value_type ATan2(value_type, value_type);
|
||||
|
||||
// hyperbolic functions
|
||||
static value_type Sinh(value_type);
|
||||
static value_type Cosh(value_type);
|
||||
static value_type Tanh(value_type);
|
||||
// arcus hyperbolic functions
|
||||
static value_type ASinh(value_type);
|
||||
static value_type ACosh(value_type);
|
||||
static value_type ATanh(value_type);
|
||||
// Logarithm functions
|
||||
static value_type Log2(value_type); // Logarithm Base 2
|
||||
static value_type Log10(value_type); // Logarithm Base 10
|
||||
static value_type Ln(value_type); // Logarithm Base e (natural logarithm)
|
||||
// misc
|
||||
static value_type Exp(value_type);
|
||||
static value_type Abs(value_type);
|
||||
static value_type Sqrt(value_type);
|
||||
static value_type Rint(value_type);
|
||||
static value_type Sign(value_type);
|
||||
|
||||
// Prefix operators
|
||||
// !!! Unary Minus is a MUST if you want to use negative signs !!!
|
||||
static value_type UnaryMinus(value_type);
|
||||
static value_type UnaryPlus(value_type);
|
||||
|
||||
// Functions with variable number of arguments
|
||||
static value_type Sum(const value_type*, int); // sum
|
||||
static value_type Avg(const value_type*, int); // mean value
|
||||
static value_type Min(const value_type*, int); // minimum
|
||||
static value_type Max(const value_type*, int); // maximum
|
||||
|
||||
static int IsVal(const char_type* a_szExpr, int *a_iPos, value_type *a_fVal);
|
||||
};
|
||||
} // namespace mu
|
||||
|
||||
#endif
|
||||
|
317
muparser-2.2.5_GR/include/muParserBase.h
Executable file
317
muparser-2.2.5_GR/include/muParserBase.h
Executable file
|
@ -0,0 +1,317 @@
|
|||
/*
|
||||
__________
|
||||
_____ __ __\______ \_____ _______ ______ ____ _______
|
||||
/ \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
|
||||
| Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
|
||||
|__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
|
||||
\/ \/ \/ \/
|
||||
Copyright (C) 2013 Ingo Berg
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||
software and associated documentation files (the "Software"), to deal in the Software
|
||||
without restriction, including without limitation the rights to use, copy, modify,
|
||||
merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or
|
||||
substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
|
||||
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef MU_PARSER_BASE_H
|
||||
#define MU_PARSER_BASE_H
|
||||
|
||||
//--- Standard includes ------------------------------------------------------------------------
|
||||
#include <cmath>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <locale>
|
||||
#include <limits.h>
|
||||
|
||||
//--- Parser includes --------------------------------------------------------------------------
|
||||
#include "muParserDef.h"
|
||||
#include "muParserStack.h"
|
||||
#include "muParserTokenReader.h"
|
||||
#include "muParserBytecode.h"
|
||||
#include "muParserError.h"
|
||||
|
||||
|
||||
namespace mu
|
||||
{
|
||||
/** \file
|
||||
\brief This file contains the class definition of the muparser engine.
|
||||
*/
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/** \brief Mathematical expressions parser (base parser engine).
|
||||
\author (C) 2013 Ingo Berg
|
||||
|
||||
This is the implementation of a bytecode based mathematical expressions parser.
|
||||
The formula will be parsed from string and converted into a bytecode.
|
||||
Future calculations will be done with the bytecode instead the formula string
|
||||
resulting in a significant performance increase.
|
||||
Complementary to a set of internally implemented functions the parser is able to handle
|
||||
user defined functions and variables.
|
||||
*/
|
||||
class ParserBase
|
||||
{
|
||||
friend class ParserTokenReader;
|
||||
|
||||
private:
|
||||
|
||||
/** \brief Typedef for the parse functions.
|
||||
|
||||
The parse function do the actual work. The parser exchanges
|
||||
the function pointer to the parser function depending on
|
||||
which state it is in. (i.e. bytecode parser vs. string parser)
|
||||
*/
|
||||
typedef value_type (ParserBase::*ParseFunction)() const;
|
||||
|
||||
/** \brief Type used for storing an array of values. */
|
||||
typedef std::vector<value_type> valbuf_type;
|
||||
|
||||
/** \brief Type for a vector of strings. */
|
||||
typedef std::vector<string_type> stringbuf_type;
|
||||
|
||||
/** \brief Typedef for the token reader. */
|
||||
typedef ParserTokenReader token_reader_type;
|
||||
|
||||
/** \brief Type used for parser tokens. */
|
||||
typedef ParserToken<value_type, string_type> token_type;
|
||||
|
||||
/** \brief Maximum number of threads spawned by OpenMP when using the bulk mode. */
|
||||
static const int s_MaxNumOpenMPThreads = 16;
|
||||
|
||||
public:
|
||||
|
||||
/** \brief Type of the error class.
|
||||
|
||||
Included for backwards compatibility.
|
||||
*/
|
||||
typedef ParserError exception_type;
|
||||
|
||||
static void EnableDebugDump(bool bDumpCmd, bool bDumpStack);
|
||||
|
||||
ParserBase();
|
||||
ParserBase(const ParserBase &a_Parser);
|
||||
ParserBase& operator=(const ParserBase &a_Parser);
|
||||
|
||||
virtual ~ParserBase();
|
||||
|
||||
value_type Eval() const;
|
||||
value_type* Eval(int &nStackSize) const;
|
||||
void Eval(value_type *results, int nBulkSize);
|
||||
|
||||
int GetNumResults() const;
|
||||
|
||||
void SetExpr(const string_type &a_sExpr);
|
||||
void SetVarFactory(facfun_type a_pFactory, void *pUserData = NULL);
|
||||
|
||||
void SetDecSep(char_type cDecSep);
|
||||
void SetThousandsSep(char_type cThousandsSep = 0);
|
||||
void ResetLocale();
|
||||
|
||||
void EnableOptimizer(bool a_bIsOn=true);
|
||||
void EnableBuiltInOprt(bool a_bIsOn=true);
|
||||
|
||||
bool HasBuiltInOprt() const;
|
||||
void AddValIdent(identfun_type a_pCallback);
|
||||
|
||||
/** \fn void mu::ParserBase::DefineFun(const string_type &a_strName, fun_type0 a_pFun, bool a_bAllowOpt = true)
|
||||
\brief Define a parser function without arguments.
|
||||
\param a_strName Name of the function
|
||||
\param a_pFun Pointer to the callback function
|
||||
\param a_bAllowOpt A flag indicating this function may be optimized
|
||||
*/
|
||||
template<typename T>
|
||||
void DefineFun(const string_type &a_strName, T a_pFun, bool a_bAllowOpt = true)
|
||||
{
|
||||
AddCallback( a_strName, ParserCallback(a_pFun, a_bAllowOpt), m_FunDef, ValidNameChars() );
|
||||
}
|
||||
|
||||
void DefineOprt(const string_type &a_strName,
|
||||
fun_type2 a_pFun,
|
||||
unsigned a_iPri=0,
|
||||
EOprtAssociativity a_eAssociativity = oaLEFT,
|
||||
bool a_bAllowOpt = false);
|
||||
void DefineConst(const string_type &a_sName, value_type a_fVal);
|
||||
void DefineStrConst(const string_type &a_sName, const string_type &a_strVal);
|
||||
void DefineVar(const string_type &a_sName, value_type *a_fVar);
|
||||
void DefinePostfixOprt(const string_type &a_strFun, fun_type1 a_pOprt, bool a_bAllowOpt=true);
|
||||
void DefineInfixOprt(const string_type &a_strName, fun_type1 a_pOprt, int a_iPrec=prINFIX, bool a_bAllowOpt=true);
|
||||
|
||||
// Clear user defined variables, constants or functions
|
||||
void ClearVar();
|
||||
void ClearFun();
|
||||
void ClearConst();
|
||||
void ClearInfixOprt();
|
||||
void ClearPostfixOprt();
|
||||
void ClearOprt();
|
||||
|
||||
void RemoveVar(const string_type &a_strVarName);
|
||||
const varmap_type& GetUsedVar() const;
|
||||
const varmap_type& GetVar() const;
|
||||
const valmap_type& GetConst() const;
|
||||
const string_type& GetExpr() const;
|
||||
const funmap_type& GetFunDef() const;
|
||||
string_type GetVersion(EParserVersionInfo eInfo = pviFULL) const;
|
||||
|
||||
const char_type ** GetOprtDef() const;
|
||||
void DefineNameChars(const char_type *a_szCharset);
|
||||
void DefineOprtChars(const char_type *a_szCharset);
|
||||
void DefineInfixOprtChars(const char_type *a_szCharset);
|
||||
|
||||
const char_type* ValidNameChars() const;
|
||||
const char_type* ValidOprtChars() const;
|
||||
const char_type* ValidInfixOprtChars() const;
|
||||
|
||||
void SetArgSep(char_type cArgSep);
|
||||
char_type GetArgSep() const;
|
||||
|
||||
void Error(EErrorCodes a_iErrc,
|
||||
int a_iPos = (int)mu::string_type::npos,
|
||||
const string_type &a_strTok = string_type() ) const;
|
||||
|
||||
protected:
|
||||
|
||||
void Init();
|
||||
|
||||
virtual void InitCharSets() = 0;
|
||||
virtual void InitFun() = 0;
|
||||
virtual void InitConst() = 0;
|
||||
virtual void InitOprt() = 0;
|
||||
|
||||
virtual void OnDetectVar(string_type *pExpr, int &nStart, int &nEnd);
|
||||
|
||||
static const char_type *c_DefaultOprt[];
|
||||
static std::locale s_locale; ///< The locale used by the parser
|
||||
static bool g_DbgDumpCmdCode;
|
||||
static bool g_DbgDumpStack;
|
||||
|
||||
/** \brief A facet class used to change decimal and thousands separator. */
|
||||
template<class TChar>
|
||||
class change_dec_sep : public std::numpunct<TChar>
|
||||
{
|
||||
public:
|
||||
|
||||
explicit change_dec_sep(char_type cDecSep, char_type cThousandsSep = 0, int nGroup = 3)
|
||||
:std::numpunct<TChar>()
|
||||
,m_nGroup(nGroup)
|
||||
,m_cDecPoint(cDecSep)
|
||||
,m_cThousandsSep(cThousandsSep)
|
||||
{}
|
||||
|
||||
protected:
|
||||
|
||||
virtual char_type do_decimal_point() const
|
||||
{
|
||||
return m_cDecPoint;
|
||||
}
|
||||
|
||||
virtual char_type do_thousands_sep() const
|
||||
{
|
||||
return m_cThousandsSep;
|
||||
}
|
||||
|
||||
virtual std::string do_grouping() const
|
||||
{
|
||||
// fix for issue 4: https://code.google.com/p/muparser/issues/detail?id=4
|
||||
// courtesy of Jens Bartsch
|
||||
// original code:
|
||||
// return std::string(1, (char)m_nGroup);
|
||||
// new code:
|
||||
return std::string(1, (char)(m_cThousandsSep > 0 ? m_nGroup : CHAR_MAX));
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
int m_nGroup;
|
||||
char_type m_cDecPoint;
|
||||
char_type m_cThousandsSep;
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
void Assign(const ParserBase &a_Parser);
|
||||
void InitTokenReader();
|
||||
void ReInit() const;
|
||||
|
||||
void AddCallback( const string_type &a_strName,
|
||||
const ParserCallback &a_Callback,
|
||||
funmap_type &a_Storage,
|
||||
const char_type *a_szCharSet );
|
||||
|
||||
void ApplyRemainingOprt(ParserStack<token_type> &a_stOpt,
|
||||
ParserStack<token_type> &a_stVal) const;
|
||||
void ApplyBinOprt(ParserStack<token_type> &a_stOpt,
|
||||
ParserStack<token_type> &a_stVal) const;
|
||||
|
||||
void ApplyIfElse(ParserStack<token_type> &a_stOpt,
|
||||
ParserStack<token_type> &a_stVal) const;
|
||||
|
||||
void ApplyFunc(ParserStack<token_type> &a_stOpt,
|
||||
ParserStack<token_type> &a_stVal,
|
||||
int iArgCount) const;
|
||||
|
||||
token_type ApplyStrFunc(const token_type &a_FunTok,
|
||||
const std::vector<token_type> &a_vArg) const;
|
||||
|
||||
int GetOprtPrecedence(const token_type &a_Tok) const;
|
||||
EOprtAssociativity GetOprtAssociativity(const token_type &a_Tok) const;
|
||||
|
||||
void CreateRPN() const;
|
||||
|
||||
value_type ParseString() const;
|
||||
value_type ParseCmdCode() const;
|
||||
value_type ParseCmdCodeBulk(int nOffset, int nThreadID) const;
|
||||
|
||||
void CheckName(const string_type &a_strName, const string_type &a_CharSet) const;
|
||||
void CheckOprt(const string_type &a_sName,
|
||||
const ParserCallback &a_Callback,
|
||||
const string_type &a_szCharSet) const;
|
||||
|
||||
void StackDump(const ParserStack<token_type > &a_stVal,
|
||||
const ParserStack<token_type > &a_stOprt) const;
|
||||
|
||||
/** \brief Pointer to the parser function.
|
||||
|
||||
Eval() calls the function whose address is stored there.
|
||||
*/
|
||||
mutable ParseFunction m_pParseFormula;
|
||||
mutable ParserByteCode m_vRPN; ///< The Bytecode class.
|
||||
mutable stringbuf_type m_vStringBuf; ///< String buffer, used for storing string function arguments
|
||||
stringbuf_type m_vStringVarBuf;
|
||||
|
||||
std::auto_ptr<token_reader_type> m_pTokenReader; ///< Managed pointer to the token reader object.
|
||||
|
||||
funmap_type m_FunDef; ///< Map of function names and pointers.
|
||||
funmap_type m_PostOprtDef; ///< Postfix operator callbacks
|
||||
funmap_type m_InfixOprtDef; ///< unary infix operator.
|
||||
funmap_type m_OprtDef; ///< Binary operator callbacks
|
||||
valmap_type m_ConstDef; ///< user constants.
|
||||
strmap_type m_StrVarDef; ///< user defined string constants
|
||||
varmap_type m_VarDef; ///< user defind variables.
|
||||
|
||||
bool m_bBuiltInOp; ///< Flag that can be used for switching built in operators on and off
|
||||
|
||||
string_type m_sNameChars; ///< Charset for names
|
||||
string_type m_sOprtChars; ///< Charset for postfix/ binary operator tokens
|
||||
string_type m_sInfixOprtChars; ///< Charset for infix operator tokens
|
||||
|
||||
mutable int m_nIfElseCounter; ///< Internal counter for keeping track of nested if-then-else clauses
|
||||
|
||||
// items merely used for caching state information
|
||||
mutable valbuf_type m_vStackBuffer; ///< This is merely a buffer used for the stack in the cmd parsing routine
|
||||
mutable int m_nFinalResultIdx;
|
||||
};
|
||||
|
||||
} // namespace mu
|
||||
|
||||
#endif
|
||||
|
141
muparser-2.2.5_GR/include/muParserBytecode.h
Executable file
141
muparser-2.2.5_GR/include/muParserBytecode.h
Executable file
|
@ -0,0 +1,141 @@
|
|||
/*
|
||||
__________
|
||||
_____ __ __\______ \_____ _______ ______ ____ _______
|
||||
/ \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
|
||||
| Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
|
||||
|__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
|
||||
\/ \/ \/ \/
|
||||
Copyright (C) 2004-2013 Ingo Berg
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||
software and associated documentation files (the "Software"), to deal in the Software
|
||||
without restriction, including without limitation the rights to use, copy, modify,
|
||||
merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or
|
||||
substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
|
||||
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef MU_PARSER_BYTECODE_H
|
||||
#define MU_PARSER_BYTECODE_H
|
||||
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
#include <stack>
|
||||
#include <vector>
|
||||
|
||||
#include "muParserDef.h"
|
||||
#include "muParserError.h"
|
||||
#include "muParserToken.h"
|
||||
|
||||
/** \file
|
||||
\brief Definition of the parser bytecode class.
|
||||
*/
|
||||
|
||||
|
||||
namespace mu
|
||||
{
|
||||
struct SToken
|
||||
{
|
||||
ECmdCode Cmd;
|
||||
int StackPos;
|
||||
|
||||
union
|
||||
{
|
||||
struct //SValData
|
||||
{
|
||||
value_type *ptr;
|
||||
value_type data;
|
||||
value_type data2;
|
||||
} Val;
|
||||
|
||||
struct //SFunData
|
||||
{
|
||||
// Note: generic_fun_type is merely a placeholder. The real type could be
|
||||
// anything between gun_type1 and fun_type9. I can't use a void
|
||||
// pointer due to constraints in the ANSI standard which allows
|
||||
// data pointers and function pointers to differ in size.
|
||||
generic_fun_type ptr;
|
||||
int argc;
|
||||
int idx;
|
||||
} Fun;
|
||||
|
||||
struct //SOprtData
|
||||
{
|
||||
value_type *ptr;
|
||||
int offset;
|
||||
} Oprt;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/** \brief Bytecode implementation of the Math Parser.
|
||||
|
||||
The bytecode contains the formula converted to revers polish notation stored in a continious
|
||||
memory area. Associated with this data are operator codes, variable pointers, constant
|
||||
values and function pointers. Those are necessary in order to calculate the result.
|
||||
All those data items will be casted to the underlying datatype of the bytecode.
|
||||
|
||||
\author (C) 2004-2013 Ingo Berg
|
||||
*/
|
||||
class ParserByteCode
|
||||
{
|
||||
private:
|
||||
|
||||
/** \brief Token type for internal use only. */
|
||||
typedef ParserToken<value_type, string_type> token_type;
|
||||
|
||||
/** \brief Token vector for storing the RPN. */
|
||||
typedef std::vector<SToken> rpn_type;
|
||||
|
||||
/** \brief Position in the Calculation array. */
|
||||
unsigned m_iStackPos;
|
||||
|
||||
/** \brief Maximum size needed for the stack. */
|
||||
std::size_t m_iMaxStackSize;
|
||||
|
||||
/** \brief The actual rpn storage. */
|
||||
rpn_type m_vRPN;
|
||||
|
||||
bool m_bEnableOptimizer;
|
||||
|
||||
void ConstantFolding(ECmdCode a_Oprt);
|
||||
|
||||
public:
|
||||
|
||||
ParserByteCode();
|
||||
ParserByteCode(const ParserByteCode &a_ByteCode);
|
||||
ParserByteCode& operator=(const ParserByteCode &a_ByteCode);
|
||||
void Assign(const ParserByteCode &a_ByteCode);
|
||||
|
||||
void AddVar(value_type *a_pVar);
|
||||
void AddVal(value_type a_fVal);
|
||||
void AddOp(ECmdCode a_Oprt);
|
||||
void AddIfElse(ECmdCode a_Oprt);
|
||||
void AddAssignOp(value_type *a_pVar);
|
||||
void AddFun(generic_fun_type a_pFun, int a_iArgc);
|
||||
void AddBulkFun(generic_fun_type a_pFun, int a_iArgc);
|
||||
void AddStrFun(generic_fun_type a_pFun, int a_iArgc, int a_iIdx);
|
||||
|
||||
void EnableOptimizer(bool bStat);
|
||||
|
||||
void Finalize();
|
||||
void clear();
|
||||
std::size_t GetMaxStackSize() const;
|
||||
std::size_t GetSize() const;
|
||||
|
||||
const SToken* GetBase() const;
|
||||
void AsciiDump();
|
||||
};
|
||||
|
||||
} // namespace mu
|
||||
|
||||
#endif
|
||||
|
||||
|
118
muparser-2.2.5_GR/include/muParserCallback.h
Executable file
118
muparser-2.2.5_GR/include/muParserCallback.h
Executable file
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
__________
|
||||
_____ __ __\______ \_____ _______ ______ ____ _______
|
||||
/ \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
|
||||
| Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
|
||||
|__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
|
||||
\/ \/ \/ \/
|
||||
Copyright (C) 2004-2011 Ingo Berg
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||
software and associated documentation files (the "Software"), to deal in the Software
|
||||
without restriction, including without limitation the rights to use, copy, modify,
|
||||
merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or
|
||||
substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
|
||||
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MU_PARSER_CALLBACK_H
|
||||
#define MU_PARSER_CALLBACK_H
|
||||
|
||||
#include "muParserDef.h"
|
||||
|
||||
/** \file
|
||||
\brief Definition of the parser callback class.
|
||||
*/
|
||||
|
||||
namespace mu
|
||||
{
|
||||
|
||||
/** \brief Encapsulation of prototypes for a numerical parser function.
|
||||
|
||||
Encapsulates the prototyp for numerical parser functions. The class
|
||||
stores the number of arguments for parser functions as well
|
||||
as additional flags indication the function is non optimizeable.
|
||||
The pointer to the callback function pointer is stored as void*
|
||||
and needs to be casted according to the argument count.
|
||||
Negative argument counts indicate a parser function with a variable number
|
||||
of arguments.
|
||||
|
||||
\author (C) 2004-2011 Ingo Berg
|
||||
*/
|
||||
class ParserCallback
|
||||
{
|
||||
public:
|
||||
ParserCallback(fun_type0 a_pFun, bool a_bAllowOpti);
|
||||
ParserCallback(fun_type1 a_pFun, bool a_bAllowOpti, int a_iPrec = -1, ECmdCode a_iCode=cmFUNC);
|
||||
ParserCallback(fun_type2 a_pFun, bool a_bAllowOpti, int a_iPrec, EOprtAssociativity a_eAssociativity);
|
||||
ParserCallback(fun_type2 a_pFun, bool a_bAllowOpti);
|
||||
ParserCallback(fun_type3 a_pFun, bool a_bAllowOpti);
|
||||
ParserCallback(fun_type4 a_pFun, bool a_bAllowOpti);
|
||||
ParserCallback(fun_type5 a_pFun, bool a_bAllowOpti);
|
||||
ParserCallback(fun_type6 a_pFun, bool a_bAllowOpti);
|
||||
ParserCallback(fun_type7 a_pFun, bool a_bAllowOpti);
|
||||
ParserCallback(fun_type8 a_pFun, bool a_bAllowOpti);
|
||||
ParserCallback(fun_type9 a_pFun, bool a_bAllowOpti);
|
||||
ParserCallback(fun_type10 a_pFun, bool a_bAllowOpti);
|
||||
|
||||
ParserCallback(bulkfun_type0 a_pFun, bool a_bAllowOpti);
|
||||
ParserCallback(bulkfun_type1 a_pFun, bool a_bAllowOpti);
|
||||
ParserCallback(bulkfun_type2 a_pFun, bool a_bAllowOpti);
|
||||
ParserCallback(bulkfun_type3 a_pFun, bool a_bAllowOpti);
|
||||
ParserCallback(bulkfun_type4 a_pFun, bool a_bAllowOpti);
|
||||
ParserCallback(bulkfun_type5 a_pFun, bool a_bAllowOpti);
|
||||
ParserCallback(bulkfun_type6 a_pFun, bool a_bAllowOpti);
|
||||
ParserCallback(bulkfun_type7 a_pFun, bool a_bAllowOpti);
|
||||
ParserCallback(bulkfun_type8 a_pFun, bool a_bAllowOpti);
|
||||
ParserCallback(bulkfun_type9 a_pFun, bool a_bAllowOpti);
|
||||
ParserCallback(bulkfun_type10 a_pFun, bool a_bAllowOpti);
|
||||
|
||||
ParserCallback(multfun_type a_pFun, bool a_bAllowOpti);
|
||||
ParserCallback(strfun_type1 a_pFun, bool a_bAllowOpti);
|
||||
ParserCallback(strfun_type2 a_pFun, bool a_bAllowOpti);
|
||||
ParserCallback(strfun_type3 a_pFun, bool a_bAllowOpti);
|
||||
ParserCallback();
|
||||
ParserCallback(const ParserCallback &a_Fun);
|
||||
|
||||
ParserCallback* Clone() const;
|
||||
|
||||
bool IsOptimizable() const;
|
||||
void* GetAddr() const;
|
||||
ECmdCode GetCode() const;
|
||||
ETypeCode GetType() const;
|
||||
int GetPri() const;
|
||||
EOprtAssociativity GetAssociativity() const;
|
||||
int GetArgc() const;
|
||||
|
||||
private:
|
||||
void *m_pFun; ///< Pointer to the callback function, casted to void
|
||||
|
||||
/** \brief Number of numeric function arguments
|
||||
|
||||
This number is negative for functions with variable number of arguments. in this cases
|
||||
they represent the actual number of arguments found.
|
||||
*/
|
||||
int m_iArgc;
|
||||
int m_iPri; ///< Valid only for binary and infix operators; Operator precedence.
|
||||
EOprtAssociativity m_eOprtAsct; ///< Operator associativity; Valid only for binary operators
|
||||
ECmdCode m_iCode;
|
||||
ETypeCode m_iType;
|
||||
bool m_bAllowOpti; ///< Flag indication optimizeability
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/** \brief Container for Callback objects. */
|
||||
typedef std::map<string_type, ParserCallback> funmap_type;
|
||||
|
||||
} // namespace mu
|
||||
|
||||
#endif
|
||||
|
241
muparser-2.2.5_GR/include/muParserDLL.h
Executable file
241
muparser-2.2.5_GR/include/muParserDLL.h
Executable file
|
@ -0,0 +1,241 @@
|
|||
/*
|
||||
__________
|
||||
_____ __ __\______ \_____ _______ ______ ____ _______
|
||||
/ \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
|
||||
| Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
|
||||
|__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
|
||||
\/ \/ \/ \/
|
||||
Copyright (C) 2011 Ingo Berg
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||
software and associated documentation files (the "Software"), to deal in the Software
|
||||
without restriction, including without limitation the rights to use, copy, modify,
|
||||
merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or
|
||||
substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
|
||||
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef MU_PARSER_DLL_H
|
||||
#define MU_PARSER_DLL_H
|
||||
|
||||
#if defined(WIN32) || defined(_WIN32)
|
||||
#ifdef MUPARSERLIB_EXPORTS
|
||||
#define API_EXPORT(TYPE) __declspec(dllexport) TYPE __cdecl
|
||||
#else
|
||||
#define API_EXPORT(TYPE) __declspec(dllimport) TYPE __cdecl
|
||||
#endif
|
||||
#else
|
||||
#define API_EXPORT(TYPE) TYPE
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/** \file
|
||||
\brief This file contains the DLL interface of muparser.
|
||||
*/
|
||||
|
||||
// Basic types
|
||||
typedef void* muParserHandle_t; // parser handle
|
||||
|
||||
#ifndef _UNICODE
|
||||
typedef char muChar_t; // character type
|
||||
#else
|
||||
typedef wchar_t muChar_t; // character type
|
||||
#endif
|
||||
|
||||
typedef int muBool_t; // boolean type
|
||||
typedef int muInt_t; // integer type
|
||||
typedef double muFloat_t; // floating point type
|
||||
|
||||
// function types for calculation
|
||||
typedef muFloat_t (*muFun0_t )();
|
||||
typedef muFloat_t (*muFun1_t )(muFloat_t);
|
||||
typedef muFloat_t (*muFun2_t )(muFloat_t, muFloat_t);
|
||||
typedef muFloat_t (*muFun3_t )(muFloat_t, muFloat_t, muFloat_t);
|
||||
typedef muFloat_t (*muFun4_t )(muFloat_t, muFloat_t, muFloat_t, muFloat_t);
|
||||
typedef muFloat_t (*muFun5_t )(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t);
|
||||
typedef muFloat_t (*muFun6_t )(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t);
|
||||
typedef muFloat_t (*muFun7_t )(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t);
|
||||
typedef muFloat_t (*muFun8_t )(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t);
|
||||
typedef muFloat_t (*muFun9_t )(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t);
|
||||
typedef muFloat_t (*muFun10_t)(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t);
|
||||
|
||||
// Function prototypes for bulkmode functions
|
||||
typedef muFloat_t (*muBulkFun0_t )(int, int);
|
||||
typedef muFloat_t (*muBulkFun1_t )(int, int, muFloat_t);
|
||||
typedef muFloat_t (*muBulkFun2_t )(int, int, muFloat_t, muFloat_t);
|
||||
typedef muFloat_t (*muBulkFun3_t )(int, int, muFloat_t, muFloat_t, muFloat_t);
|
||||
typedef muFloat_t (*muBulkFun4_t )(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t);
|
||||
typedef muFloat_t (*muBulkFun5_t )(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t);
|
||||
typedef muFloat_t (*muBulkFun6_t )(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t);
|
||||
typedef muFloat_t (*muBulkFun7_t )(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t);
|
||||
typedef muFloat_t (*muBulkFun8_t )(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t);
|
||||
typedef muFloat_t (*muBulkFun9_t )(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t);
|
||||
typedef muFloat_t (*muBulkFun10_t)(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t);
|
||||
|
||||
typedef muFloat_t (*muMultFun_t)(const muFloat_t*, muInt_t);
|
||||
typedef muFloat_t (*muStrFun1_t)(const muChar_t*);
|
||||
typedef muFloat_t (*muStrFun2_t)(const muChar_t*, muFloat_t);
|
||||
typedef muFloat_t (*muStrFun3_t)(const muChar_t*, muFloat_t, muFloat_t);
|
||||
|
||||
// Functions for parser management
|
||||
typedef void (*muErrorHandler_t)(muParserHandle_t a_hParser); // [optional] callback to an error handler
|
||||
typedef muFloat_t* (*muFacFun_t)(const muChar_t*, void*); // [optional] callback for creating new variables
|
||||
typedef muInt_t (*muIdentFun_t)(const muChar_t*, muInt_t*, muFloat_t*); // [optional] value identification callbacks
|
||||
|
||||
//-----------------------------------------------------------------------------------------------------
|
||||
// Constants
|
||||
static const int muOPRT_ASCT_LEFT = 0;
|
||||
static const int muOPRT_ASCT_RIGHT = 1;
|
||||
|
||||
static const int muBASETYPE_FLOAT = 0;
|
||||
static const int muBASETYPE_INT = 1;
|
||||
|
||||
//-----------------------------------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
// muParser C compatible bindings
|
||||
//
|
||||
//
|
||||
//-----------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
// Basic operations / initialization
|
||||
API_EXPORT(muParserHandle_t) mupCreate(int nBaseType);
|
||||
API_EXPORT(void) mupRelease(muParserHandle_t a_hParser);
|
||||
API_EXPORT(const muChar_t*) mupGetExpr(muParserHandle_t a_hParser);
|
||||
API_EXPORT(void) mupSetExpr(muParserHandle_t a_hParser, const muChar_t *a_szExpr);
|
||||
API_EXPORT(void) mupSetVarFactory(muParserHandle_t a_hParser, muFacFun_t a_pFactory, void* pUserData);
|
||||
API_EXPORT(const muChar_t*) mupGetVersion(muParserHandle_t a_hParser);
|
||||
API_EXPORT(muFloat_t) mupEval(muParserHandle_t a_hParser);
|
||||
API_EXPORT(muFloat_t*) mupEvalMulti(muParserHandle_t a_hParser, int *nNum);
|
||||
API_EXPORT(void) mupEvalBulk(muParserHandle_t a_hParser, muFloat_t *a_fResult, int nSize);
|
||||
|
||||
// Defining callbacks / variables / constants
|
||||
API_EXPORT(void) mupDefineFun0(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun0_t a_pFun, muBool_t a_bOptimize);
|
||||
API_EXPORT(void) mupDefineFun1(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun1_t a_pFun, muBool_t a_bOptimize);
|
||||
API_EXPORT(void) mupDefineFun2(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun2_t a_pFun, muBool_t a_bOptimize);
|
||||
API_EXPORT(void) mupDefineFun3(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun3_t a_pFun, muBool_t a_bOptimize);
|
||||
API_EXPORT(void) mupDefineFun4(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun4_t a_pFun, muBool_t a_bOptimize);
|
||||
API_EXPORT(void) mupDefineFun5(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun5_t a_pFun, muBool_t a_bOptimize);
|
||||
API_EXPORT(void) mupDefineFun6(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun6_t a_pFun, muBool_t a_bOptimize);
|
||||
API_EXPORT(void) mupDefineFun7(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun7_t a_pFun, muBool_t a_bOptimize);
|
||||
API_EXPORT(void) mupDefineFun8(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun8_t a_pFun, muBool_t a_bOptimize);
|
||||
API_EXPORT(void) mupDefineFun9(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun9_t a_pFun, muBool_t a_bOptimize);
|
||||
API_EXPORT(void) mupDefineFun10(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun10_t a_pFun, muBool_t a_bOptimize);
|
||||
|
||||
// Defining bulkmode functions
|
||||
API_EXPORT(void) mupDefineBulkFun0(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun0_t a_pFun);
|
||||
API_EXPORT(void) mupDefineBulkFun1(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun1_t a_pFun);
|
||||
API_EXPORT(void) mupDefineBulkFun2(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun2_t a_pFun);
|
||||
API_EXPORT(void) mupDefineBulkFun3(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun3_t a_pFun);
|
||||
API_EXPORT(void) mupDefineBulkFun4(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun4_t a_pFun);
|
||||
API_EXPORT(void) mupDefineBulkFun5(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun5_t a_pFun);
|
||||
API_EXPORT(void) mupDefineBulkFun6(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun6_t a_pFun);
|
||||
API_EXPORT(void) mupDefineBulkFun7(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun7_t a_pFun);
|
||||
API_EXPORT(void) mupDefineBulkFun8(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun8_t a_pFun);
|
||||
API_EXPORT(void) mupDefineBulkFun9(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun9_t a_pFun);
|
||||
API_EXPORT(void) mupDefineBulkFun10(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun10_t a_pFun);
|
||||
|
||||
// string functions
|
||||
API_EXPORT(void) mupDefineStrFun1(muParserHandle_t a_hParser, const muChar_t *a_szName, muStrFun1_t a_pFun);
|
||||
API_EXPORT(void) mupDefineStrFun2(muParserHandle_t a_hParser, const muChar_t *a_szName, muStrFun2_t a_pFun);
|
||||
API_EXPORT(void) mupDefineStrFun3(muParserHandle_t a_hParser, const muChar_t *a_szName, muStrFun3_t a_pFun);
|
||||
|
||||
API_EXPORT(void) mupDefineMultFun( muParserHandle_t a_hParser,
|
||||
const muChar_t* a_szName,
|
||||
muMultFun_t a_pFun,
|
||||
muBool_t a_bOptimize);
|
||||
|
||||
API_EXPORT(void) mupDefineOprt( muParserHandle_t a_hParser,
|
||||
const muChar_t* a_szName,
|
||||
muFun2_t a_pFun,
|
||||
muInt_t a_nPrec,
|
||||
muInt_t a_nOprtAsct,
|
||||
muBool_t a_bOptimize);
|
||||
|
||||
API_EXPORT(void) mupDefineConst( muParserHandle_t a_hParser,
|
||||
const muChar_t* a_szName,
|
||||
muFloat_t a_fVal );
|
||||
|
||||
API_EXPORT(void) mupDefineStrConst( muParserHandle_t a_hParser,
|
||||
const muChar_t* a_szName,
|
||||
const muChar_t *a_sVal );
|
||||
|
||||
API_EXPORT(void) mupDefineVar( muParserHandle_t a_hParser,
|
||||
const muChar_t* a_szName,
|
||||
muFloat_t *a_fVar);
|
||||
|
||||
API_EXPORT(void) mupDefineBulkVar( muParserHandle_t a_hParser,
|
||||
const muChar_t* a_szName,
|
||||
muFloat_t *a_fVar);
|
||||
|
||||
API_EXPORT(void) mupDefinePostfixOprt( muParserHandle_t a_hParser,
|
||||
const muChar_t* a_szName,
|
||||
muFun1_t a_pOprt,
|
||||
muBool_t a_bOptimize);
|
||||
|
||||
|
||||
API_EXPORT(void) mupDefineInfixOprt( muParserHandle_t a_hParser,
|
||||
const muChar_t* a_szName,
|
||||
muFun1_t a_pOprt,
|
||||
muBool_t a_bOptimize);
|
||||
|
||||
// Define character sets for identifiers
|
||||
API_EXPORT(void) mupDefineNameChars(muParserHandle_t a_hParser, const muChar_t* a_szCharset);
|
||||
API_EXPORT(void) mupDefineOprtChars(muParserHandle_t a_hParser, const muChar_t* a_szCharset);
|
||||
API_EXPORT(void) mupDefineInfixOprtChars(muParserHandle_t a_hParser, const muChar_t* a_szCharset);
|
||||
|
||||
// Remove all / single variables
|
||||
API_EXPORT(void) mupRemoveVar(muParserHandle_t a_hParser, const muChar_t* a_szName);
|
||||
API_EXPORT(void) mupClearVar(muParserHandle_t a_hParser);
|
||||
API_EXPORT(void) mupClearConst(muParserHandle_t a_hParser);
|
||||
API_EXPORT(void) mupClearOprt(muParserHandle_t a_hParser);
|
||||
API_EXPORT(void) mupClearFun(muParserHandle_t a_hParser);
|
||||
|
||||
// Querying variables / expression variables / constants
|
||||
API_EXPORT(int) mupGetExprVarNum(muParserHandle_t a_hParser);
|
||||
API_EXPORT(int) mupGetVarNum(muParserHandle_t a_hParser);
|
||||
API_EXPORT(int) mupGetConstNum(muParserHandle_t a_hParser);
|
||||
API_EXPORT(void) mupGetExprVar(muParserHandle_t a_hParser, unsigned a_iVar, const muChar_t** a_pszName, muFloat_t** a_pVar);
|
||||
API_EXPORT(void) mupGetVar(muParserHandle_t a_hParser, unsigned a_iVar, const muChar_t** a_pszName, muFloat_t** a_pVar);
|
||||
API_EXPORT(void) mupGetConst(muParserHandle_t a_hParser, unsigned a_iVar, const muChar_t** a_pszName, muFloat_t* a_pVar);
|
||||
API_EXPORT(void) mupSetArgSep(muParserHandle_t a_hParser, const muChar_t cArgSep);
|
||||
API_EXPORT(void) mupSetDecSep(muParserHandle_t a_hParser, const muChar_t cArgSep);
|
||||
API_EXPORT(void) mupSetThousandsSep(muParserHandle_t a_hParser, const muChar_t cArgSep);
|
||||
API_EXPORT(void) mupResetLocale(muParserHandle_t a_hParser);
|
||||
|
||||
// Add value recognition callbacks
|
||||
API_EXPORT(void) mupAddValIdent(muParserHandle_t a_hParser, muIdentFun_t);
|
||||
|
||||
// Error handling
|
||||
API_EXPORT(muBool_t) mupError(muParserHandle_t a_hParser);
|
||||
API_EXPORT(void) mupErrorReset(muParserHandle_t a_hParser);
|
||||
API_EXPORT(void) mupSetErrorHandler(muParserHandle_t a_hParser, muErrorHandler_t a_pErrHandler);
|
||||
API_EXPORT(const muChar_t*) mupGetErrorMsg(muParserHandle_t a_hParser);
|
||||
API_EXPORT(muInt_t) mupGetErrorCode(muParserHandle_t a_hParser);
|
||||
API_EXPORT(muInt_t) mupGetErrorPos(muParserHandle_t a_hParser);
|
||||
API_EXPORT(const muChar_t*) mupGetErrorToken(muParserHandle_t a_hParser);
|
||||
//API_EXPORT(const muChar_t*) mupGetErrorExpr(muParserHandle_t a_hParser);
|
||||
|
||||
// This is used for .NET only. It creates a new variable allowing the dll to
|
||||
// manage the variable rather than the .NET garbage collector.
|
||||
API_EXPORT(muFloat_t*) mupCreateVar();
|
||||
API_EXPORT(void) mupReleaseVar(muFloat_t*);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // include guard
|
368
muparser-2.2.5_GR/include/muParserDef.h
Executable file
368
muparser-2.2.5_GR/include/muParserDef.h
Executable file
|
@ -0,0 +1,368 @@
|
|||
/*
|
||||
__________
|
||||
_____ __ __\______ \_____ _______ ______ ____ _______
|
||||
/ \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
|
||||
| Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
|
||||
|__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
|
||||
\/ \/ \/ \/
|
||||
Copyright (C) 2014 Ingo Berg
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||
software and associated documentation files (the "Software"), to deal in the Software
|
||||
without restriction, including without limitation the rights to use, copy, modify,
|
||||
merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or
|
||||
substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
|
||||
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef MUP_DEF_H
|
||||
#define MUP_DEF_H
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <map>
|
||||
|
||||
#include "muParserFixes.h"
|
||||
|
||||
/** \file
|
||||
\brief This file contains standard definitions used by the parser.
|
||||
*/
|
||||
|
||||
#define MUP_VERSION _T("2.2.5")
|
||||
#define MUP_VERSION_DATE _T("20150427; GC")
|
||||
|
||||
#define MUP_CHARS _T("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
|
||||
|
||||
/** \brief If this macro is defined mathematical exceptions (div by zero) will be thrown as exceptions. */
|
||||
//#define MUP_MATH_EXCEPTIONS
|
||||
|
||||
/** \brief Define the base datatype for values.
|
||||
|
||||
This datatype must be a built in value type. You can not use custom classes.
|
||||
It should be working with all types except "int"!
|
||||
*/
|
||||
#define MUP_BASETYPE double
|
||||
|
||||
/** \brief Activate this option in order to compile with OpenMP support.
|
||||
|
||||
OpenMP is used only in the bulk mode it may increase the performance a bit.
|
||||
*/
|
||||
//#define MUP_USE_OPENMP
|
||||
|
||||
#if defined(_UNICODE)
|
||||
/** \brief Definition of the basic parser string type. */
|
||||
#define MUP_STRING_TYPE std::wstring
|
||||
|
||||
#if !defined(_T)
|
||||
#define _T(x) L##x
|
||||
#endif // not defined _T
|
||||
#else
|
||||
#ifndef _T
|
||||
#define _T(x) x
|
||||
#endif
|
||||
|
||||
/** \brief Definition of the basic parser string type. */
|
||||
#define MUP_STRING_TYPE std::string
|
||||
#endif
|
||||
|
||||
#if defined(_DEBUG)
|
||||
/** \brief Debug macro to force an abortion of the programm with a certain message.
|
||||
*/
|
||||
#define MUP_FAIL(MSG) \
|
||||
{ \
|
||||
bool MSG=false; \
|
||||
assert(MSG); \
|
||||
}
|
||||
|
||||
/** \brief An assertion that does not kill the program.
|
||||
|
||||
This macro is neutralised in UNICODE builds. It's
|
||||
too difficult to translate.
|
||||
*/
|
||||
#define MUP_ASSERT(COND) \
|
||||
if (!(COND)) \
|
||||
{ \
|
||||
stringstream_type ss; \
|
||||
ss << _T("Assertion \"") _T(#COND) _T("\" failed: ") \
|
||||
<< __FILE__ << _T(" line ") \
|
||||
<< __LINE__ << _T("."); \
|
||||
throw ParserError( ss.str() ); \
|
||||
}
|
||||
#else
|
||||
#define MUP_FAIL(MSG)
|
||||
#define MUP_ASSERT(COND)
|
||||
#endif
|
||||
|
||||
|
||||
namespace mu
|
||||
{
|
||||
#if defined(_UNICODE)
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/** \brief Encapsulate wcout. */
|
||||
inline std::wostream& console()
|
||||
{
|
||||
return std::wcout;
|
||||
}
|
||||
|
||||
/** \brief Encapsulate cin. */
|
||||
inline std::wistream& console_in()
|
||||
{
|
||||
return std::wcin;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/** \brief Encapsulate cout.
|
||||
|
||||
Used for supporting UNICODE more easily.
|
||||
*/
|
||||
inline std::ostream& console()
|
||||
{
|
||||
return std::cout;
|
||||
}
|
||||
|
||||
/** \brief Encapsulate cin.
|
||||
|
||||
Used for supporting UNICODE more easily.
|
||||
*/
|
||||
inline std::istream& console_in()
|
||||
{
|
||||
return std::cin;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/** \brief Bytecode values.
|
||||
|
||||
\attention The order of the operator entries must match the order in ParserBase::c_DefaultOprt!
|
||||
*/
|
||||
enum ECmdCode
|
||||
{
|
||||
// The following are codes for built in binary operators
|
||||
// apart from built in operators the user has the opportunity to
|
||||
// add user defined operators.
|
||||
cmLE = 0, ///< Operator item: less or equal
|
||||
cmGE = 1, ///< Operator item: greater or equal
|
||||
cmNEQ = 2, ///< Operator item: not equal
|
||||
cmEQ = 3, ///< Operator item: equals
|
||||
cmLT = 4, ///< Operator item: less than
|
||||
cmGT = 5, ///< Operator item: greater than
|
||||
cmADD = 6, ///< Operator item: add
|
||||
cmSUB = 7, ///< Operator item: subtract
|
||||
cmMUL = 8, ///< Operator item: multiply
|
||||
cmDIV = 9, ///< Operator item: division
|
||||
cmPOW = 10, ///< Operator item: y to the power of ...
|
||||
cmLAND = 11,
|
||||
cmLOR = 12,
|
||||
cmASSIGN = 13, ///< Operator item: Assignment operator
|
||||
cmBO = 14, ///< Operator item: opening bracket
|
||||
cmBC = 15, ///< Operator item: closing bracket
|
||||
cmIF = 16, ///< For use in the ternary if-then-else operator
|
||||
cmELSE = 17, ///< For use in the ternary if-then-else operator
|
||||
cmENDIF = 18, ///< For use in the ternary if-then-else operator
|
||||
cmARG_SEP = 19, ///< function argument separator
|
||||
cmVAR = 20, ///< variable item
|
||||
cmVAL = 21, ///< value item
|
||||
|
||||
// For optimization purposes
|
||||
cmVARPOW2,
|
||||
cmVARPOW3,
|
||||
cmVARPOW4,
|
||||
cmVARMUL,
|
||||
cmPOW2,
|
||||
|
||||
// operators and functions
|
||||
cmFUNC, ///< Code for a generic function item
|
||||
cmFUNC_STR, ///< Code for a function with a string parameter
|
||||
cmFUNC_BULK, ///< Special callbacks for Bulk mode with an additional parameter for the bulk index
|
||||
cmSTRING, ///< Code for a string token
|
||||
cmOPRT_BIN, ///< user defined binary operator
|
||||
cmOPRT_POSTFIX, ///< code for postfix operators
|
||||
cmOPRT_INFIX, ///< code for infix operators
|
||||
cmEND, ///< end of formula
|
||||
cmUNKNOWN ///< uninitialized item
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/** \brief Types internally used by the parser.
|
||||
*/
|
||||
enum ETypeCode
|
||||
{
|
||||
tpSTR = 0, ///< String type (Function arguments and constants only, no string variables)
|
||||
tpDBL = 1, ///< Floating point variables
|
||||
tpVOID = 2 ///< Undefined type.
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
enum EParserVersionInfo
|
||||
{
|
||||
pviBRIEF,
|
||||
pviFULL
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/** \brief Parser operator precedence values. */
|
||||
enum EOprtAssociativity
|
||||
{
|
||||
oaLEFT = 0,
|
||||
oaRIGHT = 1,
|
||||
oaNONE = 2
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/** \brief Parser operator precedence values. */
|
||||
enum EOprtPrecedence
|
||||
{
|
||||
// binary operators
|
||||
prLOR = 1,
|
||||
prLAND = 2,
|
||||
prLOGIC = 3, ///< logic operators
|
||||
prCMP = 4, ///< comparsion operators
|
||||
prADD_SUB = 5, ///< addition
|
||||
prMUL_DIV = 6, ///< multiplication/division
|
||||
prPOW = 7, ///< power operator priority (highest)
|
||||
|
||||
// infix operators
|
||||
prINFIX = 6, ///< Signs have a higher priority than ADD_SUB, but lower than power operator
|
||||
prPOSTFIX = 6 ///< Postfix operator priority (currently unused)
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// basic types
|
||||
|
||||
/** \brief The numeric datatype used by the parser.
|
||||
|
||||
Normally this is a floating point type either single or double precision.
|
||||
*/
|
||||
typedef MUP_BASETYPE value_type;
|
||||
|
||||
/** \brief The stringtype used by the parser.
|
||||
|
||||
Depends on wether UNICODE is used or not.
|
||||
*/
|
||||
typedef MUP_STRING_TYPE string_type;
|
||||
|
||||
/** \brief The character type used by the parser.
|
||||
|
||||
Depends on wether UNICODE is used or not.
|
||||
*/
|
||||
typedef string_type::value_type char_type;
|
||||
|
||||
/** \brief Typedef for easily using stringstream that respect the parser stringtype. */
|
||||
typedef std::basic_stringstream<char_type,
|
||||
std::char_traits<char_type>,
|
||||
std::allocator<char_type> > stringstream_type;
|
||||
|
||||
// Data container types
|
||||
|
||||
/** \brief Type used for storing variables. */
|
||||
typedef std::map<string_type, value_type*> varmap_type;
|
||||
|
||||
/** \brief Type used for storing constants. */
|
||||
typedef std::map<string_type, value_type> valmap_type;
|
||||
|
||||
/** \brief Type for assigning a string name to an index in the internal string table. */
|
||||
typedef std::map<string_type, std::size_t> strmap_type;
|
||||
|
||||
// Parser callbacks
|
||||
|
||||
/** \brief Callback type used for functions without arguments. */
|
||||
typedef value_type (*generic_fun_type)();
|
||||
|
||||
/** \brief Callback type used for functions without arguments. */
|
||||
typedef value_type (*fun_type0)();
|
||||
|
||||
/** \brief Callback type used for functions with a single arguments. */
|
||||
typedef value_type (*fun_type1)(value_type);
|
||||
|
||||
/** \brief Callback type used for functions with two arguments. */
|
||||
typedef value_type (*fun_type2)(value_type, value_type);
|
||||
|
||||
/** \brief Callback type used for functions with three arguments. */
|
||||
typedef value_type (*fun_type3)(value_type, value_type, value_type);
|
||||
|
||||
/** \brief Callback type used for functions with four arguments. */
|
||||
typedef value_type (*fun_type4)(value_type, value_type, value_type, value_type);
|
||||
|
||||
/** \brief Callback type used for functions with five arguments. */
|
||||
typedef value_type (*fun_type5)(value_type, value_type, value_type, value_type, value_type);
|
||||
|
||||
/** \brief Callback type used for functions with five arguments. */
|
||||
typedef value_type (*fun_type6)(value_type, value_type, value_type, value_type, value_type, value_type);
|
||||
|
||||
/** \brief Callback type used for functions with five arguments. */
|
||||
typedef value_type (*fun_type7)(value_type, value_type, value_type, value_type, value_type, value_type, value_type);
|
||||
|
||||
/** \brief Callback type used for functions with five arguments. */
|
||||
typedef value_type (*fun_type8)(value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type);
|
||||
|
||||
/** \brief Callback type used for functions with five arguments. */
|
||||
typedef value_type (*fun_type9)(value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type);
|
||||
|
||||
/** \brief Callback type used for functions with five arguments. */
|
||||
typedef value_type (*fun_type10)(value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type);
|
||||
|
||||
/** \brief Callback type used for functions without arguments. */
|
||||
typedef value_type (*bulkfun_type0)(int, int);
|
||||
|
||||
/** \brief Callback type used for functions with a single arguments. */
|
||||
typedef value_type (*bulkfun_type1)(int, int, value_type);
|
||||
|
||||
/** \brief Callback type used for functions with two arguments. */
|
||||
typedef value_type (*bulkfun_type2)(int, int, value_type, value_type);
|
||||
|
||||
/** \brief Callback type used for functions with three arguments. */
|
||||
typedef value_type (*bulkfun_type3)(int, int, value_type, value_type, value_type);
|
||||
|
||||
/** \brief Callback type used for functions with four arguments. */
|
||||
typedef value_type (*bulkfun_type4)(int, int, value_type, value_type, value_type, value_type);
|
||||
|
||||
/** \brief Callback type used for functions with five arguments. */
|
||||
typedef value_type (*bulkfun_type5)(int, int, value_type, value_type, value_type, value_type, value_type);
|
||||
|
||||
/** \brief Callback type used for functions with five arguments. */
|
||||
typedef value_type (*bulkfun_type6)(int, int, value_type, value_type, value_type, value_type, value_type, value_type);
|
||||
|
||||
/** \brief Callback type used for functions with five arguments. */
|
||||
typedef value_type (*bulkfun_type7)(int, int, value_type, value_type, value_type, value_type, value_type, value_type, value_type);
|
||||
|
||||
/** \brief Callback type used for functions with five arguments. */
|
||||
typedef value_type (*bulkfun_type8)(int, int, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type);
|
||||
|
||||
/** \brief Callback type used for functions with five arguments. */
|
||||
typedef value_type (*bulkfun_type9)(int, int, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type);
|
||||
|
||||
/** \brief Callback type used for functions with five arguments. */
|
||||
typedef value_type (*bulkfun_type10)(int, int, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type);
|
||||
|
||||
/** \brief Callback type used for functions with a variable argument list. */
|
||||
typedef value_type (*multfun_type)(const value_type*, int);
|
||||
|
||||
/** \brief Callback type used for functions taking a string as an argument. */
|
||||
typedef value_type (*strfun_type1)(const char_type*);
|
||||
|
||||
/** \brief Callback type used for functions taking a string and a value as arguments. */
|
||||
typedef value_type (*strfun_type2)(const char_type*, value_type);
|
||||
|
||||
/** \brief Callback type used for functions taking a string and two values as arguments. */
|
||||
typedef value_type (*strfun_type3)(const char_type*, value_type, value_type);
|
||||
|
||||
/** \brief Callback used for functions that identify values in a string. */
|
||||
typedef int (*identfun_type)(const char_type *sExpr, int *nPos, value_type *fVal);
|
||||
|
||||
/** \brief Callback used for variable creation factory functions. */
|
||||
typedef value_type* (*facfun_type)(const char_type*, void*);
|
||||
} // end of namespace
|
||||
|
||||
#endif
|
||||
|
176
muparser-2.2.5_GR/include/muParserError.h
Executable file
176
muparser-2.2.5_GR/include/muParserError.h
Executable file
|
@ -0,0 +1,176 @@
|
|||
/*
|
||||
__________
|
||||
_____ __ __\______ \_____ _______ ______ ____ _______
|
||||
/ \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
|
||||
| Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
|
||||
|__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
|
||||
\/ \/ \/ \/
|
||||
Copyright (C) 2004-2011 Ingo Berg
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||
software and associated documentation files (the "Software"), to deal in the Software
|
||||
without restriction, including without limitation the rights to use, copy, modify,
|
||||
merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or
|
||||
substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
|
||||
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MU_PARSER_ERROR_H
|
||||
#define MU_PARSER_ERROR_H
|
||||
|
||||
#include <cassert>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
#include "muParserDef.h"
|
||||
|
||||
/** \file
|
||||
\brief This file defines the error class used by the parser.
|
||||
*/
|
||||
|
||||
namespace mu
|
||||
{
|
||||
|
||||
/** \brief Error codes. */
|
||||
enum EErrorCodes
|
||||
{
|
||||
// Formula syntax errors
|
||||
ecUNEXPECTED_OPERATOR = 0, ///< Unexpected binary operator found
|
||||
ecUNASSIGNABLE_TOKEN = 1, ///< Token cant be identified.
|
||||
ecUNEXPECTED_EOF = 2, ///< Unexpected end of formula. (Example: "2+sin(")
|
||||
ecUNEXPECTED_ARG_SEP = 3, ///< An unexpected comma has been found. (Example: "1,23")
|
||||
ecUNEXPECTED_ARG = 4, ///< An unexpected argument has been found
|
||||
ecUNEXPECTED_VAL = 5, ///< An unexpected value token has been found
|
||||
ecUNEXPECTED_VAR = 6, ///< An unexpected variable token has been found
|
||||
ecUNEXPECTED_PARENS = 7, ///< Unexpected Parenthesis, opening or closing
|
||||
ecUNEXPECTED_STR = 8, ///< A string has been found at an inapropriate position
|
||||
ecSTRING_EXPECTED = 9, ///< A string function has been called with a different type of argument
|
||||
ecVAL_EXPECTED = 10, ///< A numerical function has been called with a non value type of argument
|
||||
ecMISSING_PARENS = 11, ///< Missing parens. (Example: "3*sin(3")
|
||||
ecUNEXPECTED_FUN = 12, ///< Unexpected function found. (Example: "sin(8)cos(9)")
|
||||
ecUNTERMINATED_STRING = 13, ///< unterminated string constant. (Example: "3*valueof("hello)")
|
||||
ecTOO_MANY_PARAMS = 14, ///< Too many function parameters
|
||||
ecTOO_FEW_PARAMS = 15, ///< Too few function parameters. (Example: "ite(1<2,2)")
|
||||
ecOPRT_TYPE_CONFLICT = 16, ///< binary operators may only be applied to value items of the same type
|
||||
ecSTR_RESULT = 17, ///< result is a string
|
||||
|
||||
// Invalid Parser input Parameters
|
||||
ecINVALID_NAME = 18, ///< Invalid function, variable or constant name.
|
||||
ecINVALID_BINOP_IDENT = 19, ///< Invalid binary operator identifier
|
||||
ecINVALID_INFIX_IDENT = 20, ///< Invalid function, variable or constant name.
|
||||
ecINVALID_POSTFIX_IDENT = 21, ///< Invalid function, variable or constant name.
|
||||
|
||||
ecBUILTIN_OVERLOAD = 22, ///< Trying to overload builtin operator
|
||||
ecINVALID_FUN_PTR = 23, ///< Invalid callback function pointer
|
||||
ecINVALID_VAR_PTR = 24, ///< Invalid variable pointer
|
||||
ecEMPTY_EXPRESSION = 25, ///< The Expression is empty
|
||||
ecNAME_CONFLICT = 26, ///< Name conflict
|
||||
ecOPT_PRI = 27, ///< Invalid operator priority
|
||||
//
|
||||
ecDOMAIN_ERROR = 28, ///< catch division by zero, sqrt(-1), log(0) (currently unused)
|
||||
ecDIV_BY_ZERO = 29, ///< Division by zero (currently unused)
|
||||
ecGENERIC = 30, ///< Generic error
|
||||
ecLOCALE = 31, ///< Conflict with current locale
|
||||
|
||||
ecUNEXPECTED_CONDITIONAL = 32,
|
||||
ecMISSING_ELSE_CLAUSE = 33,
|
||||
ecMISPLACED_COLON = 34,
|
||||
|
||||
ecUNREASONABLE_NUMBER_OF_COMPUTATIONS = 35,
|
||||
|
||||
// internal errors
|
||||
ecINTERNAL_ERROR = 36, ///< Internal error of any kind.
|
||||
|
||||
// The last two are special entries
|
||||
ecCOUNT, ///< This is no error code, It just stores just the total number of error codes
|
||||
ecUNDEFINED = -1 ///< Undefined message, placeholder to detect unassigned error messages
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief A class that handles the error messages.
|
||||
*/
|
||||
class ParserErrorMsg
|
||||
{
|
||||
public:
|
||||
typedef ParserErrorMsg self_type;
|
||||
|
||||
ParserErrorMsg& operator=(const ParserErrorMsg &);
|
||||
ParserErrorMsg(const ParserErrorMsg&);
|
||||
ParserErrorMsg();
|
||||
|
||||
~ParserErrorMsg();
|
||||
|
||||
static const ParserErrorMsg& Instance();
|
||||
string_type operator[](unsigned a_iIdx) const;
|
||||
|
||||
private:
|
||||
std::vector<string_type> m_vErrMsg; ///< A vector with the predefined error messages
|
||||
static const self_type m_Instance; ///< The instance pointer
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Error class of the parser.
|
||||
\author Ingo Berg
|
||||
|
||||
Part of the math parser package.
|
||||
*/
|
||||
class ParserError
|
||||
{
|
||||
private:
|
||||
|
||||
/** \brief Replace all ocuurences of a substring with another string. */
|
||||
void ReplaceSubString( string_type &strSource,
|
||||
const string_type &strFind,
|
||||
const string_type &strReplaceWith);
|
||||
void Reset();
|
||||
|
||||
public:
|
||||
|
||||
ParserError();
|
||||
explicit ParserError(EErrorCodes a_iErrc);
|
||||
explicit ParserError(const string_type &sMsg);
|
||||
ParserError( EErrorCodes a_iErrc,
|
||||
const string_type &sTok,
|
||||
const string_type &sFormula = string_type(),
|
||||
int a_iPos = -1);
|
||||
ParserError( EErrorCodes a_iErrc,
|
||||
int a_iPos,
|
||||
const string_type &sTok);
|
||||
ParserError( const char_type *a_szMsg,
|
||||
int a_iPos = -1,
|
||||
const string_type &sTok = string_type());
|
||||
ParserError(const ParserError &a_Obj);
|
||||
ParserError& operator=(const ParserError &a_Obj);
|
||||
~ParserError();
|
||||
|
||||
void SetFormula(const string_type &a_strFormula);
|
||||
const string_type& GetExpr() const;
|
||||
const string_type& GetMsg() const;
|
||||
int GetPos() const;
|
||||
const string_type& GetToken() const;
|
||||
EErrorCodes GetCode() const;
|
||||
|
||||
private:
|
||||
string_type m_strMsg; ///< The message string
|
||||
string_type m_strFormula; ///< Formula string
|
||||
string_type m_strTok; ///< Token related with the error
|
||||
int m_iPos; ///< Formula position related to the error
|
||||
EErrorCodes m_iErrc; ///< Error code
|
||||
const ParserErrorMsg &m_ErrMsg;
|
||||
};
|
||||
|
||||
} // namespace mu
|
||||
|
||||
#endif
|
||||
|
62
muparser-2.2.5_GR/include/muParserFixes.h
Executable file
62
muparser-2.2.5_GR/include/muParserFixes.h
Executable file
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
__________
|
||||
_____ __ __\______ \_____ _______ ______ ____ _______
|
||||
/ \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
|
||||
| Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
|
||||
|__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
|
||||
\/ \/ \/ \/
|
||||
Copyright (C) 2013 Ingo Berg
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||
software and associated documentation files (the "Software"), to deal in the Software
|
||||
without restriction, including without limitation the rights to use, copy, modify,
|
||||
merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or
|
||||
substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
|
||||
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MU_PARSER_FIXES_H
|
||||
#define MU_PARSER_FIXES_H
|
||||
|
||||
/** \file
|
||||
\brief This file contains compatibility fixes for some platforms.
|
||||
*/
|
||||
|
||||
//
|
||||
// Compatibility fixes
|
||||
//
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Intel Compiler
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#ifdef __INTEL_COMPILER
|
||||
|
||||
// remark #981: operands are evaluated in unspecified order
|
||||
// disabled -> completely pointless if the functions do not have side effects
|
||||
//
|
||||
#pragma warning(disable:981)
|
||||
|
||||
// remark #383: value copied to temporary, reference to temporary used
|
||||
#pragma warning(disable:383)
|
||||
|
||||
// remark #1572: floating-point equality and inequality comparisons are unreliable
|
||||
// disabled -> everyone knows it, the parser passes this problem
|
||||
// deliberately to the user
|
||||
#pragma warning(disable:1572)
|
||||
|
||||
#endif
|
||||
|
||||
#endif // include guard
|
||||
|
||||
|
140
muparser-2.2.5_GR/include/muParserInt.h
Executable file
140
muparser-2.2.5_GR/include/muParserInt.h
Executable file
|
@ -0,0 +1,140 @@
|
|||
/*
|
||||
__________
|
||||
_____ __ __\______ \_____ _______ ______ ____ _______
|
||||
/ \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
|
||||
| Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
|
||||
|__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
|
||||
\/ \/ \/ \/
|
||||
Copyright (C) 2004-2013 Ingo Berg
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||
software and associated documentation files (the "Software"), to deal in the Software
|
||||
without restriction, including without limitation the rights to use, copy, modify,
|
||||
merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or
|
||||
substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
|
||||
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MU_PARSER_INT_H
|
||||
#define MU_PARSER_INT_H
|
||||
|
||||
#include "muParserBase.h"
|
||||
#include <vector>
|
||||
|
||||
|
||||
/** \file
|
||||
\brief Definition of a parser using integer value.
|
||||
*/
|
||||
|
||||
|
||||
namespace mu
|
||||
{
|
||||
|
||||
/** \brief Mathematical expressions parser.
|
||||
|
||||
This version of the parser handles only integer numbers. It disables the built in operators thus it is
|
||||
slower than muParser. Integer values are stored in the double value_type and converted if needed.
|
||||
*/
|
||||
class ParserInt : public ParserBase
|
||||
{
|
||||
private:
|
||||
static int Round(value_type v) { return (int)(v + ((v>=0) ? 0.5 : -0.5) ); };
|
||||
|
||||
static value_type Abs(value_type);
|
||||
static value_type Sign(value_type);
|
||||
static value_type Ite(value_type, value_type, value_type);
|
||||
// !! The unary Minus is a MUST, otherwise you cant use negative signs !!
|
||||
static value_type UnaryMinus(value_type);
|
||||
// Functions with variable number of arguments
|
||||
static value_type Sum(const value_type* a_afArg, int a_iArgc); // sum
|
||||
static value_type Min(const value_type* a_afArg, int a_iArgc); // minimum
|
||||
static value_type Max(const value_type* a_afArg, int a_iArgc); // maximum
|
||||
// binary operator callbacks
|
||||
static value_type Add(value_type v1, value_type v2);
|
||||
static value_type Sub(value_type v1, value_type v2);
|
||||
static value_type Mul(value_type v1, value_type v2);
|
||||
static value_type Div(value_type v1, value_type v2);
|
||||
static value_type Mod(value_type v1, value_type v2);
|
||||
static value_type Pow(value_type v1, value_type v2);
|
||||
static value_type Shr(value_type v1, value_type v2);
|
||||
static value_type Shl(value_type v1, value_type v2);
|
||||
static value_type LogAnd(value_type v1, value_type v2);
|
||||
static value_type LogOr(value_type v1, value_type v2);
|
||||
static value_type And(value_type v1, value_type v2);
|
||||
static value_type Or(value_type v1, value_type v2);
|
||||
static value_type Xor(value_type v1, value_type v2);
|
||||
static value_type Less(value_type v1, value_type v2);
|
||||
static value_type Greater(value_type v1, value_type v2);
|
||||
static value_type LessEq(value_type v1, value_type v2);
|
||||
static value_type GreaterEq(value_type v1, value_type v2);
|
||||
static value_type Equal(value_type v1, value_type v2);
|
||||
static value_type NotEqual(value_type v1, value_type v2);
|
||||
static value_type Not(value_type v1);
|
||||
|
||||
static int IsHexVal(const char_type* a_szExpr, int *a_iPos, value_type *a_iVal);
|
||||
static int IsBinVal(const char_type* a_szExpr, int *a_iPos, value_type *a_iVal);
|
||||
static int IsVal (const char_type* a_szExpr, int *a_iPos, value_type *a_iVal);
|
||||
|
||||
/** \brief A facet class used to change decimal and thousands separator. */
|
||||
template<class TChar>
|
||||
class change_dec_sep : public std::numpunct<TChar>
|
||||
{
|
||||
public:
|
||||
|
||||
explicit change_dec_sep(char_type cDecSep, char_type cThousandsSep = 0, int nGroup = 3)
|
||||
:std::numpunct<TChar>()
|
||||
,m_cDecPoint(cDecSep)
|
||||
,m_cThousandsSep(cThousandsSep)
|
||||
,m_nGroup(nGroup)
|
||||
{}
|
||||
|
||||
protected:
|
||||
|
||||
virtual char_type do_decimal_point() const
|
||||
{
|
||||
return m_cDecPoint;
|
||||
}
|
||||
|
||||
virtual char_type do_thousands_sep() const
|
||||
{
|
||||
return m_cThousandsSep;
|
||||
}
|
||||
|
||||
virtual std::string do_grouping() const
|
||||
{
|
||||
// fix for issue 4: https://code.google.com/p/muparser/issues/detail?id=4
|
||||
// courtesy of Jens Bartsch
|
||||
// original code:
|
||||
// return std::string(1, (char)m_nGroup);
|
||||
// new code:
|
||||
return std::string(1, (char)(m_cThousandsSep > 0 ? m_nGroup : CHAR_MAX));
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
int m_nGroup;
|
||||
char_type m_cDecPoint;
|
||||
char_type m_cThousandsSep;
|
||||
};
|
||||
|
||||
public:
|
||||
ParserInt();
|
||||
|
||||
virtual void InitFun();
|
||||
virtual void InitOprt();
|
||||
virtual void InitConst();
|
||||
virtual void InitCharSets();
|
||||
};
|
||||
|
||||
} // namespace mu
|
||||
|
||||
#endif
|
||||
|
125
muparser-2.2.5_GR/include/muParserStack.h
Executable file
125
muparser-2.2.5_GR/include/muParserStack.h
Executable file
|
@ -0,0 +1,125 @@
|
|||
/*
|
||||
__________
|
||||
_____ __ __\______ \_____ _______ ______ ____ _______
|
||||
/ \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
|
||||
| Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
|
||||
|__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
|
||||
\/ \/ \/ \/
|
||||
Copyright (C) 2004-2011 Ingo Berg
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||
software and associated documentation files (the "Software"), to deal in the Software
|
||||
without restriction, including without limitation the rights to use, copy, modify,
|
||||
merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or
|
||||
substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
|
||||
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MU_PARSER_STACK_H
|
||||
#define MU_PARSER_STACK_H
|
||||
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
#include <stack>
|
||||
#include <vector>
|
||||
|
||||
#include "muParserError.h"
|
||||
#include "muParserToken.h"
|
||||
|
||||
/** \file
|
||||
\brief This file defines the stack used by muparser.
|
||||
*/
|
||||
|
||||
namespace mu
|
||||
{
|
||||
|
||||
/** \brief Parser stack implementation.
|
||||
|
||||
Stack implementation based on a std::stack. The behaviour of pop() had been
|
||||
slightly changed in order to get an error code if the stack is empty.
|
||||
The stack is used within the Parser both as a value stack and as an operator stack.
|
||||
|
||||
\author (C) 2004-2011 Ingo Berg
|
||||
*/
|
||||
template <typename TValueType>
|
||||
class ParserStack
|
||||
{
|
||||
private:
|
||||
|
||||
/** \brief Type of the underlying stack implementation. */
|
||||
typedef std::stack<TValueType, std::vector<TValueType> > impl_type;
|
||||
|
||||
impl_type m_Stack; ///< This is the actual stack.
|
||||
|
||||
public:
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
ParserStack()
|
||||
:m_Stack()
|
||||
{}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
virtual ~ParserStack()
|
||||
{}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Pop a value from the stack.
|
||||
|
||||
Unlike the standard implementation this function will return the value that
|
||||
is going to be taken from the stack.
|
||||
|
||||
\throw ParserException in case the stack is empty.
|
||||
\sa pop(int &a_iErrc)
|
||||
*/
|
||||
TValueType pop()
|
||||
{
|
||||
if (empty())
|
||||
throw ParserError( _T("stack is empty.") );
|
||||
|
||||
TValueType el = top();
|
||||
m_Stack.pop();
|
||||
return el;
|
||||
}
|
||||
|
||||
/** \brief Push an object into the stack.
|
||||
|
||||
\param a_Val object to push into the stack.
|
||||
\throw nothrow
|
||||
*/
|
||||
void push(const TValueType& a_Val)
|
||||
{
|
||||
m_Stack.push(a_Val);
|
||||
}
|
||||
|
||||
/** \brief Return the number of stored elements. */
|
||||
unsigned size() const
|
||||
{
|
||||
return (unsigned)m_Stack.size();
|
||||
}
|
||||
|
||||
/** \brief Returns true if stack is empty false otherwise. */
|
||||
bool empty() const
|
||||
{
|
||||
return m_Stack.empty();
|
||||
}
|
||||
|
||||
/** \brief Return reference to the top object in the stack.
|
||||
|
||||
The top object is the one pushed most recently.
|
||||
*/
|
||||
TValueType& top()
|
||||
{
|
||||
return m_Stack.top();
|
||||
}
|
||||
};
|
||||
} // namespace MathUtils
|
||||
|
||||
#endif
|
113
muparser-2.2.5_GR/include/muParserTemplateMagic.h
Executable file
113
muparser-2.2.5_GR/include/muParserTemplateMagic.h
Executable file
|
@ -0,0 +1,113 @@
|
|||
#ifndef MU_PARSER_TEMPLATE_MAGIC_H
|
||||
#define MU_PARSER_TEMPLATE_MAGIC_H
|
||||
|
||||
#include <cmath>
|
||||
#include "muParserError.h"
|
||||
|
||||
|
||||
namespace mu
|
||||
{
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
//
|
||||
// Compile time type detection
|
||||
//
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
|
||||
/** \brief A class singling out integer types at compile time using
|
||||
template meta programming.
|
||||
*/
|
||||
template<typename T>
|
||||
struct TypeInfo
|
||||
{
|
||||
static bool IsInteger() { return false; }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct TypeInfo<char>
|
||||
{
|
||||
static bool IsInteger() { return true; }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct TypeInfo<short>
|
||||
{
|
||||
static bool IsInteger() { return true; }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct TypeInfo<int>
|
||||
{
|
||||
static bool IsInteger() { return true; }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct TypeInfo<long>
|
||||
{
|
||||
static bool IsInteger() { return true; }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct TypeInfo<unsigned char>
|
||||
{
|
||||
static bool IsInteger() { return true; }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct TypeInfo<unsigned short>
|
||||
{
|
||||
static bool IsInteger() { return true; }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct TypeInfo<unsigned int>
|
||||
{
|
||||
static bool IsInteger() { return true; }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct TypeInfo<unsigned long>
|
||||
{
|
||||
static bool IsInteger() { return true; }
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
//
|
||||
// Standard math functions with dummy overload for integer types
|
||||
//
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
|
||||
/** \brief A template class for providing wrappers for essential math functions.
|
||||
|
||||
This template is spezialized for several types in order to provide a unified interface
|
||||
for parser internal math function calls regardless of the data type.
|
||||
*/
|
||||
template<typename T>
|
||||
struct MathImpl
|
||||
{
|
||||
static T Sin(T v) { return sin(v); }
|
||||
static T Cos(T v) { return cos(v); }
|
||||
static T Tan(T v) { return tan(v); }
|
||||
static T ASin(T v) { return asin(v); }
|
||||
static T ACos(T v) { return acos(v); }
|
||||
static T ATan(T v) { return atan(v); }
|
||||
static T ATan2(T v1, T v2) { return atan2(v1, v2); }
|
||||
static T Sinh(T v) { return sinh(v); }
|
||||
static T Cosh(T v) { return cosh(v); }
|
||||
static T Tanh(T v) { return tanh(v); }
|
||||
static T ASinh(T v) { return log(v + sqrt(v * v + 1)); }
|
||||
static T ACosh(T v) { return log(v + sqrt(v * v - 1)); }
|
||||
static T ATanh(T v) { return ((T)0.5 * log((1 + v) / (1 - v))); }
|
||||
static T Log(T v) { return log(v); }
|
||||
static T Log2(T v) { return log(v)/log((T)2); } // Logarithm base 2
|
||||
static T Log10(T v) { return log10(v); } // Logarithm base 10
|
||||
static T Exp(T v) { return exp(v); }
|
||||
static T Abs(T v) { return (v>=0) ? v : -v; }
|
||||
static T Sqrt(T v) { return sqrt(v); }
|
||||
static T Rint(T v) { return floor(v + (T)0.5); }
|
||||
static T Sign(T v) { return (T)((v<0) ? -1 : (v>0) ? 1 : 0); }
|
||||
static T Pow(T v1, T v2) { return std::pow(v1, v2); }
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
214
muparser-2.2.5_GR/include/muParserTest.h
Executable file
214
muparser-2.2.5_GR/include/muParserTest.h
Executable file
|
@ -0,0 +1,214 @@
|
|||
/*
|
||||
__________
|
||||
_____ __ __\______ \_____ _______ ______ ____ _______
|
||||
/ \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
|
||||
| Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
|
||||
|__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
|
||||
\/ \/ \/ \/
|
||||
Copyright (C) 2013 Ingo Berg
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||
software and associated documentation files (the "Software"), to deal in the Software
|
||||
without restriction, including without limitation the rights to use, copy, modify,
|
||||
merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or
|
||||
substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
|
||||
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MU_PARSER_TEST_H
|
||||
#define MU_PARSER_TEST_H
|
||||
|
||||
#include <string>
|
||||
#include <cstdlib>
|
||||
#include <numeric> // for accumulate
|
||||
#include "muParser.h"
|
||||
#include "muParserInt.h"
|
||||
|
||||
/** \file
|
||||
\brief This file contains the parser test class.
|
||||
*/
|
||||
|
||||
namespace mu
|
||||
{
|
||||
/** \brief Namespace for test cases. */
|
||||
namespace Test
|
||||
{
|
||||
//------------------------------------------------------------------------------
|
||||
/** \brief Test cases for unit testing.
|
||||
|
||||
(C) 2004-2011 Ingo Berg
|
||||
*/
|
||||
class ParserTester // final
|
||||
{
|
||||
private:
|
||||
static int c_iCount;
|
||||
|
||||
// Multiarg callbacks
|
||||
static value_type f1of1(value_type v) { return v;};
|
||||
|
||||
static value_type f1of2(value_type v, value_type ) {return v;};
|
||||
static value_type f2of2(value_type , value_type v) {return v;};
|
||||
|
||||
static value_type f1of3(value_type v, value_type , value_type ) {return v;};
|
||||
static value_type f2of3(value_type , value_type v, value_type ) {return v;};
|
||||
static value_type f3of3(value_type , value_type , value_type v) {return v;};
|
||||
|
||||
static value_type f1of4(value_type v, value_type, value_type , value_type ) {return v;}
|
||||
static value_type f2of4(value_type , value_type v, value_type , value_type ) {return v;}
|
||||
static value_type f3of4(value_type , value_type, value_type v, value_type ) {return v;}
|
||||
static value_type f4of4(value_type , value_type, value_type , value_type v) {return v;}
|
||||
|
||||
static value_type f1of5(value_type v, value_type, value_type , value_type , value_type ) { return v; }
|
||||
static value_type f2of5(value_type , value_type v, value_type , value_type , value_type ) { return v; }
|
||||
static value_type f3of5(value_type , value_type, value_type v, value_type , value_type ) { return v; }
|
||||
static value_type f4of5(value_type , value_type, value_type , value_type v, value_type ) { return v; }
|
||||
static value_type f5of5(value_type , value_type, value_type , value_type , value_type v) { return v; }
|
||||
|
||||
static value_type Min(value_type a_fVal1, value_type a_fVal2) { return (a_fVal1<a_fVal2) ? a_fVal1 : a_fVal2; }
|
||||
static value_type Max(value_type a_fVal1, value_type a_fVal2) { return (a_fVal1>a_fVal2) ? a_fVal1 : a_fVal2; }
|
||||
|
||||
static value_type plus2(value_type v1) { return v1+2; }
|
||||
static value_type times3(value_type v1) { return v1*3; }
|
||||
static value_type sqr(value_type v1) { return v1*v1; }
|
||||
static value_type sign(value_type v) { return -v; }
|
||||
static value_type add(value_type v1, value_type v2) { return v1+v2; }
|
||||
static value_type land(value_type v1, value_type v2) { return (int)v1 & (int)v2; }
|
||||
|
||||
|
||||
static value_type FirstArg(const value_type* a_afArg, int a_iArgc)
|
||||
{
|
||||
if (!a_iArgc)
|
||||
throw mu::Parser::exception_type( _T("too few arguments for function FirstArg.") );
|
||||
|
||||
return a_afArg[0];
|
||||
}
|
||||
|
||||
static value_type LastArg(const value_type* a_afArg, int a_iArgc)
|
||||
{
|
||||
if (!a_iArgc)
|
||||
throw mu::Parser::exception_type( _T("too few arguments for function LastArg.") );
|
||||
|
||||
return a_afArg[a_iArgc-1];
|
||||
}
|
||||
|
||||
static value_type Sum(const value_type* a_afArg, int a_iArgc)
|
||||
{
|
||||
if (!a_iArgc)
|
||||
throw mu::Parser::exception_type( _T("too few arguments for function sum.") );
|
||||
|
||||
value_type fRes=0;
|
||||
for (int i=0; i<a_iArgc; ++i) fRes += a_afArg[i];
|
||||
return fRes;
|
||||
}
|
||||
|
||||
static value_type Rnd(value_type v)
|
||||
{
|
||||
return (value_type)(1+(v*std::rand()/(RAND_MAX+1.0)));
|
||||
}
|
||||
|
||||
static value_type RndWithString(const char_type*)
|
||||
{
|
||||
return (value_type)( 1 + (1000.0f * std::rand() / (RAND_MAX + 1.0) ) );
|
||||
}
|
||||
|
||||
static value_type Ping()
|
||||
{
|
||||
return 10;
|
||||
}
|
||||
|
||||
static value_type ValueOf(const char_type*)
|
||||
{
|
||||
return 123;
|
||||
}
|
||||
|
||||
static value_type StrFun1(const char_type* v1)
|
||||
{
|
||||
int val(0);
|
||||
stringstream_type(v1) >> val;
|
||||
return (value_type)val;
|
||||
}
|
||||
|
||||
static value_type StrFun2(const char_type* v1, value_type v2)
|
||||
{
|
||||
int val(0);
|
||||
stringstream_type(v1) >> val;
|
||||
return (value_type)(val + v2);
|
||||
}
|
||||
|
||||
static value_type StrFun3(const char_type* v1, value_type v2, value_type v3)
|
||||
{
|
||||
int val(0);
|
||||
stringstream_type(v1) >> val;
|
||||
return val + v2 + v3;
|
||||
}
|
||||
|
||||
static value_type StrToFloat(const char_type* a_szMsg)
|
||||
{
|
||||
value_type val(0);
|
||||
stringstream_type(a_szMsg) >> val;
|
||||
return val;
|
||||
}
|
||||
|
||||
// postfix operator callback
|
||||
static value_type Mega(value_type a_fVal) { return a_fVal * (value_type)1e6; }
|
||||
static value_type Micro(value_type a_fVal) { return a_fVal * (value_type)1e-6; }
|
||||
static value_type Milli(value_type a_fVal) { return a_fVal / (value_type)1e3; }
|
||||
|
||||
// Custom value recognition
|
||||
static int IsHexVal(const char_type *a_szExpr, int *a_iPos, value_type *a_fVal);
|
||||
|
||||
int TestNames();
|
||||
int TestSyntax();
|
||||
int TestMultiArg();
|
||||
int TestPostFix();
|
||||
int TestExpression();
|
||||
int TestInfixOprt();
|
||||
int TestBinOprt();
|
||||
int TestVarConst();
|
||||
int TestInterface();
|
||||
int TestException();
|
||||
int TestStrArg();
|
||||
int TestIfThenElse();
|
||||
int TestBulkMode();
|
||||
|
||||
void Abort() const;
|
||||
|
||||
public:
|
||||
typedef int (ParserTester::*testfun_type)();
|
||||
|
||||
ParserTester();
|
||||
void Run();
|
||||
|
||||
private:
|
||||
std::vector<testfun_type> m_vTestFun;
|
||||
void AddTest(testfun_type a_pFun);
|
||||
|
||||
// Test Double Parser
|
||||
int EqnTest(const string_type& a_str, double a_fRes, bool a_fPass);
|
||||
int EqnTestWithVarChange(const string_type& a_str,
|
||||
double a_fRes1,
|
||||
double a_fVar1,
|
||||
double a_fRes2,
|
||||
double a_fVar2);
|
||||
int ThrowTest(const string_type& a_str, int a_iErrc, bool a_bFail = true);
|
||||
|
||||
// Test Int Parser
|
||||
int EqnTestInt(const string_type& a_str, double a_fRes, bool a_fPass);
|
||||
|
||||
// Test Bulkmode
|
||||
int EqnTestBulk(const string_type& a_str, double a_fRes[4], bool a_fPass);
|
||||
};
|
||||
} // namespace Test
|
||||
} // namespace mu
|
||||
|
||||
#endif
|
||||
|
||||
|
401
muparser-2.2.5_GR/include/muParserToken.h
Executable file
401
muparser-2.2.5_GR/include/muParserToken.h
Executable file
|
@ -0,0 +1,401 @@
|
|||
/*
|
||||
__________
|
||||
_____ __ __\______ \_____ _______ ______ ____ _______
|
||||
/ \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
|
||||
| Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
|
||||
|__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
|
||||
\/ \/ \/ \/
|
||||
Copyright (C) 2004-2013 Ingo Berg
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||
software and associated documentation files (the "Software"), to deal in the Software
|
||||
without restriction, including without limitation the rights to use, copy, modify,
|
||||
merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or
|
||||
substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
|
||||
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MU_PARSER_TOKEN_H
|
||||
#define MU_PARSER_TOKEN_H
|
||||
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
#include <stack>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
#include "muParserError.h"
|
||||
#include "muParserCallback.h"
|
||||
|
||||
/** \file
|
||||
\brief This file contains the parser token definition.
|
||||
*/
|
||||
|
||||
namespace mu
|
||||
{
|
||||
/** \brief Encapsulation of the data for a single formula token.
|
||||
|
||||
Formula token implementation. Part of the Math Parser Package.
|
||||
Formula tokens can be either one of the following:
|
||||
<ul>
|
||||
<li>value</li>
|
||||
<li>variable</li>
|
||||
<li>function with numerical arguments</li>
|
||||
<li>functions with a string as argument</li>
|
||||
<li>prefix operators</li>
|
||||
<li>infix operators</li>
|
||||
<li>binary operator</li>
|
||||
</ul>
|
||||
|
||||
\author (C) 2004-2013 Ingo Berg
|
||||
*/
|
||||
template<typename TBase, typename TString>
|
||||
class ParserToken
|
||||
{
|
||||
private:
|
||||
|
||||
ECmdCode m_iCode; ///< Type of the token; The token type is a constant of type #ECmdCode.
|
||||
ETypeCode m_iType;
|
||||
void *m_pTok; ///< Stores Token pointer; not applicable for all tokens
|
||||
int m_iIdx; ///< An otional index to an external buffer storing the token data
|
||||
TString m_strTok; ///< Token string
|
||||
TString m_strVal; ///< Value for string variables
|
||||
value_type m_fVal; ///< the value
|
||||
std::auto_ptr<ParserCallback> m_pCallback;
|
||||
|
||||
public:
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Constructor (default).
|
||||
|
||||
Sets token to an neutral state of type cmUNKNOWN.
|
||||
\throw nothrow
|
||||
\sa ECmdCode
|
||||
*/
|
||||
ParserToken()
|
||||
:m_iCode(cmUNKNOWN)
|
||||
,m_iType(tpVOID)
|
||||
,m_pTok(0)
|
||||
,m_iIdx(-1)
|
||||
,m_strTok()
|
||||
,m_strVal()
|
||||
,m_fVal(0)
|
||||
,m_pCallback()
|
||||
{}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/** \brief Create token from another one.
|
||||
|
||||
Implemented by calling Assign(...)
|
||||
\throw nothrow
|
||||
\post m_iType==cmUNKNOWN
|
||||
\sa #Assign
|
||||
*/
|
||||
ParserToken(const ParserToken &a_Tok)
|
||||
{
|
||||
Assign(a_Tok);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/** \brief Assignement operator.
|
||||
|
||||
Copy token state from another token and return this.
|
||||
Implemented by calling Assign(...).
|
||||
\throw nothrow
|
||||
*/
|
||||
ParserToken& operator=(const ParserToken &a_Tok)
|
||||
{
|
||||
Assign(a_Tok);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/** \brief Copy token information from argument.
|
||||
|
||||
\throw nothrow
|
||||
*/
|
||||
void Assign(const ParserToken &a_Tok)
|
||||
{
|
||||
m_iCode = a_Tok.m_iCode;
|
||||
m_pTok = a_Tok.m_pTok;
|
||||
m_strTok = a_Tok.m_strTok;
|
||||
m_iIdx = a_Tok.m_iIdx;
|
||||
m_strVal = a_Tok.m_strVal;
|
||||
m_iType = a_Tok.m_iType;
|
||||
m_fVal = a_Tok.m_fVal;
|
||||
// create new callback object if a_Tok has one
|
||||
m_pCallback.reset(a_Tok.m_pCallback.get() ? a_Tok.m_pCallback->Clone() : 0);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/** \brief Assign a token type.
|
||||
|
||||
Token may not be of type value, variable or function. Those have seperate set functions.
|
||||
|
||||
\pre [assert] a_iType!=cmVAR
|
||||
\pre [assert] a_iType!=cmVAL
|
||||
\pre [assert] a_iType!=cmFUNC
|
||||
\post m_fVal = 0
|
||||
\post m_pTok = 0
|
||||
*/
|
||||
ParserToken& Set(ECmdCode a_iType, const TString &a_strTok=TString())
|
||||
{
|
||||
// The following types cant be set this way, they have special Set functions
|
||||
assert(a_iType!=cmVAR);
|
||||
assert(a_iType!=cmVAL);
|
||||
assert(a_iType!=cmFUNC);
|
||||
|
||||
m_iCode = a_iType;
|
||||
m_iType = tpVOID;
|
||||
m_pTok = 0;
|
||||
m_strTok = a_strTok;
|
||||
m_iIdx = -1;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/** \brief Set Callback type. */
|
||||
ParserToken& Set(const ParserCallback &a_pCallback, const TString &a_sTok)
|
||||
{
|
||||
assert(a_pCallback.GetAddr());
|
||||
|
||||
m_iCode = a_pCallback.GetCode();
|
||||
m_iType = tpVOID;
|
||||
m_strTok = a_sTok;
|
||||
m_pCallback.reset(new ParserCallback(a_pCallback));
|
||||
|
||||
m_pTok = 0;
|
||||
m_iIdx = -1;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/** \brief Make this token a value token.
|
||||
|
||||
Member variables not necessary for value tokens will be invalidated.
|
||||
\throw nothrow
|
||||
*/
|
||||
ParserToken& SetVal(TBase a_fVal, const TString &a_strTok=TString())
|
||||
{
|
||||
m_iCode = cmVAL;
|
||||
m_iType = tpDBL;
|
||||
m_fVal = a_fVal;
|
||||
m_strTok = a_strTok;
|
||||
m_iIdx = -1;
|
||||
|
||||
m_pTok = 0;
|
||||
m_pCallback.reset(0);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/** \brief make this token a variable token.
|
||||
|
||||
Member variables not necessary for variable tokens will be invalidated.
|
||||
\throw nothrow
|
||||
*/
|
||||
ParserToken& SetVar(TBase *a_pVar, const TString &a_strTok)
|
||||
{
|
||||
m_iCode = cmVAR;
|
||||
m_iType = tpDBL;
|
||||
m_strTok = a_strTok;
|
||||
m_iIdx = -1;
|
||||
m_pTok = (void*)a_pVar;
|
||||
m_pCallback.reset(0);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/** \brief Make this token a variable token.
|
||||
|
||||
Member variables not necessary for variable tokens will be invalidated.
|
||||
\throw nothrow
|
||||
*/
|
||||
ParserToken& SetString(const TString &a_strTok, std::size_t a_iSize)
|
||||
{
|
||||
m_iCode = cmSTRING;
|
||||
m_iType = tpSTR;
|
||||
m_strTok = a_strTok;
|
||||
m_iIdx = static_cast<int>(a_iSize);
|
||||
|
||||
m_pTok = 0;
|
||||
m_pCallback.reset(0);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/** \brief Set an index associated with the token related data.
|
||||
|
||||
In cmSTRFUNC - This is the index to a string table in the main parser.
|
||||
\param a_iIdx The index the string function result will take in the bytecode parser.
|
||||
\throw exception_type if #a_iIdx<0 or #m_iType!=cmSTRING
|
||||
*/
|
||||
void SetIdx(int a_iIdx)
|
||||
{
|
||||
if (m_iCode!=cmSTRING || a_iIdx<0)
|
||||
throw ParserError(ecINTERNAL_ERROR);
|
||||
|
||||
m_iIdx = a_iIdx;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/** \brief Return Index associated with the token related data.
|
||||
|
||||
In cmSTRFUNC - This is the index to a string table in the main parser.
|
||||
|
||||
\throw exception_type if #m_iIdx<0 or #m_iType!=cmSTRING
|
||||
\return The index the result will take in the Bytecode calculatin array (#m_iIdx).
|
||||
*/
|
||||
int GetIdx() const
|
||||
{
|
||||
if (m_iIdx<0 || m_iCode!=cmSTRING )
|
||||
throw ParserError(ecINTERNAL_ERROR);
|
||||
|
||||
return m_iIdx;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/** \brief Return the token type.
|
||||
|
||||
\return #m_iType
|
||||
\throw nothrow
|
||||
*/
|
||||
ECmdCode GetCode() const
|
||||
{
|
||||
if (m_pCallback.get())
|
||||
{
|
||||
return m_pCallback->GetCode();
|
||||
}
|
||||
else
|
||||
{
|
||||
return m_iCode;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
ETypeCode GetType() const
|
||||
{
|
||||
if (m_pCallback.get())
|
||||
{
|
||||
return m_pCallback->GetType();
|
||||
}
|
||||
else
|
||||
{
|
||||
return m_iType;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
int GetPri() const
|
||||
{
|
||||
if ( !m_pCallback.get())
|
||||
throw ParserError(ecINTERNAL_ERROR);
|
||||
|
||||
if ( m_pCallback->GetCode()!=cmOPRT_BIN && m_pCallback->GetCode()!=cmOPRT_INFIX)
|
||||
throw ParserError(ecINTERNAL_ERROR);
|
||||
|
||||
return m_pCallback->GetPri();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
EOprtAssociativity GetAssociativity() const
|
||||
{
|
||||
if (m_pCallback.get()==NULL || m_pCallback->GetCode()!=cmOPRT_BIN)
|
||||
throw ParserError(ecINTERNAL_ERROR);
|
||||
|
||||
return m_pCallback->GetAssociativity();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/** \brief Return the address of the callback function assoziated with
|
||||
function and operator tokens.
|
||||
|
||||
\return The pointer stored in #m_pTok.
|
||||
\throw exception_type if token type is non of:
|
||||
<ul>
|
||||
<li>cmFUNC</li>
|
||||
<li>cmSTRFUNC</li>
|
||||
<li>cmPOSTOP</li>
|
||||
<li>cmINFIXOP</li>
|
||||
<li>cmOPRT_BIN</li>
|
||||
</ul>
|
||||
\sa ECmdCode
|
||||
*/
|
||||
generic_fun_type GetFuncAddr() const
|
||||
{
|
||||
return (m_pCallback.get()) ? (generic_fun_type)m_pCallback->GetAddr() : 0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/** \biref Get value of the token.
|
||||
|
||||
Only applicable to variable and value tokens.
|
||||
\throw exception_type if token is no value/variable token.
|
||||
*/
|
||||
TBase GetVal() const
|
||||
{
|
||||
switch (m_iCode)
|
||||
{
|
||||
case cmVAL: return m_fVal;
|
||||
case cmVAR: return *((TBase*)m_pTok);
|
||||
default: throw ParserError(ecVAL_EXPECTED);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/** \brief Get address of a variable token.
|
||||
|
||||
Valid only if m_iType==CmdVar.
|
||||
\throw exception_type if token is no variable token.
|
||||
*/
|
||||
TBase* GetVar() const
|
||||
{
|
||||
if (m_iCode!=cmVAR)
|
||||
throw ParserError(ecINTERNAL_ERROR);
|
||||
|
||||
return (TBase*)m_pTok;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/** \brief Return the number of function arguments.
|
||||
|
||||
Valid only if m_iType==CmdFUNC.
|
||||
*/
|
||||
int GetArgCount() const
|
||||
{
|
||||
assert(m_pCallback.get());
|
||||
|
||||
if (!m_pCallback->GetAddr())
|
||||
throw ParserError(ecINTERNAL_ERROR);
|
||||
|
||||
return m_pCallback->GetArgc();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/** \brief Return the token identifier.
|
||||
|
||||
If #m_iType is cmSTRING the token identifier is the value of the string argument
|
||||
for a string function.
|
||||
\return #m_strTok
|
||||
\throw nothrow
|
||||
\sa m_strTok
|
||||
*/
|
||||
const TString& GetAsString() const
|
||||
{
|
||||
return m_strTok;
|
||||
}
|
||||
};
|
||||
} // namespace mu
|
||||
|
||||
#endif
|
161
muparser-2.2.5_GR/include/muParserTokenReader.h
Executable file
161
muparser-2.2.5_GR/include/muParserTokenReader.h
Executable file
|
@ -0,0 +1,161 @@
|
|||
/*
|
||||
__________
|
||||
_____ __ __\______ \_____ _______ ______ ____ _______
|
||||
/ \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
|
||||
| Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
|
||||
|__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
|
||||
\/ \/ \/ \/
|
||||
Copyright (C) 2004-2013 Ingo Berg
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||
software and associated documentation files (the "Software"), to deal in the Software
|
||||
without restriction, including without limitation the rights to use, copy, modify,
|
||||
merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or
|
||||
substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
|
||||
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MU_PARSER_TOKEN_READER_H
|
||||
#define MU_PARSER_TOKEN_READER_H
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <stack>
|
||||
#include <string>
|
||||
|
||||
#include "muParserDef.h"
|
||||
#include "muParserToken.h"
|
||||
|
||||
/** \file
|
||||
\brief This file contains the parser token reader definition.
|
||||
*/
|
||||
|
||||
|
||||
namespace mu
|
||||
{
|
||||
// Forward declaration
|
||||
class ParserBase;
|
||||
|
||||
/** \brief Token reader for the ParserBase class.
|
||||
|
||||
*/
|
||||
class ParserTokenReader
|
||||
{
|
||||
private:
|
||||
|
||||
typedef ParserToken<value_type, string_type> token_type;
|
||||
|
||||
public:
|
||||
|
||||
ParserTokenReader(ParserBase *a_pParent);
|
||||
ParserTokenReader* Clone(ParserBase *a_pParent) const;
|
||||
|
||||
void AddValIdent(identfun_type a_pCallback);
|
||||
void SetVarCreator(facfun_type a_pFactory, void *pUserData);
|
||||
void SetFormula(const string_type &a_strFormula);
|
||||
void SetArgSep(char_type cArgSep);
|
||||
|
||||
int GetPos() const;
|
||||
const string_type& GetExpr() const;
|
||||
varmap_type& GetUsedVar();
|
||||
char_type GetArgSep() const;
|
||||
|
||||
void IgnoreUndefVar(bool bIgnore);
|
||||
void ReInit();
|
||||
token_type ReadNextToken();
|
||||
|
||||
private:
|
||||
|
||||
/** \brief Syntax codes.
|
||||
|
||||
The syntax codes control the syntax check done during the first time parsing of
|
||||
the expression string. They are flags that indicate which tokens are allowed next
|
||||
if certain tokens are identified.
|
||||
*/
|
||||
enum ESynCodes
|
||||
{
|
||||
noBO = 1 << 0, ///< to avoid i.e. "cos(7)("
|
||||
noBC = 1 << 1, ///< to avoid i.e. "sin)" or "()"
|
||||
noVAL = 1 << 2, ///< to avoid i.e. "tan 2" or "sin(8)3.14"
|
||||
noVAR = 1 << 3, ///< to avoid i.e. "sin a" or "sin(8)a"
|
||||
noARG_SEP = 1 << 4, ///< to avoid i.e. ",," or "+," ...
|
||||
noFUN = 1 << 5, ///< to avoid i.e. "sqrt cos" or "(1)sin"
|
||||
noOPT = 1 << 6, ///< to avoid i.e. "(+)"
|
||||
noPOSTOP = 1 << 7, ///< to avoid i.e. "(5!!)" "sin!"
|
||||
noINFIXOP = 1 << 8, ///< to avoid i.e. "++4" "!!4"
|
||||
noEND = 1 << 9, ///< to avoid unexpected end of formula
|
||||
noSTR = 1 << 10, ///< to block numeric arguments on string functions
|
||||
noASSIGN = 1 << 11, ///< to block assignement to constant i.e. "4=7"
|
||||
noIF = 1 << 12,
|
||||
noELSE = 1 << 13,
|
||||
sfSTART_OF_LINE = noOPT | noBC | noPOSTOP | noASSIGN | noIF | noELSE | noARG_SEP,
|
||||
noANY = ~0 ///< All of he above flags set
|
||||
};
|
||||
|
||||
ParserTokenReader(const ParserTokenReader &a_Reader);
|
||||
ParserTokenReader& operator=(const ParserTokenReader &a_Reader);
|
||||
void Assign(const ParserTokenReader &a_Reader);
|
||||
|
||||
void SetParent(ParserBase *a_pParent);
|
||||
int ExtractToken(const char_type *a_szCharSet,
|
||||
string_type &a_strTok,
|
||||
int a_iPos) const;
|
||||
int ExtractOperatorToken(string_type &a_sTok, int a_iPos) const;
|
||||
|
||||
bool IsBuiltIn(token_type &a_Tok);
|
||||
bool IsArgSep(token_type &a_Tok);
|
||||
bool IsEOF(token_type &a_Tok);
|
||||
bool IsInfixOpTok(token_type &a_Tok);
|
||||
bool IsFunTok(token_type &a_Tok);
|
||||
bool IsPostOpTok(token_type &a_Tok);
|
||||
bool IsOprt(token_type &a_Tok);
|
||||
bool IsValTok(token_type &a_Tok);
|
||||
bool IsVarTok(token_type &a_Tok);
|
||||
bool IsStrVarTok(token_type &a_Tok);
|
||||
bool IsUndefVarTok(token_type &a_Tok);
|
||||
bool IsString(token_type &a_Tok);
|
||||
void Error(EErrorCodes a_iErrc,
|
||||
int a_iPos = -1,
|
||||
const string_type &a_sTok = string_type() ) const;
|
||||
|
||||
token_type& SaveBeforeReturn(const token_type &tok);
|
||||
|
||||
ParserBase *m_pParser;
|
||||
string_type m_strFormula;
|
||||
int m_iPos;
|
||||
int m_iSynFlags;
|
||||
bool m_bIgnoreUndefVar;
|
||||
|
||||
const funmap_type *m_pFunDef;
|
||||
const funmap_type *m_pPostOprtDef;
|
||||
const funmap_type *m_pInfixOprtDef;
|
||||
const funmap_type *m_pOprtDef;
|
||||
const valmap_type *m_pConstDef;
|
||||
const strmap_type *m_pStrVarDef;
|
||||
varmap_type *m_pVarDef; ///< The only non const pointer to parser internals
|
||||
facfun_type m_pFactory;
|
||||
void *m_pFactoryData;
|
||||
std::list<identfun_type> m_vIdentFun; ///< Value token identification function
|
||||
varmap_type m_UsedVar;
|
||||
value_type m_fZero; ///< Dummy value of zero, referenced by undefined variables
|
||||
int m_iBrackets;
|
||||
token_type m_lastTok;
|
||||
char_type m_cArgSep; ///< The character used for separating function arguments
|
||||
};
|
||||
} // namespace mu
|
||||
|
||||
#endif
|
||||
|
||||
|
397
muparser-2.2.5_GR/src/muParser.cc
Executable file
397
muparser-2.2.5_GR/src/muParser.cc
Executable file
|
@ -0,0 +1,397 @@
|
|||
/*
|
||||
__________
|
||||
_____ __ __\______ \_____ _______ ______ ____ _______
|
||||
/ \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
|
||||
| Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
|
||||
|__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
|
||||
\/ \/ \/ \/
|
||||
|
||||
Copyright (C) 2013 Ingo Berg
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||
software and associated documentation files (the "Software"), to deal in the Software
|
||||
without restriction, including without limitation the rights to use, copy, modify,
|
||||
merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or
|
||||
substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
|
||||
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include "muParser.h"
|
||||
#include "muParserTemplateMagic.h"
|
||||
|
||||
//--- Standard includes ------------------------------------------------------------------------
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
#include <numeric>
|
||||
|
||||
/** \brief Pi (what else?). */
|
||||
#define PARSER_CONST_PI 3.141592653589793238462643
|
||||
|
||||
/** \brief The Eulerian number. */
|
||||
#define PARSER_CONST_E 2.718281828459045235360287
|
||||
|
||||
using namespace std;
|
||||
|
||||
/** \file
|
||||
\brief Implementation of the standard floating point parser.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/** \brief Namespace for mathematical applications. */
|
||||
namespace mu
|
||||
{
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Trigonometric function
|
||||
value_type Parser::Sin(value_type v) { return MathImpl<value_type>::Sin(v); }
|
||||
value_type Parser::Cos(value_type v) { return MathImpl<value_type>::Cos(v); }
|
||||
value_type Parser::Tan(value_type v) { return MathImpl<value_type>::Tan(v); }
|
||||
value_type Parser::ASin(value_type v) { return MathImpl<value_type>::ASin(v); }
|
||||
value_type Parser::ACos(value_type v) { return MathImpl<value_type>::ACos(v); }
|
||||
value_type Parser::ATan(value_type v) { return MathImpl<value_type>::ATan(v); }
|
||||
value_type Parser::ATan2(value_type v1, value_type v2) { return MathImpl<value_type>::ATan2(v1, v2); }
|
||||
value_type Parser::Sinh(value_type v) { return MathImpl<value_type>::Sinh(v); }
|
||||
value_type Parser::Cosh(value_type v) { return MathImpl<value_type>::Cosh(v); }
|
||||
value_type Parser::Tanh(value_type v) { return MathImpl<value_type>::Tanh(v); }
|
||||
value_type Parser::ASinh(value_type v) { return MathImpl<value_type>::ASinh(v); }
|
||||
value_type Parser::ACosh(value_type v) { return MathImpl<value_type>::ACosh(v); }
|
||||
value_type Parser::ATanh(value_type v) { return MathImpl<value_type>::ATanh(v); }
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Logarithm functions
|
||||
|
||||
// Logarithm base 2
|
||||
value_type Parser::Log2(value_type v)
|
||||
{
|
||||
#ifdef MUP_MATH_EXCEPTIONS
|
||||
if (v<=0)
|
||||
throw ParserError(ecDOMAIN_ERROR, _T("Log2"));
|
||||
#endif
|
||||
|
||||
return MathImpl<value_type>::Log2(v);
|
||||
}
|
||||
|
||||
// Logarithm base 10
|
||||
value_type Parser::Log10(value_type v)
|
||||
{
|
||||
#ifdef MUP_MATH_EXCEPTIONS
|
||||
if (v<=0)
|
||||
throw ParserError(ecDOMAIN_ERROR, _T("Log10"));
|
||||
#endif
|
||||
|
||||
return MathImpl<value_type>::Log10(v);
|
||||
}
|
||||
|
||||
// Logarithm base e (natural logarithm)
|
||||
value_type Parser::Ln(value_type v)
|
||||
{
|
||||
#ifdef MUP_MATH_EXCEPTIONS
|
||||
if (v<=0)
|
||||
throw ParserError(ecDOMAIN_ERROR, _T("Ln"));
|
||||
#endif
|
||||
|
||||
return MathImpl<value_type>::Log(v);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// misc
|
||||
value_type Parser::Exp(value_type v) { return MathImpl<value_type>::Exp(v); }
|
||||
value_type Parser::Abs(value_type v) { return MathImpl<value_type>::Abs(v); }
|
||||
value_type Parser::Sqrt(value_type v)
|
||||
{
|
||||
#ifdef MUP_MATH_EXCEPTIONS
|
||||
if (v<0)
|
||||
throw ParserError(ecDOMAIN_ERROR, _T("sqrt"));
|
||||
#endif
|
||||
|
||||
return MathImpl<value_type>::Sqrt(v);
|
||||
}
|
||||
value_type Parser::Rint(value_type v) { return MathImpl<value_type>::Rint(v); }
|
||||
value_type Parser::Sign(value_type v) { return MathImpl<value_type>::Sign(v); }
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Callback for the unary minus operator.
|
||||
\param v The value to negate
|
||||
\return -v
|
||||
*/
|
||||
value_type Parser::UnaryMinus(value_type v)
|
||||
{
|
||||
return -v;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Callback for the unary minus operator.
|
||||
\param v The value to negate
|
||||
\return -v
|
||||
*/
|
||||
value_type Parser::UnaryPlus(value_type v)
|
||||
{
|
||||
return v;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Callback for adding multiple values.
|
||||
\param [in] a_afArg Vector with the function arguments
|
||||
\param [in] a_iArgc The size of a_afArg
|
||||
*/
|
||||
value_type Parser::Sum(const value_type *a_afArg, int a_iArgc)
|
||||
{
|
||||
if (!a_iArgc)
|
||||
throw exception_type(_T("too few arguments for function sum."));
|
||||
|
||||
value_type fRes=0;
|
||||
for (int i=0; i<a_iArgc; ++i) fRes += a_afArg[i];
|
||||
return fRes;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Callback for averaging multiple values.
|
||||
\param [in] a_afArg Vector with the function arguments
|
||||
\param [in] a_iArgc The size of a_afArg
|
||||
*/
|
||||
value_type Parser::Avg(const value_type *a_afArg, int a_iArgc)
|
||||
{
|
||||
if (!a_iArgc)
|
||||
throw exception_type(_T("too few arguments for function sum."));
|
||||
|
||||
value_type fRes=0;
|
||||
for (int i=0; i<a_iArgc; ++i) fRes += a_afArg[i];
|
||||
return fRes/(value_type)a_iArgc;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Callback for determining the minimum value out of a vector.
|
||||
\param [in] a_afArg Vector with the function arguments
|
||||
\param [in] a_iArgc The size of a_afArg
|
||||
*/
|
||||
value_type Parser::Min(const value_type *a_afArg, int a_iArgc)
|
||||
{
|
||||
if (!a_iArgc)
|
||||
throw exception_type(_T("too few arguments for function min."));
|
||||
|
||||
value_type fRes=a_afArg[0];
|
||||
for (int i=0; i<a_iArgc; ++i)
|
||||
fRes = std::min(fRes, a_afArg[i]);
|
||||
|
||||
return fRes;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Callback for determining the maximum value out of a vector.
|
||||
\param [in] a_afArg Vector with the function arguments
|
||||
\param [in] a_iArgc The size of a_afArg
|
||||
*/
|
||||
value_type Parser::Max(const value_type *a_afArg, int a_iArgc)
|
||||
{
|
||||
if (!a_iArgc)
|
||||
throw exception_type(_T("too few arguments for function min."));
|
||||
|
||||
value_type fRes=a_afArg[0];
|
||||
for (int i=0; i<a_iArgc; ++i) fRes = std::max(fRes, a_afArg[i]);
|
||||
|
||||
return fRes;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Default value recognition callback.
|
||||
\param [in] a_szExpr Pointer to the expression
|
||||
\param [in, out] a_iPos Pointer to an index storing the current position within the expression
|
||||
\param [out] a_fVal Pointer where the value should be stored in case one is found.
|
||||
\return 1 if a value was found 0 otherwise.
|
||||
*/
|
||||
int Parser::IsVal(const char_type* a_szExpr, int *a_iPos, value_type *a_fVal)
|
||||
{
|
||||
value_type fVal(0);
|
||||
|
||||
stringstream_type stream(a_szExpr);
|
||||
stream.seekg(0); // todo: check if this really is necessary
|
||||
stream.imbue(Parser::s_locale);
|
||||
stream >> fVal;
|
||||
stringstream_type::pos_type iEnd = stream.tellg(); // Position after reading
|
||||
|
||||
if (iEnd==(stringstream_type::pos_type)-1)
|
||||
return 0;
|
||||
|
||||
*a_iPos += (int)iEnd;
|
||||
*a_fVal = fVal;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Constructor.
|
||||
|
||||
Call ParserBase class constructor and trigger Function, Operator and Constant initialization.
|
||||
*/
|
||||
Parser::Parser()
|
||||
:ParserBase()
|
||||
{
|
||||
AddValIdent(IsVal);
|
||||
|
||||
InitCharSets();
|
||||
InitFun();
|
||||
InitConst();
|
||||
InitOprt();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Define the character sets.
|
||||
\sa DefineNameChars, DefineOprtChars, DefineInfixOprtChars
|
||||
|
||||
This function is used for initializing the default character sets that define
|
||||
the characters to be useable in function and variable names and operators.
|
||||
*/
|
||||
void Parser::InitCharSets()
|
||||
{
|
||||
DefineNameChars( _T("0123456789_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") );
|
||||
DefineOprtChars( _T("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+-*^/?<>=#!$%&|~'_{}") );
|
||||
DefineInfixOprtChars( _T("/+-*^?<>=#!$%&|~'_") );
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Initialize the default functions. */
|
||||
void Parser::InitFun()
|
||||
{
|
||||
if (mu::TypeInfo<mu::value_type>::IsInteger())
|
||||
{
|
||||
// When setting MUP_BASETYPE to an integer type
|
||||
// Place functions for dealing with integer values here
|
||||
// ...
|
||||
// ...
|
||||
// ...
|
||||
}
|
||||
else
|
||||
{
|
||||
// trigonometric functions
|
||||
DefineFun(_T("sin"), Sin);
|
||||
DefineFun(_T("cos"), Cos);
|
||||
DefineFun(_T("tan"), Tan);
|
||||
// arcus functions
|
||||
DefineFun(_T("asin"), ASin);
|
||||
DefineFun(_T("acos"), ACos);
|
||||
DefineFun(_T("atan"), ATan);
|
||||
DefineFun(_T("atan2"), ATan2);
|
||||
// hyperbolic functions
|
||||
DefineFun(_T("sinh"), Sinh);
|
||||
DefineFun(_T("cosh"), Cosh);
|
||||
DefineFun(_T("tanh"), Tanh);
|
||||
// arcus hyperbolic functions
|
||||
DefineFun(_T("asinh"), ASinh);
|
||||
DefineFun(_T("acosh"), ACosh);
|
||||
DefineFun(_T("atanh"), ATanh);
|
||||
// Logarithm functions
|
||||
DefineFun(_T("log2"), Log2);
|
||||
DefineFun(_T("log10"), Log10);
|
||||
DefineFun(_T("log"), Ln);
|
||||
DefineFun(_T("ln"), Ln);
|
||||
// misc
|
||||
DefineFun(_T("exp"), Exp);
|
||||
DefineFun(_T("sqrt"), Sqrt);
|
||||
DefineFun(_T("sign"), Sign);
|
||||
DefineFun(_T("rint"), Rint);
|
||||
DefineFun(_T("abs"), Abs);
|
||||
// Functions with variable number of arguments
|
||||
DefineFun(_T("sum"), Sum);
|
||||
DefineFun(_T("avg"), Avg);
|
||||
DefineFun(_T("min"), Min);
|
||||
DefineFun(_T("max"), Max);
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Initialize constants.
|
||||
|
||||
By default the parser recognizes two constants. Pi ("pi") and the Eulerian
|
||||
number ("_e").
|
||||
*/
|
||||
void Parser::InitConst()
|
||||
{
|
||||
DefineConst(_T("_pi"), (value_type)PARSER_CONST_PI);
|
||||
DefineConst(_T("_e"), (value_type)PARSER_CONST_E);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Initialize operators.
|
||||
|
||||
By default only the unary minus operator is added.
|
||||
*/
|
||||
void Parser::InitOprt()
|
||||
{
|
||||
DefineInfixOprt(_T("-"), UnaryMinus);
|
||||
DefineInfixOprt(_T("+"), UnaryPlus);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
void Parser::OnDetectVar(string_type * /*pExpr*/, int & /*nStart*/, int & /*nEnd*/)
|
||||
{
|
||||
// this is just sample code to illustrate modifying variable names on the fly.
|
||||
// I'm not sure anyone really needs such a feature...
|
||||
/*
|
||||
|
||||
|
||||
string sVar(pExpr->begin()+nStart, pExpr->begin()+nEnd);
|
||||
string sRepl = std::string("_") + sVar + "_";
|
||||
|
||||
int nOrigVarEnd = nEnd;
|
||||
cout << "variable detected!\n";
|
||||
cout << " Expr: " << *pExpr << "\n";
|
||||
cout << " Start: " << nStart << "\n";
|
||||
cout << " End: " << nEnd << "\n";
|
||||
cout << " Var: \"" << sVar << "\"\n";
|
||||
cout << " Repl: \"" << sRepl << "\"\n";
|
||||
nEnd = nStart + sRepl.length();
|
||||
cout << " End: " << nEnd << "\n";
|
||||
pExpr->replace(pExpr->begin()+nStart, pExpr->begin()+nOrigVarEnd, sRepl);
|
||||
cout << " New expr: " << *pExpr << "\n";
|
||||
*/
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Numerically differentiate with regard to a variable.
|
||||
\param [in] a_Var Pointer to the differentiation variable.
|
||||
\param [in] a_fPos Position at which the differentiation should take place.
|
||||
\param [in] a_fEpsilon Epsilon used for the numerical differentiation.
|
||||
|
||||
Numerical differentiation uses a 5 point operator yielding a 4th order
|
||||
formula. The default value for epsilon is 0.00074 which is
|
||||
numeric_limits<double>::epsilon() ^ (1/5) as suggested in the muparser
|
||||
forum:
|
||||
|
||||
http://sourceforge.net/forum/forum.php?thread_id=1994611&forum_id=462843
|
||||
*/
|
||||
value_type Parser::Diff(value_type *a_Var,
|
||||
value_type a_fPos,
|
||||
value_type a_fEpsilon) const
|
||||
{
|
||||
value_type fRes(0),
|
||||
fBuf(*a_Var),
|
||||
f[4] = {0,0,0,0},
|
||||
fEpsilon(a_fEpsilon);
|
||||
|
||||
// Backwards compatible calculation of epsilon inc case the user doesn't provide
|
||||
// his own epsilon
|
||||
if (fEpsilon==0)
|
||||
fEpsilon = (a_fPos==0) ? (value_type)1e-10 : (value_type)1e-7 * a_fPos;
|
||||
|
||||
*a_Var = a_fPos+2 * fEpsilon; f[0] = Eval();
|
||||
*a_Var = a_fPos+1 * fEpsilon; f[1] = Eval();
|
||||
*a_Var = a_fPos-1 * fEpsilon; f[2] = Eval();
|
||||
*a_Var = a_fPos-2 * fEpsilon; f[3] = Eval();
|
||||
*a_Var = fBuf; // restore variable
|
||||
|
||||
fRes = (-f[0] + 8*f[1] - 8*f[2] + f[3]) / (12*fEpsilon);
|
||||
return fRes;
|
||||
}
|
||||
} // namespace mu
|
1778
muparser-2.2.5_GR/src/muParserBase.cc
Executable file
1778
muparser-2.2.5_GR/src/muParserBase.cc
Executable file
File diff suppressed because it is too large
Load diff
588
muparser-2.2.5_GR/src/muParserBytecode.cc
Executable file
588
muparser-2.2.5_GR/src/muParserBytecode.cc
Executable file
|
@ -0,0 +1,588 @@
|
|||
/*
|
||||
__________
|
||||
_____ __ __\______ \_____ _______ ______ ____ _______
|
||||
/ \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
|
||||
| Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
|
||||
|__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
|
||||
\/ \/ \/ \/
|
||||
Copyright (C) 2011 Ingo Berg
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||
software and associated documentation files (the "Software"), to deal in the Software
|
||||
without restriction, including without limitation the rights to use, copy, modify,
|
||||
merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or
|
||||
substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
|
||||
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "muParserBytecode.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
#include <stack>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
|
||||
#include "muParserDef.h"
|
||||
#include "muParserError.h"
|
||||
#include "muParserToken.h"
|
||||
#include "muParserStack.h"
|
||||
#include "muParserTemplateMagic.h"
|
||||
|
||||
|
||||
namespace mu
|
||||
{
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Bytecode default constructor. */
|
||||
ParserByteCode::ParserByteCode()
|
||||
:m_iStackPos(0)
|
||||
,m_iMaxStackSize(0)
|
||||
,m_vRPN()
|
||||
,m_bEnableOptimizer(true)
|
||||
{
|
||||
m_vRPN.reserve(50);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Copy constructor.
|
||||
|
||||
Implemented in Terms of Assign(const ParserByteCode &a_ByteCode)
|
||||
*/
|
||||
ParserByteCode::ParserByteCode(const ParserByteCode &a_ByteCode)
|
||||
{
|
||||
Assign(a_ByteCode);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Assignment operator.
|
||||
|
||||
Implemented in Terms of Assign(const ParserByteCode &a_ByteCode)
|
||||
*/
|
||||
ParserByteCode& ParserByteCode::operator=(const ParserByteCode &a_ByteCode)
|
||||
{
|
||||
Assign(a_ByteCode);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
void ParserByteCode::EnableOptimizer(bool bStat)
|
||||
{
|
||||
m_bEnableOptimizer = bStat;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Copy state of another object to this.
|
||||
|
||||
\throw nowthrow
|
||||
*/
|
||||
void ParserByteCode::Assign(const ParserByteCode &a_ByteCode)
|
||||
{
|
||||
if (this==&a_ByteCode)
|
||||
return;
|
||||
|
||||
m_iStackPos = a_ByteCode.m_iStackPos;
|
||||
m_vRPN = a_ByteCode.m_vRPN;
|
||||
m_iMaxStackSize = a_ByteCode.m_iMaxStackSize;
|
||||
m_bEnableOptimizer = a_ByteCode.m_bEnableOptimizer;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Add a Variable pointer to bytecode.
|
||||
\param a_pVar Pointer to be added.
|
||||
\throw nothrow
|
||||
*/
|
||||
void ParserByteCode::AddVar(value_type *a_pVar)
|
||||
{
|
||||
++m_iStackPos;
|
||||
m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos);
|
||||
|
||||
// optimization does not apply
|
||||
SToken tok;
|
||||
tok.Cmd = cmVAR;
|
||||
tok.Val.ptr = a_pVar;
|
||||
tok.Val.data = 1;
|
||||
tok.Val.data2 = 0;
|
||||
m_vRPN.push_back(tok);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Add a Variable pointer to bytecode.
|
||||
|
||||
Value entries in byte code consist of:
|
||||
<ul>
|
||||
<li>value array position of the value</li>
|
||||
<li>the operator code according to ParserToken::cmVAL</li>
|
||||
<li>the value stored in #mc_iSizeVal number of bytecode entries.</li>
|
||||
</ul>
|
||||
|
||||
\param a_pVal Value to be added.
|
||||
\throw nothrow
|
||||
*/
|
||||
void ParserByteCode::AddVal(value_type a_fVal)
|
||||
{
|
||||
++m_iStackPos;
|
||||
m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos);
|
||||
|
||||
// If optimization does not apply
|
||||
SToken tok;
|
||||
tok.Cmd = cmVAL;
|
||||
tok.Val.ptr = NULL;
|
||||
tok.Val.data = 0;
|
||||
tok.Val.data2 = a_fVal;
|
||||
m_vRPN.push_back(tok);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
void ParserByteCode::ConstantFolding(ECmdCode a_Oprt)
|
||||
{
|
||||
std::size_t sz = m_vRPN.size();
|
||||
value_type &x = m_vRPN[sz-2].Val.data2,
|
||||
&y = m_vRPN[sz-1].Val.data2;
|
||||
switch (a_Oprt)
|
||||
{
|
||||
case cmLAND: x = (int)x && (int)y; m_vRPN.pop_back(); break;
|
||||
case cmLOR: x = (int)x || (int)y; m_vRPN.pop_back(); break;
|
||||
case cmLT: x = x < y; m_vRPN.pop_back(); break;
|
||||
case cmGT: x = x > y; m_vRPN.pop_back(); break;
|
||||
case cmLE: x = x <= y; m_vRPN.pop_back(); break;
|
||||
case cmGE: x = x >= y; m_vRPN.pop_back(); break;
|
||||
case cmNEQ: x = x != y; m_vRPN.pop_back(); break;
|
||||
case cmEQ: x = x == y; m_vRPN.pop_back(); break;
|
||||
case cmADD: x = x + y; m_vRPN.pop_back(); break;
|
||||
case cmSUB: x = x - y; m_vRPN.pop_back(); break;
|
||||
case cmMUL: x = x * y; m_vRPN.pop_back(); break;
|
||||
case cmDIV:
|
||||
|
||||
#if defined(MUP_MATH_EXCEPTIONS)
|
||||
if (y==0)
|
||||
throw ParserError(ecDIV_BY_ZERO, _T("0"));
|
||||
#endif
|
||||
|
||||
x = x / y;
|
||||
m_vRPN.pop_back();
|
||||
break;
|
||||
|
||||
case cmPOW: x = MathImpl<value_type>::Pow(x, y);
|
||||
m_vRPN.pop_back();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
} // switch opcode
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Add an operator identifier to bytecode.
|
||||
|
||||
Operator entries in byte code consist of:
|
||||
<ul>
|
||||
<li>value array position of the result</li>
|
||||
<li>the operator code according to ParserToken::ECmdCode</li>
|
||||
</ul>
|
||||
|
||||
\sa ParserToken::ECmdCode
|
||||
*/
|
||||
void ParserByteCode::AddOp(ECmdCode a_Oprt)
|
||||
{
|
||||
bool bOptimized = false;
|
||||
|
||||
if (m_bEnableOptimizer)
|
||||
{
|
||||
std::size_t sz = m_vRPN.size();
|
||||
|
||||
// Check for foldable constants like:
|
||||
// cmVAL cmVAL cmADD
|
||||
// where cmADD can stand fopr any binary operator applied to
|
||||
// two constant values.
|
||||
if (sz>=2 && m_vRPN[sz-2].Cmd == cmVAL && m_vRPN[sz-1].Cmd == cmVAL)
|
||||
{
|
||||
ConstantFolding(a_Oprt);
|
||||
bOptimized = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(a_Oprt)
|
||||
{
|
||||
case cmPOW:
|
||||
// Optimization for polynomials of low order
|
||||
if (m_vRPN[sz-2].Cmd == cmVAR && m_vRPN[sz-1].Cmd == cmVAL)
|
||||
{
|
||||
if (m_vRPN[sz-1].Val.data2==2)
|
||||
m_vRPN[sz-2].Cmd = cmVARPOW2;
|
||||
else if (m_vRPN[sz-1].Val.data2==3)
|
||||
m_vRPN[sz-2].Cmd = cmVARPOW3;
|
||||
else if (m_vRPN[sz-1].Val.data2==4)
|
||||
m_vRPN[sz-2].Cmd = cmVARPOW4;
|
||||
else
|
||||
break;
|
||||
|
||||
m_vRPN.pop_back();
|
||||
bOptimized = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case cmSUB:
|
||||
case cmADD:
|
||||
// Simple optimization based on pattern recognition for a shitload of different
|
||||
// bytecode combinations of addition/subtraction
|
||||
if ( (m_vRPN[sz-1].Cmd == cmVAR && m_vRPN[sz-2].Cmd == cmVAL) ||
|
||||
(m_vRPN[sz-1].Cmd == cmVAL && m_vRPN[sz-2].Cmd == cmVAR) ||
|
||||
(m_vRPN[sz-1].Cmd == cmVAL && m_vRPN[sz-2].Cmd == cmVARMUL) ||
|
||||
(m_vRPN[sz-1].Cmd == cmVARMUL && m_vRPN[sz-2].Cmd == cmVAL) ||
|
||||
(m_vRPN[sz-1].Cmd == cmVAR && m_vRPN[sz-2].Cmd == cmVAR && m_vRPN[sz-2].Val.ptr == m_vRPN[sz-1].Val.ptr) ||
|
||||
(m_vRPN[sz-1].Cmd == cmVAR && m_vRPN[sz-2].Cmd == cmVARMUL && m_vRPN[sz-2].Val.ptr == m_vRPN[sz-1].Val.ptr) ||
|
||||
(m_vRPN[sz-1].Cmd == cmVARMUL && m_vRPN[sz-2].Cmd == cmVAR && m_vRPN[sz-2].Val.ptr == m_vRPN[sz-1].Val.ptr) ||
|
||||
(m_vRPN[sz-1].Cmd == cmVARMUL && m_vRPN[sz-2].Cmd == cmVARMUL && m_vRPN[sz-2].Val.ptr == m_vRPN[sz-1].Val.ptr) )
|
||||
{
|
||||
assert( (m_vRPN[sz-2].Val.ptr==NULL && m_vRPN[sz-1].Val.ptr!=NULL) ||
|
||||
(m_vRPN[sz-2].Val.ptr!=NULL && m_vRPN[sz-1].Val.ptr==NULL) ||
|
||||
(m_vRPN[sz-2].Val.ptr == m_vRPN[sz-1].Val.ptr) );
|
||||
|
||||
m_vRPN[sz-2].Cmd = cmVARMUL;
|
||||
m_vRPN[sz-2].Val.ptr = (value_type*)((long long)(m_vRPN[sz-2].Val.ptr) | (long long)(m_vRPN[sz-1].Val.ptr)); // variable
|
||||
m_vRPN[sz-2].Val.data2 += ((a_Oprt==cmSUB) ? -1 : 1) * m_vRPN[sz-1].Val.data2; // offset
|
||||
m_vRPN[sz-2].Val.data += ((a_Oprt==cmSUB) ? -1 : 1) * m_vRPN[sz-1].Val.data; // multiplicand
|
||||
m_vRPN.pop_back();
|
||||
bOptimized = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case cmMUL:
|
||||
if ( (m_vRPN[sz-1].Cmd == cmVAR && m_vRPN[sz-2].Cmd == cmVAL) ||
|
||||
(m_vRPN[sz-1].Cmd == cmVAL && m_vRPN[sz-2].Cmd == cmVAR) )
|
||||
{
|
||||
m_vRPN[sz-2].Cmd = cmVARMUL;
|
||||
m_vRPN[sz-2].Val.ptr = (value_type*)((long long)(m_vRPN[sz-2].Val.ptr) | (long long)(m_vRPN[sz-1].Val.ptr));
|
||||
m_vRPN[sz-2].Val.data = m_vRPN[sz-2].Val.data2 + m_vRPN[sz-1].Val.data2;
|
||||
m_vRPN[sz-2].Val.data2 = 0;
|
||||
m_vRPN.pop_back();
|
||||
bOptimized = true;
|
||||
}
|
||||
else if ( (m_vRPN[sz-1].Cmd == cmVAL && m_vRPN[sz-2].Cmd == cmVARMUL) ||
|
||||
(m_vRPN[sz-1].Cmd == cmVARMUL && m_vRPN[sz-2].Cmd == cmVAL) )
|
||||
{
|
||||
// Optimization: 2*(3*b+1) or (3*b+1)*2 -> 6*b+2
|
||||
m_vRPN[sz-2].Cmd = cmVARMUL;
|
||||
m_vRPN[sz-2].Val.ptr = (value_type*)((long long)(m_vRPN[sz-2].Val.ptr) | (long long)(m_vRPN[sz-1].Val.ptr));
|
||||
if (m_vRPN[sz-1].Cmd == cmVAL)
|
||||
{
|
||||
m_vRPN[sz-2].Val.data *= m_vRPN[sz-1].Val.data2;
|
||||
m_vRPN[sz-2].Val.data2 *= m_vRPN[sz-1].Val.data2;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_vRPN[sz-2].Val.data = m_vRPN[sz-1].Val.data * m_vRPN[sz-2].Val.data2;
|
||||
m_vRPN[sz-2].Val.data2 = m_vRPN[sz-1].Val.data2 * m_vRPN[sz-2].Val.data2;
|
||||
}
|
||||
m_vRPN.pop_back();
|
||||
bOptimized = true;
|
||||
}
|
||||
else if (m_vRPN[sz-1].Cmd == cmVAR && m_vRPN[sz-2].Cmd == cmVAR &&
|
||||
m_vRPN[sz-1].Val.ptr == m_vRPN[sz-2].Val.ptr)
|
||||
{
|
||||
// Optimization: a*a -> a^2
|
||||
m_vRPN[sz-2].Cmd = cmVARPOW2;
|
||||
m_vRPN.pop_back();
|
||||
bOptimized = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case cmDIV:
|
||||
if (m_vRPN[sz-1].Cmd == cmVAL && m_vRPN[sz-2].Cmd == cmVARMUL && m_vRPN[sz-1].Val.data2!=0)
|
||||
{
|
||||
// Optimization: 4*a/2 -> 2*a
|
||||
m_vRPN[sz-2].Val.data /= m_vRPN[sz-1].Val.data2;
|
||||
m_vRPN[sz-2].Val.data2 /= m_vRPN[sz-1].Val.data2;
|
||||
m_vRPN.pop_back();
|
||||
bOptimized = true;
|
||||
}
|
||||
break;
|
||||
|
||||
} // switch a_Oprt
|
||||
}
|
||||
}
|
||||
|
||||
// If optimization can't be applied just write the value
|
||||
if (!bOptimized)
|
||||
{
|
||||
--m_iStackPos;
|
||||
SToken tok;
|
||||
tok.Cmd = a_Oprt;
|
||||
m_vRPN.push_back(tok);
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
void ParserByteCode::AddIfElse(ECmdCode a_Oprt)
|
||||
{
|
||||
SToken tok;
|
||||
tok.Cmd = a_Oprt;
|
||||
m_vRPN.push_back(tok);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Add an assignment operator
|
||||
|
||||
Operator entries in byte code consist of:
|
||||
<ul>
|
||||
<li>cmASSIGN code</li>
|
||||
<li>the pointer of the destination variable</li>
|
||||
</ul>
|
||||
|
||||
\sa ParserToken::ECmdCode
|
||||
*/
|
||||
void ParserByteCode::AddAssignOp(value_type *a_pVar)
|
||||
{
|
||||
--m_iStackPos;
|
||||
|
||||
SToken tok;
|
||||
tok.Cmd = cmASSIGN;
|
||||
tok.Oprt.ptr = a_pVar;
|
||||
m_vRPN.push_back(tok);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Add function to bytecode.
|
||||
|
||||
\param a_iArgc Number of arguments, negative numbers indicate multiarg functions.
|
||||
\param a_pFun Pointer to function callback.
|
||||
*/
|
||||
void ParserByteCode::AddFun(generic_fun_type a_pFun, int a_iArgc)
|
||||
{
|
||||
if (a_iArgc>=0)
|
||||
{
|
||||
m_iStackPos = m_iStackPos - a_iArgc + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// function with unlimited number of arguments
|
||||
m_iStackPos = m_iStackPos + a_iArgc + 1;
|
||||
}
|
||||
m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos);
|
||||
|
||||
SToken tok;
|
||||
tok.Cmd = cmFUNC;
|
||||
tok.Fun.argc = a_iArgc;
|
||||
tok.Fun.ptr = a_pFun;
|
||||
m_vRPN.push_back(tok);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Add a bulk function to bytecode.
|
||||
|
||||
\param a_iArgc Number of arguments, negative numbers indicate multiarg functions.
|
||||
\param a_pFun Pointer to function callback.
|
||||
*/
|
||||
void ParserByteCode::AddBulkFun(generic_fun_type a_pFun, int a_iArgc)
|
||||
{
|
||||
m_iStackPos = m_iStackPos - a_iArgc + 1;
|
||||
m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos);
|
||||
|
||||
SToken tok;
|
||||
tok.Cmd = cmFUNC_BULK;
|
||||
tok.Fun.argc = a_iArgc;
|
||||
tok.Fun.ptr = a_pFun;
|
||||
m_vRPN.push_back(tok);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Add Strung function entry to the parser bytecode.
|
||||
\throw nothrow
|
||||
|
||||
A string function entry consists of the stack position of the return value,
|
||||
followed by a cmSTRFUNC code, the function pointer and an index into the
|
||||
string buffer maintained by the parser.
|
||||
*/
|
||||
void ParserByteCode::AddStrFun(generic_fun_type a_pFun, int a_iArgc, int a_iIdx)
|
||||
{
|
||||
m_iStackPos = m_iStackPos - a_iArgc + 1;
|
||||
|
||||
SToken tok;
|
||||
tok.Cmd = cmFUNC_STR;
|
||||
tok.Fun.argc = a_iArgc;
|
||||
tok.Fun.idx = a_iIdx;
|
||||
tok.Fun.ptr = a_pFun;
|
||||
m_vRPN.push_back(tok);
|
||||
|
||||
m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Add end marker to bytecode.
|
||||
|
||||
\throw nothrow
|
||||
*/
|
||||
void ParserByteCode::Finalize()
|
||||
{
|
||||
SToken tok;
|
||||
tok.Cmd = cmEND;
|
||||
m_vRPN.push_back(tok);
|
||||
rpn_type(m_vRPN).swap(m_vRPN); // shrink bytecode vector to fit
|
||||
|
||||
// Determine the if-then-else jump offsets
|
||||
ParserStack<int> stIf, stElse;
|
||||
int idx;
|
||||
for (int i=0; i<(int)m_vRPN.size(); ++i)
|
||||
{
|
||||
switch(m_vRPN[i].Cmd)
|
||||
{
|
||||
case cmIF:
|
||||
stIf.push(i);
|
||||
break;
|
||||
|
||||
case cmELSE:
|
||||
stElse.push(i);
|
||||
idx = stIf.pop();
|
||||
m_vRPN[idx].Oprt.offset = i - idx;
|
||||
break;
|
||||
|
||||
case cmENDIF:
|
||||
idx = stElse.pop();
|
||||
m_vRPN[idx].Oprt.offset = i - idx;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
const SToken* ParserByteCode::GetBase() const
|
||||
{
|
||||
if (m_vRPN.size()==0)
|
||||
throw ParserError(ecINTERNAL_ERROR);
|
||||
else
|
||||
return &m_vRPN[0];
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
std::size_t ParserByteCode::GetMaxStackSize() const
|
||||
{
|
||||
return m_iMaxStackSize+1;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Returns the number of entries in the bytecode. */
|
||||
std::size_t ParserByteCode::GetSize() const
|
||||
{
|
||||
return m_vRPN.size();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Delete the bytecode.
|
||||
|
||||
\throw nothrow
|
||||
|
||||
The name of this function is a violation of my own coding guidelines
|
||||
but this way it's more in line with the STL functions thus more
|
||||
intuitive.
|
||||
*/
|
||||
void ParserByteCode::clear()
|
||||
{
|
||||
m_vRPN.clear();
|
||||
m_iStackPos = 0;
|
||||
m_iMaxStackSize = 0;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Dump bytecode (for debugging only!). */
|
||||
void ParserByteCode::AsciiDump()
|
||||
{
|
||||
if (!m_vRPN.size())
|
||||
{
|
||||
mu::console() << _T("No bytecode available\n");
|
||||
return;
|
||||
}
|
||||
|
||||
mu::console() << _T("Number of RPN tokens:") << (int)m_vRPN.size() << _T("\n");
|
||||
for (std::size_t i=0; i<m_vRPN.size() && m_vRPN[i].Cmd!=cmEND; ++i)
|
||||
{
|
||||
mu::console() << std::dec << i << _T(" : \t");
|
||||
switch (m_vRPN[i].Cmd)
|
||||
{
|
||||
case cmVAL: mu::console() << _T("VAL \t");
|
||||
mu::console() << _T("[") << m_vRPN[i].Val.data2 << _T("]\n");
|
||||
break;
|
||||
|
||||
case cmVAR: mu::console() << _T("VAR \t");
|
||||
mu::console() << _T("[ADDR: 0x") << std::hex << m_vRPN[i].Val.ptr << _T("]\n");
|
||||
break;
|
||||
|
||||
case cmVARPOW2: mu::console() << _T("VARPOW2 \t");
|
||||
mu::console() << _T("[ADDR: 0x") << std::hex << m_vRPN[i].Val.ptr << _T("]\n");
|
||||
break;
|
||||
|
||||
case cmVARPOW3: mu::console() << _T("VARPOW3 \t");
|
||||
mu::console() << _T("[ADDR: 0x") << std::hex << m_vRPN[i].Val.ptr << _T("]\n");
|
||||
break;
|
||||
|
||||
case cmVARPOW4: mu::console() << _T("VARPOW4 \t");
|
||||
mu::console() << _T("[ADDR: 0x") << std::hex << m_vRPN[i].Val.ptr << _T("]\n");
|
||||
break;
|
||||
|
||||
case cmVARMUL: mu::console() << _T("VARMUL \t");
|
||||
mu::console() << _T("[ADDR: 0x") << std::hex << m_vRPN[i].Val.ptr << _T("]");
|
||||
mu::console() << _T(" * [") << m_vRPN[i].Val.data << _T("]");
|
||||
mu::console() << _T(" + [") << m_vRPN[i].Val.data2 << _T("]\n");
|
||||
break;
|
||||
|
||||
case cmFUNC: mu::console() << _T("CALL\t");
|
||||
mu::console() << _T("[ARG:") << std::dec << m_vRPN[i].Fun.argc << _T("]");
|
||||
mu::console() << _T("[ADDR: 0x") << std::hex << m_vRPN[i].Fun.ptr << _T("]");
|
||||
mu::console() << _T("\n");
|
||||
break;
|
||||
|
||||
case cmFUNC_STR:
|
||||
mu::console() << _T("CALL STRFUNC\t");
|
||||
mu::console() << _T("[ARG:") << std::dec << m_vRPN[i].Fun.argc << _T("]");
|
||||
mu::console() << _T("[IDX:") << std::dec << m_vRPN[i].Fun.idx << _T("]");
|
||||
mu::console() << _T("[ADDR: 0x") << m_vRPN[i].Fun.ptr << _T("]\n");
|
||||
break;
|
||||
|
||||
case cmLT: mu::console() << _T("LT\n"); break;
|
||||
case cmGT: mu::console() << _T("GT\n"); break;
|
||||
case cmLE: mu::console() << _T("LE\n"); break;
|
||||
case cmGE: mu::console() << _T("GE\n"); break;
|
||||
case cmEQ: mu::console() << _T("EQ\n"); break;
|
||||
case cmNEQ: mu::console() << _T("NEQ\n"); break;
|
||||
case cmADD: mu::console() << _T("ADD\n"); break;
|
||||
case cmLAND: mu::console() << _T("&&\n"); break;
|
||||
case cmLOR: mu::console() << _T("||\n"); break;
|
||||
case cmSUB: mu::console() << _T("SUB\n"); break;
|
||||
case cmMUL: mu::console() << _T("MUL\n"); break;
|
||||
case cmDIV: mu::console() << _T("DIV\n"); break;
|
||||
case cmPOW: mu::console() << _T("POW\n"); break;
|
||||
|
||||
case cmIF: mu::console() << _T("IF\t");
|
||||
mu::console() << _T("[OFFSET:") << std::dec << m_vRPN[i].Oprt.offset << _T("]\n");
|
||||
break;
|
||||
|
||||
case cmELSE: mu::console() << _T("ELSE\t");
|
||||
mu::console() << _T("[OFFSET:") << std::dec << m_vRPN[i].Oprt.offset << _T("]\n");
|
||||
break;
|
||||
|
||||
case cmENDIF: mu::console() << _T("ENDIF\n"); break;
|
||||
|
||||
case cmASSIGN:
|
||||
mu::console() << _T("ASSIGN\t");
|
||||
mu::console() << _T("[ADDR: 0x") << m_vRPN[i].Oprt.ptr << _T("]\n");
|
||||
break;
|
||||
|
||||
default: mu::console() << _T("(unknown code: ") << m_vRPN[i].Cmd << _T(")\n");
|
||||
break;
|
||||
} // switch cmdCode
|
||||
} // while bytecode
|
||||
|
||||
mu::console() << _T("END") << std::endl;
|
||||
}
|
||||
} // namespace mu
|
463
muparser-2.2.5_GR/src/muParserCallback.cc
Executable file
463
muparser-2.2.5_GR/src/muParserCallback.cc
Executable file
|
@ -0,0 +1,463 @@
|
|||
/*
|
||||
__________
|
||||
_____ __ __\______ \_____ _______ ______ ____ _______
|
||||
/ \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
|
||||
| Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
|
||||
|__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
|
||||
\/ \/ \/ \/
|
||||
Copyright (C) 2004-2011 Ingo Berg
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||
software and associated documentation files (the "Software"), to deal in the Software
|
||||
without restriction, including without limitation the rights to use, copy, modify,
|
||||
merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or
|
||||
substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
|
||||
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "muParserCallback.h"
|
||||
|
||||
/** \file
|
||||
\brief Implementation of the parser callback class.
|
||||
*/
|
||||
|
||||
|
||||
namespace mu
|
||||
{
|
||||
//---------------------------------------------------------------------------
|
||||
ParserCallback::ParserCallback(fun_type0 a_pFun, bool a_bAllowOpti)
|
||||
:m_pFun((void*)a_pFun)
|
||||
,m_iArgc(0)
|
||||
,m_iPri(-1)
|
||||
,m_eOprtAsct(oaNONE)
|
||||
,m_iCode(cmFUNC)
|
||||
,m_iType(tpDBL)
|
||||
,m_bAllowOpti(a_bAllowOpti)
|
||||
{}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
ParserCallback::ParserCallback(fun_type1 a_pFun, bool a_bAllowOpti, int a_iPrec, ECmdCode a_iCode)
|
||||
:m_pFun((void*)a_pFun)
|
||||
,m_iArgc(1)
|
||||
,m_iPri(a_iPrec)
|
||||
,m_eOprtAsct(oaNONE)
|
||||
,m_iCode(a_iCode)
|
||||
,m_iType(tpDBL)
|
||||
,m_bAllowOpti(a_bAllowOpti)
|
||||
{}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Constructor for constructing function callbacks taking two arguments.
|
||||
\throw nothrow
|
||||
*/
|
||||
ParserCallback::ParserCallback(fun_type2 a_pFun, bool a_bAllowOpti)
|
||||
:m_pFun((void*)a_pFun)
|
||||
,m_iArgc(2)
|
||||
,m_iPri(-1)
|
||||
,m_eOprtAsct(oaNONE)
|
||||
,m_iCode(cmFUNC)
|
||||
,m_iType(tpDBL)
|
||||
,m_bAllowOpti(a_bAllowOpti)
|
||||
{}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Constructor for constructing binary operator callbacks.
|
||||
\param a_pFun Pointer to a static function taking two arguments
|
||||
\param a_bAllowOpti A flag indicating this function can be optimized
|
||||
\param a_iPrec The operator precedence
|
||||
\param a_eOprtAsct The operators associativity
|
||||
\throw nothrow
|
||||
*/
|
||||
ParserCallback::ParserCallback(fun_type2 a_pFun,
|
||||
bool a_bAllowOpti,
|
||||
int a_iPrec,
|
||||
EOprtAssociativity a_eOprtAsct)
|
||||
:m_pFun((void*)a_pFun)
|
||||
,m_iArgc(2)
|
||||
,m_iPri(a_iPrec)
|
||||
,m_eOprtAsct(a_eOprtAsct)
|
||||
,m_iCode(cmOPRT_BIN)
|
||||
,m_iType(tpDBL)
|
||||
,m_bAllowOpti(a_bAllowOpti)
|
||||
{}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
ParserCallback::ParserCallback(fun_type3 a_pFun, bool a_bAllowOpti)
|
||||
:m_pFun((void*)a_pFun)
|
||||
,m_iArgc(3)
|
||||
,m_iPri(-1)
|
||||
,m_eOprtAsct(oaNONE)
|
||||
,m_iCode(cmFUNC)
|
||||
,m_iType(tpDBL)
|
||||
,m_bAllowOpti(a_bAllowOpti)
|
||||
{}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
ParserCallback::ParserCallback(fun_type4 a_pFun, bool a_bAllowOpti)
|
||||
:m_pFun((void*)a_pFun)
|
||||
,m_iArgc(4)
|
||||
,m_iPri(-1)
|
||||
,m_eOprtAsct(oaNONE)
|
||||
,m_iCode(cmFUNC)
|
||||
,m_iType(tpDBL)
|
||||
,m_bAllowOpti(a_bAllowOpti)
|
||||
{}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
ParserCallback::ParserCallback(fun_type5 a_pFun, bool a_bAllowOpti)
|
||||
:m_pFun((void*)a_pFun)
|
||||
,m_iArgc(5)
|
||||
,m_iPri(-1)
|
||||
,m_eOprtAsct(oaNONE)
|
||||
,m_iCode(cmFUNC)
|
||||
,m_iType(tpDBL)
|
||||
,m_bAllowOpti(a_bAllowOpti)
|
||||
{}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
ParserCallback::ParserCallback(fun_type6 a_pFun, bool a_bAllowOpti)
|
||||
:m_pFun((void*)a_pFun)
|
||||
,m_iArgc(6)
|
||||
,m_iPri(-1)
|
||||
,m_eOprtAsct(oaNONE)
|
||||
,m_iCode(cmFUNC)
|
||||
,m_iType(tpDBL)
|
||||
,m_bAllowOpti(a_bAllowOpti)
|
||||
{}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
ParserCallback::ParserCallback(fun_type7 a_pFun, bool a_bAllowOpti)
|
||||
:m_pFun((void*)a_pFun)
|
||||
,m_iArgc(7)
|
||||
,m_iPri(-1)
|
||||
,m_eOprtAsct(oaNONE)
|
||||
,m_iCode(cmFUNC)
|
||||
,m_iType(tpDBL)
|
||||
,m_bAllowOpti(a_bAllowOpti)
|
||||
{}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
ParserCallback::ParserCallback(fun_type8 a_pFun, bool a_bAllowOpti)
|
||||
:m_pFun((void*)a_pFun)
|
||||
,m_iArgc(8)
|
||||
,m_iPri(-1)
|
||||
,m_eOprtAsct(oaNONE)
|
||||
,m_iCode(cmFUNC)
|
||||
,m_iType(tpDBL)
|
||||
,m_bAllowOpti(a_bAllowOpti)
|
||||
{}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
ParserCallback::ParserCallback(fun_type9 a_pFun, bool a_bAllowOpti)
|
||||
:m_pFun((void*)a_pFun)
|
||||
,m_iArgc(9)
|
||||
,m_iPri(-1)
|
||||
,m_eOprtAsct(oaNONE)
|
||||
,m_iCode(cmFUNC)
|
||||
,m_iType(tpDBL)
|
||||
,m_bAllowOpti(a_bAllowOpti)
|
||||
{}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
ParserCallback::ParserCallback(fun_type10 a_pFun, bool a_bAllowOpti)
|
||||
:m_pFun((void*)a_pFun)
|
||||
,m_iArgc(10)
|
||||
,m_iPri(-1)
|
||||
,m_eOprtAsct(oaNONE)
|
||||
,m_iCode(cmFUNC)
|
||||
,m_iType(tpDBL)
|
||||
,m_bAllowOpti(a_bAllowOpti)
|
||||
{}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
ParserCallback::ParserCallback(bulkfun_type0 a_pFun, bool a_bAllowOpti)
|
||||
:m_pFun((void*)a_pFun)
|
||||
,m_iArgc(0)
|
||||
,m_iPri(-1)
|
||||
,m_eOprtAsct(oaNONE)
|
||||
,m_iCode(cmFUNC_BULK)
|
||||
,m_iType(tpDBL)
|
||||
,m_bAllowOpti(a_bAllowOpti)
|
||||
{}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
ParserCallback::ParserCallback(bulkfun_type1 a_pFun, bool a_bAllowOpti)
|
||||
:m_pFun((void*)a_pFun)
|
||||
,m_iArgc(1)
|
||||
,m_iPri(-1)
|
||||
,m_eOprtAsct(oaNONE)
|
||||
,m_iCode(cmFUNC_BULK)
|
||||
,m_iType(tpDBL)
|
||||
,m_bAllowOpti(a_bAllowOpti)
|
||||
{}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Constructor for constructing function callbacks taking two arguments.
|
||||
\throw nothrow
|
||||
*/
|
||||
ParserCallback::ParserCallback(bulkfun_type2 a_pFun, bool a_bAllowOpti)
|
||||
:m_pFun((void*)a_pFun)
|
||||
,m_iArgc(2)
|
||||
,m_iPri(-1)
|
||||
,m_eOprtAsct(oaNONE)
|
||||
,m_iCode(cmFUNC_BULK)
|
||||
,m_iType(tpDBL)
|
||||
,m_bAllowOpti(a_bAllowOpti)
|
||||
{}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
ParserCallback::ParserCallback(bulkfun_type3 a_pFun, bool a_bAllowOpti)
|
||||
:m_pFun((void*)a_pFun)
|
||||
,m_iArgc(3)
|
||||
,m_iPri(-1)
|
||||
,m_eOprtAsct(oaNONE)
|
||||
,m_iCode(cmFUNC_BULK)
|
||||
,m_iType(tpDBL)
|
||||
,m_bAllowOpti(a_bAllowOpti)
|
||||
{}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
ParserCallback::ParserCallback(bulkfun_type4 a_pFun, bool a_bAllowOpti)
|
||||
:m_pFun((void*)a_pFun)
|
||||
,m_iArgc(4)
|
||||
,m_iPri(-1)
|
||||
,m_eOprtAsct(oaNONE)
|
||||
,m_iCode(cmFUNC_BULK)
|
||||
,m_iType(tpDBL)
|
||||
,m_bAllowOpti(a_bAllowOpti)
|
||||
{}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
ParserCallback::ParserCallback(bulkfun_type5 a_pFun, bool a_bAllowOpti)
|
||||
:m_pFun((void*)a_pFun)
|
||||
,m_iArgc(5)
|
||||
,m_iPri(-1)
|
||||
,m_eOprtAsct(oaNONE)
|
||||
,m_iCode(cmFUNC_BULK)
|
||||
,m_iType(tpDBL)
|
||||
,m_bAllowOpti(a_bAllowOpti)
|
||||
{}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
ParserCallback::ParserCallback(bulkfun_type6 a_pFun, bool a_bAllowOpti)
|
||||
:m_pFun((void*)a_pFun)
|
||||
,m_iArgc(6)
|
||||
,m_iPri(-1)
|
||||
,m_eOprtAsct(oaNONE)
|
||||
,m_iCode(cmFUNC_BULK)
|
||||
,m_iType(tpDBL)
|
||||
,m_bAllowOpti(a_bAllowOpti)
|
||||
{}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
ParserCallback::ParserCallback(bulkfun_type7 a_pFun, bool a_bAllowOpti)
|
||||
:m_pFun((void*)a_pFun)
|
||||
,m_iArgc(7)
|
||||
,m_iPri(-1)
|
||||
,m_eOprtAsct(oaNONE)
|
||||
,m_iCode(cmFUNC_BULK)
|
||||
,m_iType(tpDBL)
|
||||
,m_bAllowOpti(a_bAllowOpti)
|
||||
{}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
ParserCallback::ParserCallback(bulkfun_type8 a_pFun, bool a_bAllowOpti)
|
||||
:m_pFun((void*)a_pFun)
|
||||
,m_iArgc(8)
|
||||
,m_iPri(-1)
|
||||
,m_eOprtAsct(oaNONE)
|
||||
,m_iCode(cmFUNC_BULK)
|
||||
,m_iType(tpDBL)
|
||||
,m_bAllowOpti(a_bAllowOpti)
|
||||
{}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
ParserCallback::ParserCallback(bulkfun_type9 a_pFun, bool a_bAllowOpti)
|
||||
:m_pFun((void*)a_pFun)
|
||||
,m_iArgc(9)
|
||||
,m_iPri(-1)
|
||||
,m_eOprtAsct(oaNONE)
|
||||
,m_iCode(cmFUNC_BULK)
|
||||
,m_iType(tpDBL)
|
||||
,m_bAllowOpti(a_bAllowOpti)
|
||||
{}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
ParserCallback::ParserCallback(bulkfun_type10 a_pFun, bool a_bAllowOpti)
|
||||
:m_pFun((void*)a_pFun)
|
||||
,m_iArgc(10)
|
||||
,m_iPri(-1)
|
||||
,m_eOprtAsct(oaNONE)
|
||||
,m_iCode(cmFUNC_BULK)
|
||||
,m_iType(tpDBL)
|
||||
,m_bAllowOpti(a_bAllowOpti)
|
||||
{}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
ParserCallback::ParserCallback(multfun_type a_pFun, bool a_bAllowOpti)
|
||||
:m_pFun((void*)a_pFun)
|
||||
,m_iArgc(-1)
|
||||
,m_iPri(-1)
|
||||
,m_eOprtAsct(oaNONE)
|
||||
,m_iCode(cmFUNC)
|
||||
,m_iType(tpDBL)
|
||||
,m_bAllowOpti(a_bAllowOpti)
|
||||
{}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
ParserCallback::ParserCallback(strfun_type1 a_pFun, bool a_bAllowOpti)
|
||||
:m_pFun((void*)a_pFun)
|
||||
,m_iArgc(0)
|
||||
,m_iPri(-1)
|
||||
,m_eOprtAsct(oaNONE)
|
||||
,m_iCode(cmFUNC_STR)
|
||||
,m_iType(tpSTR)
|
||||
,m_bAllowOpti(a_bAllowOpti)
|
||||
{}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
ParserCallback::ParserCallback(strfun_type2 a_pFun, bool a_bAllowOpti)
|
||||
:m_pFun((void*)a_pFun)
|
||||
,m_iArgc(1)
|
||||
,m_iPri(-1)
|
||||
,m_eOprtAsct(oaNONE)
|
||||
,m_iCode(cmFUNC_STR)
|
||||
,m_iType(tpSTR)
|
||||
,m_bAllowOpti(a_bAllowOpti)
|
||||
{}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
ParserCallback::ParserCallback(strfun_type3 a_pFun, bool a_bAllowOpti)
|
||||
:m_pFun((void*)a_pFun)
|
||||
,m_iArgc(2)
|
||||
,m_iPri(-1)
|
||||
,m_eOprtAsct(oaNONE)
|
||||
,m_iCode(cmFUNC_STR)
|
||||
,m_iType(tpSTR)
|
||||
,m_bAllowOpti(a_bAllowOpti)
|
||||
{}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Default constructor.
|
||||
\throw nothrow
|
||||
*/
|
||||
ParserCallback::ParserCallback()
|
||||
:m_pFun(0)
|
||||
,m_iArgc(0)
|
||||
,m_iPri(-1)
|
||||
,m_eOprtAsct(oaNONE)
|
||||
,m_iCode(cmUNKNOWN)
|
||||
,m_iType(tpVOID)
|
||||
,m_bAllowOpti(0)
|
||||
{}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Copy constructor.
|
||||
\throw nothrow
|
||||
*/
|
||||
ParserCallback::ParserCallback(const ParserCallback &ref)
|
||||
{
|
||||
m_pFun = ref.m_pFun;
|
||||
m_iArgc = ref.m_iArgc;
|
||||
m_bAllowOpti = ref.m_bAllowOpti;
|
||||
m_iCode = ref.m_iCode;
|
||||
m_iType = ref.m_iType;
|
||||
m_iPri = ref.m_iPri;
|
||||
m_eOprtAsct = ref.m_eOprtAsct;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Clone this instance and return a pointer to the new instance. */
|
||||
ParserCallback* ParserCallback::Clone() const
|
||||
{
|
||||
return new ParserCallback(*this);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Return tru if the function is conservative.
|
||||
|
||||
Conservative functions return always the same result for the same argument.
|
||||
\throw nothrow
|
||||
*/
|
||||
bool ParserCallback::IsOptimizable() const
|
||||
{
|
||||
return m_bAllowOpti;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Get the callback address for the parser function.
|
||||
|
||||
The type of the address is void. It needs to be recasted according to the
|
||||
argument number to the right type.
|
||||
|
||||
\throw nothrow
|
||||
\return #pFun
|
||||
*/
|
||||
void* ParserCallback::GetAddr() const
|
||||
{
|
||||
return m_pFun;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Return the callback code. */
|
||||
ECmdCode ParserCallback::GetCode() const
|
||||
{
|
||||
return m_iCode;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
ETypeCode ParserCallback::GetType() const
|
||||
{
|
||||
return m_iType;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Return the operator precedence.
|
||||
\throw nothrown
|
||||
|
||||
Only valid if the callback token is an operator token (binary or infix).
|
||||
*/
|
||||
int ParserCallback::GetPri() const
|
||||
{
|
||||
return m_iPri;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Return the operators associativity.
|
||||
\throw nothrown
|
||||
|
||||
Only valid if the callback token is a binary operator token.
|
||||
*/
|
||||
EOprtAssociativity ParserCallback::GetAssociativity() const
|
||||
{
|
||||
return m_eOprtAsct;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Returns the number of function Arguments. */
|
||||
int ParserCallback::GetArgc() const
|
||||
{
|
||||
return m_iArgc;
|
||||
}
|
||||
} // namespace mu
|
1096
muparser-2.2.5_GR/src/muParserDLL.cc
Executable file
1096
muparser-2.2.5_GR/src/muParserDLL.cc
Executable file
File diff suppressed because it is too large
Load diff
337
muparser-2.2.5_GR/src/muParserError.cc
Executable file
337
muparser-2.2.5_GR/src/muParserError.cc
Executable file
|
@ -0,0 +1,337 @@
|
|||
/*
|
||||
__________
|
||||
_____ __ __\______ \_____ _______ ______ ____ _______
|
||||
/ \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
|
||||
| Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
|
||||
|__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
|
||||
\/ \/ \/ \/
|
||||
Copyright (C) 2011 Ingo Berg
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||
software and associated documentation files (the "Software"), to deal in the Software
|
||||
without restriction, including without limitation the rights to use, copy, modify,
|
||||
merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or
|
||||
substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
|
||||
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include "muParserError.h"
|
||||
|
||||
|
||||
namespace mu
|
||||
{
|
||||
const ParserErrorMsg ParserErrorMsg::m_Instance;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
const ParserErrorMsg& ParserErrorMsg::Instance()
|
||||
{
|
||||
return m_Instance;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
string_type ParserErrorMsg::operator[](unsigned a_iIdx) const
|
||||
{
|
||||
return (a_iIdx<m_vErrMsg.size()) ? m_vErrMsg[a_iIdx] : string_type();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
ParserErrorMsg::~ParserErrorMsg()
|
||||
{}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Assignement operator is deactivated.
|
||||
*/
|
||||
ParserErrorMsg& ParserErrorMsg::operator=(const ParserErrorMsg& )
|
||||
{
|
||||
assert(false);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
ParserErrorMsg::ParserErrorMsg(const ParserErrorMsg&)
|
||||
{}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
ParserErrorMsg::ParserErrorMsg()
|
||||
:m_vErrMsg(0)
|
||||
{
|
||||
m_vErrMsg.resize(ecCOUNT);
|
||||
|
||||
m_vErrMsg[ecUNASSIGNABLE_TOKEN] = _T("Unexpected token \"$TOK$\" found at position $POS$.");
|
||||
m_vErrMsg[ecINTERNAL_ERROR] = _T("Internal error");
|
||||
m_vErrMsg[ecINVALID_NAME] = _T("Invalid function-, variable- or constant name: \"$TOK$\".");
|
||||
m_vErrMsg[ecINVALID_BINOP_IDENT] = _T("Invalid binary operator identifier: \"$TOK$\".");
|
||||
m_vErrMsg[ecINVALID_INFIX_IDENT] = _T("Invalid infix operator identifier: \"$TOK$\".");
|
||||
m_vErrMsg[ecINVALID_POSTFIX_IDENT] = _T("Invalid postfix operator identifier: \"$TOK$\".");
|
||||
m_vErrMsg[ecINVALID_FUN_PTR] = _T("Invalid pointer to callback function.");
|
||||
m_vErrMsg[ecEMPTY_EXPRESSION] = _T("Expression is empty.");
|
||||
m_vErrMsg[ecINVALID_VAR_PTR] = _T("Invalid pointer to variable.");
|
||||
m_vErrMsg[ecUNEXPECTED_OPERATOR] = _T("Unexpected operator \"$TOK$\" found at position $POS$");
|
||||
m_vErrMsg[ecUNEXPECTED_EOF] = _T("Unexpected end of expression at position $POS$");
|
||||
m_vErrMsg[ecUNEXPECTED_ARG_SEP] = _T("Unexpected argument separator at position $POS$");
|
||||
m_vErrMsg[ecUNEXPECTED_PARENS] = _T("Unexpected parenthesis \"$TOK$\" at position $POS$");
|
||||
m_vErrMsg[ecUNEXPECTED_FUN] = _T("Unexpected function \"$TOK$\" at position $POS$");
|
||||
m_vErrMsg[ecUNEXPECTED_VAL] = _T("Unexpected value \"$TOK$\" found at position $POS$");
|
||||
m_vErrMsg[ecUNEXPECTED_VAR] = _T("Unexpected variable \"$TOK$\" found at position $POS$");
|
||||
m_vErrMsg[ecUNEXPECTED_ARG] = _T("Function arguments used without a function (position: $POS$)");
|
||||
m_vErrMsg[ecMISSING_PARENS] = _T("Missing parenthesis");
|
||||
m_vErrMsg[ecTOO_MANY_PARAMS] = _T("Too many parameters for function \"$TOK$\" at expression position $POS$");
|
||||
m_vErrMsg[ecTOO_FEW_PARAMS] = _T("Too few parameters for function \"$TOK$\" at expression position $POS$");
|
||||
m_vErrMsg[ecDIV_BY_ZERO] = _T("Divide by zero");
|
||||
m_vErrMsg[ecDOMAIN_ERROR] = _T("Domain error");
|
||||
m_vErrMsg[ecNAME_CONFLICT] = _T("Name conflict");
|
||||
m_vErrMsg[ecOPT_PRI] = _T("Invalid value for operator priority (must be greater or equal to zero).");
|
||||
m_vErrMsg[ecBUILTIN_OVERLOAD] = _T("user defined binary operator \"$TOK$\" conflicts with a built in operator.");
|
||||
m_vErrMsg[ecUNEXPECTED_STR] = _T("Unexpected string token found at position $POS$.");
|
||||
m_vErrMsg[ecUNTERMINATED_STRING] = _T("Unterminated string starting at position $POS$.");
|
||||
m_vErrMsg[ecSTRING_EXPECTED] = _T("String function called with a non string type of argument.");
|
||||
m_vErrMsg[ecVAL_EXPECTED] = _T("String value used where a numerical argument is expected.");
|
||||
m_vErrMsg[ecOPRT_TYPE_CONFLICT] = _T("No suitable overload for operator \"$TOK$\" at position $POS$.");
|
||||
m_vErrMsg[ecSTR_RESULT] = _T("Function result is a string.");
|
||||
m_vErrMsg[ecGENERIC] = _T("Parser error.");
|
||||
m_vErrMsg[ecLOCALE] = _T("Decimal separator is identic to function argument separator.");
|
||||
m_vErrMsg[ecUNEXPECTED_CONDITIONAL] = _T("The \"$TOK$\" operator must be preceeded by a closing bracket.");
|
||||
m_vErrMsg[ecMISSING_ELSE_CLAUSE] = _T("If-then-else operator is missing an else clause");
|
||||
m_vErrMsg[ecMISPLACED_COLON] = _T("Misplaced colon at position $POS$");
|
||||
m_vErrMsg[ecUNREASONABLE_NUMBER_OF_COMPUTATIONS] = _T("Number of computations to small for bulk mode. (Vectorisation overhead too costly)");
|
||||
|
||||
#if defined(_DEBUG)
|
||||
for (int i=0; i<ecCOUNT; ++i)
|
||||
if (!m_vErrMsg[i].length())
|
||||
assert(false);
|
||||
#endif
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// ParserError class
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
/** \brief Default constructor. */
|
||||
ParserError::ParserError()
|
||||
:m_strMsg()
|
||||
,m_strFormula()
|
||||
,m_strTok()
|
||||
,m_iPos(-1)
|
||||
,m_iErrc(ecUNDEFINED)
|
||||
,m_ErrMsg(ParserErrorMsg::Instance())
|
||||
{
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/** \brief This Constructor is used for internal exceptions only.
|
||||
|
||||
It does not contain any information but the error code.
|
||||
*/
|
||||
ParserError::ParserError(EErrorCodes a_iErrc)
|
||||
:m_strMsg()
|
||||
,m_strFormula()
|
||||
,m_strTok()
|
||||
,m_iPos(-1)
|
||||
,m_iErrc(a_iErrc)
|
||||
,m_ErrMsg(ParserErrorMsg::Instance())
|
||||
{
|
||||
m_strMsg = m_ErrMsg[m_iErrc];
|
||||
stringstream_type stream;
|
||||
stream << (int)m_iPos;
|
||||
ReplaceSubString(m_strMsg, _T("$POS$"), stream.str());
|
||||
ReplaceSubString(m_strMsg, _T("$TOK$"), m_strTok);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/** \brief Construct an error from a message text. */
|
||||
ParserError::ParserError(const string_type &sMsg)
|
||||
:m_ErrMsg(ParserErrorMsg::Instance())
|
||||
{
|
||||
Reset();
|
||||
m_strMsg = sMsg;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/** \brief Construct an error object.
|
||||
\param [in] a_iErrc the error code.
|
||||
\param [in] sTok The token string related to this error.
|
||||
\param [in] sExpr The expression related to the error.
|
||||
\param [in] a_iPos the position in the expression where the error occurred.
|
||||
*/
|
||||
ParserError::ParserError( EErrorCodes iErrc,
|
||||
const string_type &sTok,
|
||||
const string_type &sExpr,
|
||||
int iPos )
|
||||
:m_strMsg()
|
||||
,m_strFormula(sExpr)
|
||||
,m_strTok(sTok)
|
||||
,m_iPos(iPos)
|
||||
,m_iErrc(iErrc)
|
||||
,m_ErrMsg(ParserErrorMsg::Instance())
|
||||
{
|
||||
m_strMsg = m_ErrMsg[m_iErrc];
|
||||
stringstream_type stream;
|
||||
stream << (int)m_iPos;
|
||||
ReplaceSubString(m_strMsg, _T("$POS$"), stream.str());
|
||||
ReplaceSubString(m_strMsg, _T("$TOK$"), m_strTok);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/** \brief Construct an error object.
|
||||
\param [in] iErrc the error code.
|
||||
\param [in] iPos the position in the expression where the error occurred.
|
||||
\param [in] sTok The token string related to this error.
|
||||
*/
|
||||
ParserError::ParserError(EErrorCodes iErrc, int iPos, const string_type &sTok)
|
||||
:m_strMsg()
|
||||
,m_strFormula()
|
||||
,m_strTok(sTok)
|
||||
,m_iPos(iPos)
|
||||
,m_iErrc(iErrc)
|
||||
,m_ErrMsg(ParserErrorMsg::Instance())
|
||||
{
|
||||
m_strMsg = m_ErrMsg[m_iErrc];
|
||||
stringstream_type stream;
|
||||
stream << (int)m_iPos;
|
||||
ReplaceSubString(m_strMsg, _T("$POS$"), stream.str());
|
||||
ReplaceSubString(m_strMsg, _T("$TOK$"), m_strTok);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/** \brief Construct an error object.
|
||||
\param [in] szMsg The error message text.
|
||||
\param [in] iPos the position related to the error.
|
||||
\param [in] sTok The token string related to this error.
|
||||
*/
|
||||
ParserError::ParserError(const char_type *szMsg, int iPos, const string_type &sTok)
|
||||
:m_strMsg(szMsg)
|
||||
,m_strFormula()
|
||||
,m_strTok(sTok)
|
||||
,m_iPos(iPos)
|
||||
,m_iErrc(ecGENERIC)
|
||||
,m_ErrMsg(ParserErrorMsg::Instance())
|
||||
{
|
||||
stringstream_type stream;
|
||||
stream << (int)m_iPos;
|
||||
ReplaceSubString(m_strMsg, _T("$POS$"), stream.str());
|
||||
ReplaceSubString(m_strMsg, _T("$TOK$"), m_strTok);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/** \brief Copy constructor. */
|
||||
ParserError::ParserError(const ParserError &a_Obj)
|
||||
:m_strMsg(a_Obj.m_strMsg)
|
||||
,m_strFormula(a_Obj.m_strFormula)
|
||||
,m_strTok(a_Obj.m_strTok)
|
||||
,m_iPos(a_Obj.m_iPos)
|
||||
,m_iErrc(a_Obj.m_iErrc)
|
||||
,m_ErrMsg(ParserErrorMsg::Instance())
|
||||
{
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/** \brief Assignment operator. */
|
||||
ParserError& ParserError::operator=(const ParserError &a_Obj)
|
||||
{
|
||||
if (this==&a_Obj)
|
||||
return *this;
|
||||
|
||||
m_strMsg = a_Obj.m_strMsg;
|
||||
m_strFormula = a_Obj.m_strFormula;
|
||||
m_strTok = a_Obj.m_strTok;
|
||||
m_iPos = a_Obj.m_iPos;
|
||||
m_iErrc = a_Obj.m_iErrc;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
ParserError::~ParserError()
|
||||
{}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/** \brief Replace all occurrences of a substring with another string.
|
||||
\param strFind The string that shall be replaced.
|
||||
\param strReplaceWith The string that should be inserted instead of strFind
|
||||
*/
|
||||
void ParserError::ReplaceSubString( string_type &strSource,
|
||||
const string_type &strFind,
|
||||
const string_type &strReplaceWith)
|
||||
{
|
||||
string_type strResult;
|
||||
string_type::size_type iPos(0), iNext(0);
|
||||
|
||||
for(;;)
|
||||
{
|
||||
iNext = strSource.find(strFind, iPos);
|
||||
strResult.append(strSource, iPos, iNext-iPos);
|
||||
|
||||
if( iNext==string_type::npos )
|
||||
break;
|
||||
|
||||
strResult.append(strReplaceWith);
|
||||
iPos = iNext + strFind.length();
|
||||
}
|
||||
|
||||
strSource.swap(strResult);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/** \brief Reset the erro object. */
|
||||
void ParserError::Reset()
|
||||
{
|
||||
m_strMsg = _T("");
|
||||
m_strFormula = _T("");
|
||||
m_strTok = _T("");
|
||||
m_iPos = -1;
|
||||
m_iErrc = ecUNDEFINED;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/** \brief Set the expression related to this error. */
|
||||
void ParserError::SetFormula(const string_type &a_strFormula)
|
||||
{
|
||||
m_strFormula = a_strFormula;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/** \brief gets the expression related tp this error.*/
|
||||
const string_type& ParserError::GetExpr() const
|
||||
{
|
||||
return m_strFormula;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/** \brief Returns the message string for this error. */
|
||||
const string_type& ParserError::GetMsg() const
|
||||
{
|
||||
return m_strMsg;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/** \brief Return the formula position related to the error.
|
||||
|
||||
If the error is not related to a distinct position this will return -1
|
||||
*/
|
||||
int ParserError::GetPos() const
|
||||
{
|
||||
return m_iPos;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/** \brief Return string related with this token (if available). */
|
||||
const string_type& ParserError::GetToken() const
|
||||
{
|
||||
return m_strTok;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/** \brief Return the error code. */
|
||||
EErrorCodes ParserError::GetCode() const
|
||||
{
|
||||
return m_iErrc;
|
||||
}
|
||||
} // namespace mu
|
280
muparser-2.2.5_GR/src/muParserInt.cc
Executable file
280
muparser-2.2.5_GR/src/muParserInt.cc
Executable file
|
@ -0,0 +1,280 @@
|
|||
/*
|
||||
__________
|
||||
_____ __ __\______ \_____ _______ ______ ____ _______
|
||||
/ \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
|
||||
| Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
|
||||
|__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
|
||||
\/ \/ \/ \/
|
||||
Copyright (C) 2011 Ingo Berg
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||
software and associated documentation files (the "Software"), to deal in the Software
|
||||
without restriction, including without limitation the rights to use, copy, modify,
|
||||
merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or
|
||||
substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
|
||||
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "muParserInt.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
#include <numeric>
|
||||
|
||||
using namespace std;
|
||||
|
||||
/** \file
|
||||
\brief Implementation of a parser using integer value.
|
||||
*/
|
||||
|
||||
/** \brief Namespace for mathematical applications. */
|
||||
namespace mu
|
||||
{
|
||||
value_type ParserInt::Abs(value_type v) { return (value_type)Round(fabs((double)v)); }
|
||||
value_type ParserInt::Sign(value_type v) { return (Round(v)<0) ? -1 : (Round(v)>0) ? 1 : 0; }
|
||||
value_type ParserInt::Ite(value_type v1,
|
||||
value_type v2,
|
||||
value_type v3) { return (Round(v1)==1) ? Round(v2) : Round(v3); }
|
||||
value_type ParserInt::Add(value_type v1, value_type v2) { return Round(v1) + Round(v2); }
|
||||
value_type ParserInt::Sub(value_type v1, value_type v2) { return Round(v1) - Round(v2); }
|
||||
value_type ParserInt::Mul(value_type v1, value_type v2) { return Round(v1) * Round(v2); }
|
||||
value_type ParserInt::Div(value_type v1, value_type v2) { return Round(v1) / Round(v2); }
|
||||
value_type ParserInt::Mod(value_type v1, value_type v2) { return Round(v1) % Round(v2); }
|
||||
value_type ParserInt::Shr(value_type v1, value_type v2) { return Round(v1) >> Round(v2); }
|
||||
value_type ParserInt::Shl(value_type v1, value_type v2) { return Round(v1) << Round(v2); }
|
||||
value_type ParserInt::LogAnd(value_type v1, value_type v2) { return Round(v1) & Round(v2); }
|
||||
value_type ParserInt::LogOr(value_type v1, value_type v2) { return Round(v1) | Round(v2); }
|
||||
value_type ParserInt::And(value_type v1, value_type v2) { return Round(v1) && Round(v2); }
|
||||
value_type ParserInt::Or(value_type v1, value_type v2) { return Round(v1) || Round(v2); }
|
||||
value_type ParserInt::Less(value_type v1, value_type v2) { return Round(v1) < Round(v2); }
|
||||
value_type ParserInt::Greater(value_type v1, value_type v2) { return Round(v1) > Round(v2); }
|
||||
value_type ParserInt::LessEq(value_type v1, value_type v2) { return Round(v1) <= Round(v2); }
|
||||
value_type ParserInt::GreaterEq(value_type v1, value_type v2) { return Round(v1) >= Round(v2); }
|
||||
value_type ParserInt::Equal(value_type v1, value_type v2) { return Round(v1) == Round(v2); }
|
||||
value_type ParserInt::NotEqual(value_type v1, value_type v2) { return Round(v1) != Round(v2); }
|
||||
value_type ParserInt::Not(value_type v) { return !Round(v); }
|
||||
|
||||
value_type ParserInt::Pow(value_type v1, value_type v2)
|
||||
{
|
||||
return std::pow((double)Round(v1), (double)Round(v2));
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Unary operator Callbacks: Infix operators
|
||||
value_type ParserInt::UnaryMinus(value_type v)
|
||||
{
|
||||
return -Round(v);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
value_type ParserInt::Sum(const value_type* a_afArg, int a_iArgc)
|
||||
{
|
||||
if (!a_iArgc)
|
||||
throw ParserError(_T("too few arguments for function sum."));
|
||||
|
||||
value_type fRes=0;
|
||||
for (int i=0; i<a_iArgc; ++i)
|
||||
fRes += a_afArg[i];
|
||||
|
||||
return fRes;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
value_type ParserInt::Min(const value_type* a_afArg, int a_iArgc)
|
||||
{
|
||||
if (!a_iArgc)
|
||||
throw ParserError( _T("too few arguments for function min.") );
|
||||
|
||||
value_type fRes=a_afArg[0];
|
||||
for (int i=0; i<a_iArgc; ++i)
|
||||
fRes = std::min(fRes, a_afArg[i]);
|
||||
|
||||
return fRes;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
value_type ParserInt::Max(const value_type* a_afArg, int a_iArgc)
|
||||
{
|
||||
if (!a_iArgc)
|
||||
throw ParserError(_T("too few arguments for function min."));
|
||||
|
||||
value_type fRes=a_afArg[0];
|
||||
for (int i=0; i<a_iArgc; ++i)
|
||||
fRes = std::max(fRes, a_afArg[i]);
|
||||
|
||||
return fRes;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Default value recognition callback
|
||||
int ParserInt::IsVal(const char_type *a_szExpr, int *a_iPos, value_type *a_fVal)
|
||||
{
|
||||
string_type buf(a_szExpr);
|
||||
std::size_t pos = buf.find_first_not_of(_T("0123456789"));
|
||||
|
||||
if (pos==std::string::npos)
|
||||
return 0;
|
||||
|
||||
stringstream_type stream( buf.substr(0, pos ) );
|
||||
int iVal(0);
|
||||
|
||||
stream >> iVal;
|
||||
if (stream.fail())
|
||||
return 0;
|
||||
|
||||
stringstream_type::pos_type iEnd = stream.tellg(); // Position after reading
|
||||
if (stream.fail())
|
||||
iEnd = stream.str().length();
|
||||
|
||||
if (iEnd==(stringstream_type::pos_type)-1)
|
||||
return 0;
|
||||
|
||||
*a_iPos += (int)iEnd;
|
||||
*a_fVal = (value_type)iVal;
|
||||
return 1;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Check a given position in the expression for the presence of
|
||||
a hex value.
|
||||
\param a_szExpr Pointer to the expression string
|
||||
\param [in/out] a_iPos Pointer to an integer value holding the current parsing
|
||||
position in the expression.
|
||||
\param [out] a_fVal Pointer to the position where the detected value shall be stored.
|
||||
|
||||
Hey values must be prefixed with "0x" in order to be detected properly.
|
||||
*/
|
||||
int ParserInt::IsHexVal(const char_type *a_szExpr, int *a_iPos, value_type *a_fVal)
|
||||
{
|
||||
if (a_szExpr[1]==0 || (a_szExpr[0]!='0' || a_szExpr[1]!='x') )
|
||||
return 0;
|
||||
|
||||
unsigned iVal(0);
|
||||
|
||||
// New code based on streams for UNICODE compliance:
|
||||
stringstream_type::pos_type nPos(0);
|
||||
stringstream_type ss(a_szExpr + 2);
|
||||
ss >> std::hex >> iVal;
|
||||
nPos = ss.tellg();
|
||||
|
||||
if (nPos==(stringstream_type::pos_type)0)
|
||||
return 1;
|
||||
|
||||
*a_iPos += (int)(2 + nPos);
|
||||
*a_fVal = (value_type)iVal;
|
||||
return 1;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
int ParserInt::IsBinVal(const char_type *a_szExpr, int *a_iPos, value_type *a_fVal)
|
||||
{
|
||||
if (a_szExpr[0]!='#')
|
||||
return 0;
|
||||
|
||||
unsigned iVal(0),
|
||||
iBits(sizeof(iVal)*8),
|
||||
i(0);
|
||||
|
||||
for (i=0; (a_szExpr[i+1]=='0' || a_szExpr[i+1]=='1') && i<iBits; ++i)
|
||||
iVal |= (int)(a_szExpr[i+1]=='1') << ((iBits-1)-i);
|
||||
|
||||
if (i==0)
|
||||
return 0;
|
||||
|
||||
if (i==iBits)
|
||||
throw exception_type(_T("Binary to integer conversion error (overflow)."));
|
||||
|
||||
*a_fVal = (unsigned)(iVal >> (iBits-i) );
|
||||
*a_iPos += i+1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Constructor.
|
||||
|
||||
Call ParserBase class constructor and trigger Function, Operator and Constant initialization.
|
||||
*/
|
||||
ParserInt::ParserInt()
|
||||
:ParserBase()
|
||||
{
|
||||
AddValIdent(IsVal); // lowest priority
|
||||
AddValIdent(IsBinVal);
|
||||
AddValIdent(IsHexVal); // highest priority
|
||||
|
||||
InitCharSets();
|
||||
InitFun();
|
||||
InitOprt();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
void ParserInt::InitConst()
|
||||
{
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
void ParserInt::InitCharSets()
|
||||
{
|
||||
DefineNameChars( _T("0123456789_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") );
|
||||
DefineOprtChars( _T("+-*^/?<>=!%&|~'_") );
|
||||
DefineInfixOprtChars( _T("/+-*^?<>=!%&|~'_") );
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Initialize the default functions. */
|
||||
void ParserInt::InitFun()
|
||||
{
|
||||
DefineFun( _T("sign"), Sign);
|
||||
DefineFun( _T("abs"), Abs);
|
||||
DefineFun( _T("if"), Ite);
|
||||
DefineFun( _T("sum"), Sum);
|
||||
DefineFun( _T("min"), Min);
|
||||
DefineFun( _T("max"), Max);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Initialize operators. */
|
||||
void ParserInt::InitOprt()
|
||||
{
|
||||
// disable all built in operators, not all of them useful for integer numbers
|
||||
// (they don't do rounding of values)
|
||||
EnableBuiltInOprt(false);
|
||||
|
||||
// Disable all built in operators, they wont work with integer numbers
|
||||
// since they are designed for floating point numbers
|
||||
DefineInfixOprt( _T("-"), UnaryMinus);
|
||||
DefineInfixOprt( _T("!"), Not);
|
||||
|
||||
DefineOprt( _T("&"), LogAnd, prLOGIC);
|
||||
DefineOprt( _T("|"), LogOr, prLOGIC);
|
||||
DefineOprt( _T("&&"), And, prLOGIC);
|
||||
DefineOprt( _T("||"), Or, prLOGIC);
|
||||
|
||||
DefineOprt( _T("<"), Less, prCMP);
|
||||
DefineOprt( _T(">"), Greater, prCMP);
|
||||
DefineOprt( _T("<="), LessEq, prCMP);
|
||||
DefineOprt( _T(">="), GreaterEq, prCMP);
|
||||
DefineOprt( _T("=="), Equal, prCMP);
|
||||
DefineOprt( _T("!="), NotEqual, prCMP);
|
||||
|
||||
DefineOprt( _T("+"), Add, prADD_SUB);
|
||||
DefineOprt( _T("-"), Sub, prADD_SUB);
|
||||
|
||||
DefineOprt( _T("*"), Mul, prMUL_DIV);
|
||||
DefineOprt( _T("/"), Div, prMUL_DIV);
|
||||
DefineOprt( _T("%"), Mod, prMUL_DIV);
|
||||
|
||||
DefineOprt( _T("^"), Pow, prPOW, oaRIGHT);
|
||||
DefineOprt( _T(">>"), Shr, prMUL_DIV+1);
|
||||
DefineOprt( _T("<<"), Shl, prMUL_DIV+1);
|
||||
}
|
||||
|
||||
} // namespace mu
|
1552
muparser-2.2.5_GR/src/muParserTest.cc
Executable file
1552
muparser-2.2.5_GR/src/muParserTest.cc
Executable file
File diff suppressed because it is too large
Load diff
958
muparser-2.2.5_GR/src/muParserTokenReader.cc
Executable file
958
muparser-2.2.5_GR/src/muParserTokenReader.cc
Executable file
|
@ -0,0 +1,958 @@
|
|||
/*
|
||||
__________
|
||||
_____ __ __\______ \_____ _______ ______ ____ _______
|
||||
/ \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
|
||||
| Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
|
||||
|__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
|
||||
\/ \/ \/ \/
|
||||
Copyright (C) 2013 Ingo Berg
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||
software and associated documentation files (the "Software"), to deal in the Software
|
||||
without restriction, including without limitation the rights to use, copy, modify,
|
||||
merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or
|
||||
substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
|
||||
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include <cassert>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <map>
|
||||
#include <stack>
|
||||
#include <string>
|
||||
|
||||
#include "muParserTokenReader.h"
|
||||
#include "muParserBase.h"
|
||||
|
||||
/** \file
|
||||
\brief This file contains the parser token reader implementation.
|
||||
*/
|
||||
|
||||
|
||||
namespace mu
|
||||
{
|
||||
|
||||
// Forward declaration
|
||||
class ParserBase;
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Copy constructor.
|
||||
|
||||
\sa Assign
|
||||
\throw nothrow
|
||||
*/
|
||||
ParserTokenReader::ParserTokenReader(const ParserTokenReader &a_Reader)
|
||||
{
|
||||
Assign(a_Reader);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Assignment operator.
|
||||
|
||||
Self assignment will be suppressed otherwise #Assign is called.
|
||||
|
||||
\param a_Reader Object to copy to this token reader.
|
||||
\throw nothrow
|
||||
*/
|
||||
ParserTokenReader& ParserTokenReader::operator=(const ParserTokenReader &a_Reader)
|
||||
{
|
||||
if (&a_Reader!=this)
|
||||
Assign(a_Reader);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Assign state of a token reader to this token reader.
|
||||
|
||||
\param a_Reader Object from which the state should be copied.
|
||||
\throw nothrow
|
||||
*/
|
||||
void ParserTokenReader::Assign(const ParserTokenReader &a_Reader)
|
||||
{
|
||||
m_pParser = a_Reader.m_pParser;
|
||||
m_strFormula = a_Reader.m_strFormula;
|
||||
m_iPos = a_Reader.m_iPos;
|
||||
m_iSynFlags = a_Reader.m_iSynFlags;
|
||||
|
||||
m_UsedVar = a_Reader.m_UsedVar;
|
||||
m_pFunDef = a_Reader.m_pFunDef;
|
||||
m_pConstDef = a_Reader.m_pConstDef;
|
||||
m_pVarDef = a_Reader.m_pVarDef;
|
||||
m_pStrVarDef = a_Reader.m_pStrVarDef;
|
||||
m_pPostOprtDef = a_Reader.m_pPostOprtDef;
|
||||
m_pInfixOprtDef = a_Reader.m_pInfixOprtDef;
|
||||
m_pOprtDef = a_Reader.m_pOprtDef;
|
||||
m_bIgnoreUndefVar = a_Reader.m_bIgnoreUndefVar;
|
||||
m_vIdentFun = a_Reader.m_vIdentFun;
|
||||
m_pFactory = a_Reader.m_pFactory;
|
||||
m_pFactoryData = a_Reader.m_pFactoryData;
|
||||
m_iBrackets = a_Reader.m_iBrackets;
|
||||
m_cArgSep = a_Reader.m_cArgSep;
|
||||
m_fZero = a_Reader.m_fZero;
|
||||
m_lastTok = a_Reader.m_lastTok;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Constructor.
|
||||
|
||||
Create a Token reader and bind it to a parser object.
|
||||
|
||||
\pre [assert] a_pParser may not be NULL
|
||||
\post #m_pParser==a_pParser
|
||||
\param a_pParent Parent parser object of the token reader.
|
||||
*/
|
||||
ParserTokenReader::ParserTokenReader(ParserBase *a_pParent)
|
||||
:m_pParser(a_pParent)
|
||||
,m_strFormula()
|
||||
,m_iPos(0)
|
||||
,m_iSynFlags(0)
|
||||
,m_bIgnoreUndefVar(false)
|
||||
,m_pFunDef(NULL)
|
||||
,m_pPostOprtDef(NULL)
|
||||
,m_pInfixOprtDef(NULL)
|
||||
,m_pOprtDef(NULL)
|
||||
,m_pConstDef(NULL)
|
||||
,m_pStrVarDef(NULL)
|
||||
,m_pVarDef(NULL)
|
||||
,m_pFactory(NULL)
|
||||
,m_pFactoryData(NULL)
|
||||
,m_vIdentFun()
|
||||
,m_UsedVar()
|
||||
,m_fZero(0)
|
||||
,m_iBrackets(0)
|
||||
,m_lastTok()
|
||||
,m_cArgSep(',')
|
||||
{
|
||||
assert(m_pParser);
|
||||
SetParent(m_pParser);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Create instance of a ParserTokenReader identical with this
|
||||
and return its pointer.
|
||||
|
||||
This is a factory method the calling function must take care of the object destruction.
|
||||
|
||||
\return A new ParserTokenReader object.
|
||||
\throw nothrow
|
||||
*/
|
||||
ParserTokenReader* ParserTokenReader::Clone(ParserBase *a_pParent) const
|
||||
{
|
||||
std::auto_ptr<ParserTokenReader> ptr(new ParserTokenReader(*this));
|
||||
ptr->SetParent(a_pParent);
|
||||
return ptr.release();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
ParserTokenReader::token_type& ParserTokenReader::SaveBeforeReturn(const token_type &tok)
|
||||
{
|
||||
m_lastTok = tok;
|
||||
return m_lastTok;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
void ParserTokenReader::AddValIdent(identfun_type a_pCallback)
|
||||
{
|
||||
// Use push_front is used to give user defined callbacks a higher priority than
|
||||
// the built in ones. Otherwise reading hex numbers would not work
|
||||
// since the "0" in "0xff" would always be read first making parsing of
|
||||
// the rest impossible.
|
||||
// reference:
|
||||
// http://sourceforge.net/projects/muparser/forums/forum/462843/topic/4824956
|
||||
m_vIdentFun.push_front(a_pCallback);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
void ParserTokenReader::SetVarCreator(facfun_type a_pFactory, void *pUserData)
|
||||
{
|
||||
m_pFactory = a_pFactory;
|
||||
m_pFactoryData = pUserData;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Return the current position of the token reader in the formula string.
|
||||
|
||||
\return #m_iPos
|
||||
\throw nothrow
|
||||
*/
|
||||
int ParserTokenReader::GetPos() const
|
||||
{
|
||||
return m_iPos;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Return a reference to the formula.
|
||||
|
||||
\return #m_strFormula
|
||||
\throw nothrow
|
||||
*/
|
||||
const string_type& ParserTokenReader::GetExpr() const
|
||||
{
|
||||
return m_strFormula;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Return a map containing the used variables only. */
|
||||
varmap_type& ParserTokenReader::GetUsedVar()
|
||||
{
|
||||
return m_UsedVar;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Initialize the token Reader.
|
||||
|
||||
Sets the formula position index to zero and set Syntax flags to default for initial formula parsing.
|
||||
\pre [assert] triggered if a_szFormula==0
|
||||
*/
|
||||
void ParserTokenReader::SetFormula(const string_type &a_strFormula)
|
||||
{
|
||||
m_strFormula = a_strFormula;
|
||||
ReInit();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Set Flag that controls behaviour in case of undefined variables being found.
|
||||
|
||||
If true, the parser does not throw an exception if an undefined variable is found.
|
||||
otherwise it does. This variable is used internally only!
|
||||
It suppresses a "undefined variable" exception in GetUsedVar().
|
||||
Those function should return a complete list of variables including
|
||||
those the are not defined by the time of it's call.
|
||||
*/
|
||||
void ParserTokenReader::IgnoreUndefVar(bool bIgnore)
|
||||
{
|
||||
m_bIgnoreUndefVar = bIgnore;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Reset the token reader to the start of the formula.
|
||||
|
||||
The syntax flags will be reset to a value appropriate for the
|
||||
start of a formula.
|
||||
\post #m_iPos==0, #m_iSynFlags = noOPT | noBC | noPOSTOP | noSTR
|
||||
\throw nothrow
|
||||
\sa ESynCodes
|
||||
*/
|
||||
void ParserTokenReader::ReInit()
|
||||
{
|
||||
m_iPos = 0;
|
||||
m_iSynFlags = sfSTART_OF_LINE;
|
||||
m_iBrackets = 0;
|
||||
m_UsedVar.clear();
|
||||
m_lastTok = token_type();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Read the next token from the string. */
|
||||
ParserTokenReader::token_type ParserTokenReader::ReadNextToken()
|
||||
{
|
||||
assert(m_pParser);
|
||||
|
||||
const char_type *szFormula = m_strFormula.c_str();
|
||||
token_type tok;
|
||||
|
||||
// Ignore all non printable characters when reading the expression
|
||||
while (szFormula[m_iPos]>0 && szFormula[m_iPos]<=0x20)
|
||||
++m_iPos;
|
||||
|
||||
if ( IsEOF(tok) ) return SaveBeforeReturn(tok); // Check for end of formula
|
||||
if ( IsOprt(tok) ) return SaveBeforeReturn(tok); // Check for user defined binary operator
|
||||
if ( IsFunTok(tok) ) return SaveBeforeReturn(tok); // Check for function token
|
||||
if ( IsBuiltIn(tok) ) return SaveBeforeReturn(tok); // Check built in operators / tokens
|
||||
if ( IsArgSep(tok) ) return SaveBeforeReturn(tok); // Check for function argument separators
|
||||
if ( IsValTok(tok) ) return SaveBeforeReturn(tok); // Check for values / constant tokens
|
||||
if ( IsVarTok(tok) ) return SaveBeforeReturn(tok); // Check for variable tokens
|
||||
if ( IsStrVarTok(tok) ) return SaveBeforeReturn(tok); // Check for string variables
|
||||
if ( IsString(tok) ) return SaveBeforeReturn(tok); // Check for String tokens
|
||||
if ( IsInfixOpTok(tok) ) return SaveBeforeReturn(tok); // Check for unary operators
|
||||
if ( IsPostOpTok(tok) ) return SaveBeforeReturn(tok); // Check for unary operators
|
||||
|
||||
// Check String for undefined variable token. Done only if a
|
||||
// flag is set indicating to ignore undefined variables.
|
||||
// This is a way to conditionally avoid an error if
|
||||
// undefined variables occur.
|
||||
// (The GetUsedVar function must suppress the error for
|
||||
// undefined variables in order to collect all variable
|
||||
// names including the undefined ones.)
|
||||
if ( (m_bIgnoreUndefVar || m_pFactory) && IsUndefVarTok(tok) )
|
||||
return SaveBeforeReturn(tok);
|
||||
|
||||
// Check for unknown token
|
||||
//
|
||||
// !!! From this point on there is no exit without an exception possible...
|
||||
//
|
||||
string_type strTok;
|
||||
int iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos);
|
||||
if (iEnd!=m_iPos)
|
||||
Error(ecUNASSIGNABLE_TOKEN, m_iPos, strTok);
|
||||
|
||||
Error(ecUNASSIGNABLE_TOKEN, m_iPos, m_strFormula.substr(m_iPos));
|
||||
return token_type(); // never reached
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
void ParserTokenReader::SetParent(ParserBase *a_pParent)
|
||||
{
|
||||
m_pParser = a_pParent;
|
||||
m_pFunDef = &a_pParent->m_FunDef;
|
||||
m_pOprtDef = &a_pParent->m_OprtDef;
|
||||
m_pInfixOprtDef = &a_pParent->m_InfixOprtDef;
|
||||
m_pPostOprtDef = &a_pParent->m_PostOprtDef;
|
||||
m_pVarDef = &a_pParent->m_VarDef;
|
||||
m_pStrVarDef = &a_pParent->m_StrVarDef;
|
||||
m_pConstDef = &a_pParent->m_ConstDef;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Extract all characters that belong to a certain charset.
|
||||
|
||||
\param a_szCharSet [in] Const char array of the characters allowed in the token.
|
||||
\param a_strTok [out] The string that consists entirely of characters listed in a_szCharSet.
|
||||
\param a_iPos [in] Position in the string from where to start reading.
|
||||
\return The Position of the first character not listed in a_szCharSet.
|
||||
\throw nothrow
|
||||
*/
|
||||
int ParserTokenReader::ExtractToken(const char_type *a_szCharSet,
|
||||
string_type &a_sTok,
|
||||
int a_iPos) const
|
||||
{
|
||||
int iEnd = (int)m_strFormula.find_first_not_of(a_szCharSet, a_iPos);
|
||||
|
||||
if (iEnd==(int)string_type::npos)
|
||||
iEnd = (int)m_strFormula.length();
|
||||
|
||||
// Assign token string if there was something found
|
||||
if (a_iPos!=iEnd)
|
||||
a_sTok = string_type( m_strFormula.begin()+a_iPos, m_strFormula.begin()+iEnd);
|
||||
|
||||
return iEnd;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Check Expression for the presence of a binary operator token.
|
||||
|
||||
Userdefined binary operator "++" gives inconsistent parsing result for
|
||||
the equations "a++b" and "a ++ b" if alphabetic characters are allowed
|
||||
in operator tokens. To avoid this this function checks specifically
|
||||
for operator tokens.
|
||||
*/
|
||||
int ParserTokenReader::ExtractOperatorToken(string_type &a_sTok,
|
||||
int a_iPos) const
|
||||
{
|
||||
// Changed as per Issue 6: https://code.google.com/p/muparser/issues/detail?id=6
|
||||
int iEnd = (int)m_strFormula.find_first_not_of(m_pParser->ValidOprtChars(), a_iPos);
|
||||
if (iEnd==(int)string_type::npos)
|
||||
iEnd = (int)m_strFormula.length();
|
||||
|
||||
// Assign token string if there was something found
|
||||
if (a_iPos!=iEnd)
|
||||
{
|
||||
a_sTok = string_type( m_strFormula.begin() + a_iPos, m_strFormula.begin() + iEnd);
|
||||
return iEnd;
|
||||
}
|
||||
else
|
||||
{
|
||||
// There is still the chance of having to deal with an operator consisting exclusively
|
||||
// of alphabetic characters.
|
||||
return ExtractToken(MUP_CHARS, a_sTok, a_iPos);
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Check if a built in operator or other token can be found
|
||||
\param a_Tok [out] Operator token if one is found. This can either be a binary operator or an infix operator token.
|
||||
\return true if an operator token has been found.
|
||||
*/
|
||||
bool ParserTokenReader::IsBuiltIn(token_type &a_Tok)
|
||||
{
|
||||
const char_type **const pOprtDef = m_pParser->GetOprtDef(),
|
||||
*const szFormula = m_strFormula.c_str();
|
||||
|
||||
// Compare token with function and operator strings
|
||||
// check string for operator/function
|
||||
for (int i=0; pOprtDef[i]; i++)
|
||||
{
|
||||
std::size_t len( std::char_traits<char_type>::length(pOprtDef[i]) );
|
||||
if ( string_type(pOprtDef[i]) == string_type(szFormula + m_iPos, szFormula + m_iPos + len) )
|
||||
{
|
||||
switch(i)
|
||||
{
|
||||
//case cmAND:
|
||||
//case cmOR:
|
||||
//case cmXOR:
|
||||
case cmLAND:
|
||||
case cmLOR:
|
||||
case cmLT:
|
||||
case cmGT:
|
||||
case cmLE:
|
||||
case cmGE:
|
||||
case cmNEQ:
|
||||
case cmEQ:
|
||||
case cmADD:
|
||||
case cmSUB:
|
||||
case cmMUL:
|
||||
case cmDIV:
|
||||
case cmPOW:
|
||||
case cmASSIGN:
|
||||
//if (len!=sTok.length())
|
||||
// continue;
|
||||
|
||||
// The assignment operator need special treatment
|
||||
if (i==cmASSIGN && m_iSynFlags & noASSIGN)
|
||||
Error(ecUNEXPECTED_OPERATOR, m_iPos, pOprtDef[i]);
|
||||
|
||||
if (!m_pParser->HasBuiltInOprt()) continue;
|
||||
if (m_iSynFlags & noOPT)
|
||||
{
|
||||
// Maybe its an infix operator not an operator
|
||||
// Both operator types can share characters in
|
||||
// their identifiers
|
||||
if ( IsInfixOpTok(a_Tok) )
|
||||
return true;
|
||||
|
||||
Error(ecUNEXPECTED_OPERATOR, m_iPos, pOprtDef[i]);
|
||||
}
|
||||
|
||||
m_iSynFlags = noBC | noOPT | noARG_SEP | noPOSTOP | noASSIGN | noIF | noELSE | noEND;
|
||||
break;
|
||||
|
||||
case cmBO:
|
||||
if (m_iSynFlags & noBO)
|
||||
Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]);
|
||||
|
||||
if (m_lastTok.GetCode()==cmFUNC)
|
||||
m_iSynFlags = noOPT | noEND | noARG_SEP | noPOSTOP | noASSIGN | noIF | noELSE;
|
||||
else
|
||||
m_iSynFlags = noBC | noOPT | noEND | noARG_SEP | noPOSTOP | noASSIGN| noIF | noELSE;
|
||||
|
||||
++m_iBrackets;
|
||||
break;
|
||||
|
||||
case cmBC:
|
||||
if (m_iSynFlags & noBC)
|
||||
Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]);
|
||||
|
||||
m_iSynFlags = noBO | noVAR | noVAL | noFUN | noINFIXOP | noSTR | noASSIGN;
|
||||
|
||||
if (--m_iBrackets<0)
|
||||
Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]);
|
||||
break;
|
||||
|
||||
case cmELSE:
|
||||
if (m_iSynFlags & noELSE)
|
||||
Error(ecUNEXPECTED_CONDITIONAL, m_iPos, pOprtDef[i]);
|
||||
|
||||
m_iSynFlags = noBC | noPOSTOP | noEND | noOPT | noIF | noELSE;
|
||||
break;
|
||||
|
||||
case cmIF:
|
||||
if (m_iSynFlags & noIF)
|
||||
Error(ecUNEXPECTED_CONDITIONAL, m_iPos, pOprtDef[i]);
|
||||
|
||||
m_iSynFlags = noBC | noPOSTOP | noEND | noOPT | noIF | noELSE;
|
||||
break;
|
||||
|
||||
default: // The operator is listed in c_DefaultOprt, but not here. This is a bad thing...
|
||||
Error(ecINTERNAL_ERROR);
|
||||
} // switch operator id
|
||||
|
||||
m_iPos += (int)len;
|
||||
a_Tok.Set( (ECmdCode)i, pOprtDef[i] );
|
||||
return true;
|
||||
} // if operator string found
|
||||
} // end of for all operator strings
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
bool ParserTokenReader::IsArgSep(token_type &a_Tok)
|
||||
{
|
||||
const char_type* szFormula = m_strFormula.c_str();
|
||||
|
||||
if (szFormula[m_iPos]==m_cArgSep)
|
||||
{
|
||||
// copy the separator into null terminated string
|
||||
char_type szSep[2];
|
||||
szSep[0] = m_cArgSep;
|
||||
szSep[1] = 0;
|
||||
|
||||
if (m_iSynFlags & noARG_SEP)
|
||||
Error(ecUNEXPECTED_ARG_SEP, m_iPos, szSep);
|
||||
|
||||
m_iSynFlags = noBC | noOPT | noEND | noARG_SEP | noPOSTOP | noASSIGN;
|
||||
m_iPos++;
|
||||
a_Tok.Set(cmARG_SEP, szSep);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Check for End of Formula.
|
||||
|
||||
\return true if an end of formula is found false otherwise.
|
||||
\param a_Tok [out] If an eof is found the corresponding token will be stored there.
|
||||
\throw nothrow
|
||||
\sa IsOprt, IsFunTok, IsStrFunTok, IsValTok, IsVarTok, IsString, IsInfixOpTok, IsPostOpTok
|
||||
*/
|
||||
bool ParserTokenReader::IsEOF(token_type &a_Tok)
|
||||
{
|
||||
const char_type* szFormula = m_strFormula.c_str();
|
||||
|
||||
// check for EOF
|
||||
if ( !szFormula[m_iPos] /*|| szFormula[m_iPos] == '\n'*/)
|
||||
{
|
||||
if ( m_iSynFlags & noEND )
|
||||
Error(ecUNEXPECTED_EOF, m_iPos);
|
||||
|
||||
if (m_iBrackets>0)
|
||||
Error(ecMISSING_PARENS, m_iPos, _T(")"));
|
||||
|
||||
m_iSynFlags = 0;
|
||||
a_Tok.Set(cmEND);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Check if a string position contains a unary infix operator.
|
||||
\return true if a function token has been found false otherwise.
|
||||
*/
|
||||
bool ParserTokenReader::IsInfixOpTok(token_type &a_Tok)
|
||||
{
|
||||
string_type sTok;
|
||||
int iEnd = ExtractToken(m_pParser->ValidInfixOprtChars(), sTok, m_iPos);
|
||||
if (iEnd==m_iPos)
|
||||
return false;
|
||||
|
||||
// iterate over all postfix operator strings
|
||||
funmap_type::const_reverse_iterator it = m_pInfixOprtDef->rbegin();
|
||||
for ( ; it!=m_pInfixOprtDef->rend(); ++it)
|
||||
{
|
||||
if (sTok.find(it->first)!=0)
|
||||
continue;
|
||||
|
||||
a_Tok.Set(it->second, it->first);
|
||||
m_iPos += (int)it->first.length();
|
||||
|
||||
if (m_iSynFlags & noINFIXOP)
|
||||
Error(ecUNEXPECTED_OPERATOR, m_iPos, a_Tok.GetAsString());
|
||||
|
||||
m_iSynFlags = noPOSTOP | noINFIXOP | noOPT | noBC | noSTR | noASSIGN;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
/*
|
||||
a_Tok.Set(item->second, sTok);
|
||||
m_iPos = (int)iEnd;
|
||||
|
||||
if (m_iSynFlags & noINFIXOP)
|
||||
Error(ecUNEXPECTED_OPERATOR, m_iPos, a_Tok.GetAsString());
|
||||
|
||||
m_iSynFlags = noPOSTOP | noINFIXOP | noOPT | noBC | noSTR | noASSIGN;
|
||||
return true;
|
||||
*/
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Check whether the token at a given position is a function token.
|
||||
\param a_Tok [out] If a value token is found it will be placed here.
|
||||
\throw ParserException if Syntaxflags do not allow a function at a_iPos
|
||||
\return true if a function token has been found false otherwise.
|
||||
\pre [assert] m_pParser!=0
|
||||
*/
|
||||
bool ParserTokenReader::IsFunTok(token_type &a_Tok)
|
||||
{
|
||||
string_type strTok;
|
||||
int iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos);
|
||||
if (iEnd==m_iPos)
|
||||
return false;
|
||||
|
||||
funmap_type::const_iterator item = m_pFunDef->find(strTok);
|
||||
if (item==m_pFunDef->end())
|
||||
return false;
|
||||
|
||||
// Check if the next sign is an opening bracket
|
||||
const char_type *szFormula = m_strFormula.c_str();
|
||||
if (szFormula[iEnd]!='(')
|
||||
return false;
|
||||
|
||||
a_Tok.Set(item->second, strTok);
|
||||
|
||||
m_iPos = (int)iEnd;
|
||||
if (m_iSynFlags & noFUN)
|
||||
Error(ecUNEXPECTED_FUN, m_iPos-(int)a_Tok.GetAsString().length(), a_Tok.GetAsString());
|
||||
|
||||
m_iSynFlags = noANY ^ noBO;
|
||||
return true;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Check if a string position contains a binary operator.
|
||||
\param a_Tok [out] Operator token if one is found. This can either be a binary operator or an infix operator token.
|
||||
\return true if an operator token has been found.
|
||||
*/
|
||||
bool ParserTokenReader::IsOprt(token_type &a_Tok)
|
||||
{
|
||||
const char_type *const szExpr = m_strFormula.c_str();
|
||||
string_type strTok;
|
||||
|
||||
int iEnd = ExtractOperatorToken(strTok, m_iPos);
|
||||
if (iEnd==m_iPos)
|
||||
return false;
|
||||
|
||||
// Check if the operator is a built in operator, if so ignore it here
|
||||
const char_type **const pOprtDef = m_pParser->GetOprtDef();
|
||||
for (int i=0; m_pParser->HasBuiltInOprt() && pOprtDef[i]; ++i)
|
||||
{
|
||||
if (string_type(pOprtDef[i])==strTok)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Note:
|
||||
// All tokens in oprt_bin_maptype are have been sorted by their length
|
||||
// Long operators must come first! Otherwise short names (like: "add") that
|
||||
// are part of long token names (like: "add123") will be found instead
|
||||
// of the long ones.
|
||||
// Length sorting is done with ascending length so we use a reverse iterator here.
|
||||
funmap_type::const_reverse_iterator it = m_pOprtDef->rbegin();
|
||||
for ( ; it!=m_pOprtDef->rend(); ++it)
|
||||
{
|
||||
const string_type &sID = it->first;
|
||||
if ( sID == string_type(szExpr + m_iPos, szExpr + m_iPos + sID.length()) )
|
||||
{
|
||||
a_Tok.Set(it->second, strTok);
|
||||
|
||||
// operator was found
|
||||
if (m_iSynFlags & noOPT)
|
||||
{
|
||||
// An operator was found but is not expected to occur at
|
||||
// this position of the formula, maybe it is an infix
|
||||
// operator, not a binary operator. Both operator types
|
||||
// can share characters in their identifiers.
|
||||
if ( IsInfixOpTok(a_Tok) )
|
||||
return true;
|
||||
else
|
||||
{
|
||||
// nope, no infix operator
|
||||
return false;
|
||||
//Error(ecUNEXPECTED_OPERATOR, m_iPos, a_Tok.GetAsString());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
m_iPos += (int)sID.length();
|
||||
m_iSynFlags = noBC | noOPT | noARG_SEP | noPOSTOP | noEND | noASSIGN;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Check if a string position contains a unary post value operator. */
|
||||
bool ParserTokenReader::IsPostOpTok(token_type &a_Tok)
|
||||
{
|
||||
// <ibg 20110629> Do not check for postfix operators if they are not allowed at
|
||||
// the current expression index.
|
||||
//
|
||||
// This will fix the bug reported here:
|
||||
//
|
||||
// http://sourceforge.net/tracker/index.php?func=detail&aid=3343891&group_id=137191&atid=737979
|
||||
//
|
||||
if (m_iSynFlags & noPOSTOP)
|
||||
return false;
|
||||
// </ibg>
|
||||
|
||||
// Tricky problem with equations like "3m+5":
|
||||
// m is a postfix operator, + is a valid sign for postfix operators and
|
||||
// for binary operators parser detects "m+" as operator string and
|
||||
// finds no matching postfix operator.
|
||||
//
|
||||
// This is a special case so this routine slightly differs from the other
|
||||
// token readers.
|
||||
|
||||
// Test if there could be a postfix operator
|
||||
string_type sTok;
|
||||
int iEnd = ExtractToken(m_pParser->ValidOprtChars(), sTok, m_iPos);
|
||||
if (iEnd==m_iPos)
|
||||
return false;
|
||||
|
||||
// iterate over all postfix operator strings
|
||||
funmap_type::const_reverse_iterator it = m_pPostOprtDef->rbegin();
|
||||
for ( ; it!=m_pPostOprtDef->rend(); ++it)
|
||||
{
|
||||
if (sTok.find(it->first)!=0)
|
||||
continue;
|
||||
|
||||
a_Tok.Set(it->second, sTok);
|
||||
m_iPos += (int)it->first.length();
|
||||
|
||||
m_iSynFlags = noVAL | noVAR | noFUN | noBO | noPOSTOP | noSTR | noASSIGN;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Check whether the token at a given position is a value token.
|
||||
|
||||
Value tokens are either values or constants.
|
||||
|
||||
\param a_Tok [out] If a value token is found it will be placed here.
|
||||
\return true if a value token has been found.
|
||||
*/
|
||||
bool ParserTokenReader::IsValTok(token_type &a_Tok)
|
||||
{
|
||||
assert(m_pConstDef);
|
||||
assert(m_pParser);
|
||||
|
||||
string_type strTok;
|
||||
value_type fVal(0);
|
||||
int iEnd(0);
|
||||
|
||||
// 2.) Check for user defined constant
|
||||
// Read everything that could be a constant name
|
||||
iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos);
|
||||
if (iEnd!=m_iPos)
|
||||
{
|
||||
valmap_type::const_iterator item = m_pConstDef->find(strTok);
|
||||
if (item!=m_pConstDef->end())
|
||||
{
|
||||
m_iPos = iEnd;
|
||||
a_Tok.SetVal(item->second, strTok);
|
||||
|
||||
if (m_iSynFlags & noVAL)
|
||||
Error(ecUNEXPECTED_VAL, m_iPos - (int)strTok.length(), strTok);
|
||||
|
||||
m_iSynFlags = noVAL | noVAR | noFUN | noBO | noINFIXOP | noSTR | noASSIGN;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// 3.call the value recognition functions provided by the user
|
||||
// Call user defined value recognition functions
|
||||
std::list<identfun_type>::const_iterator item = m_vIdentFun.begin();
|
||||
for (item = m_vIdentFun.begin(); item!=m_vIdentFun.end(); ++item)
|
||||
{
|
||||
int iStart = m_iPos;
|
||||
if ( (*item)(m_strFormula.c_str() + m_iPos, &m_iPos, &fVal)==1 )
|
||||
{
|
||||
// 2013-11-27 Issue 2: https://code.google.com/p/muparser/issues/detail?id=2
|
||||
strTok.assign(m_strFormula.c_str(), iStart, m_iPos-iStart);
|
||||
|
||||
if (m_iSynFlags & noVAL)
|
||||
Error(ecUNEXPECTED_VAL, m_iPos - (int)strTok.length(), strTok);
|
||||
|
||||
a_Tok.SetVal(fVal, strTok);
|
||||
m_iSynFlags = noVAL | noVAR | noFUN | noBO | noINFIXOP | noSTR | noASSIGN;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Check wheter a token at a given position is a variable token.
|
||||
\param a_Tok [out] If a variable token has been found it will be placed here.
|
||||
\return true if a variable token has been found.
|
||||
*/
|
||||
bool ParserTokenReader::IsVarTok(token_type &a_Tok)
|
||||
{
|
||||
if (m_pVarDef->empty())
|
||||
return false;
|
||||
|
||||
string_type strTok;
|
||||
int iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos);
|
||||
if (iEnd==m_iPos)
|
||||
return false;
|
||||
|
||||
varmap_type::const_iterator item = m_pVarDef->find(strTok);
|
||||
if (item==m_pVarDef->end())
|
||||
return false;
|
||||
|
||||
if (m_iSynFlags & noVAR)
|
||||
Error(ecUNEXPECTED_VAR, m_iPos, strTok);
|
||||
|
||||
m_pParser->OnDetectVar(&m_strFormula, m_iPos, iEnd);
|
||||
|
||||
m_iPos = iEnd;
|
||||
a_Tok.SetVar(item->second, strTok);
|
||||
m_UsedVar[item->first] = item->second; // Add variable to used-var-list
|
||||
|
||||
m_iSynFlags = noVAL | noVAR | noFUN | noBO | noINFIXOP | noSTR;
|
||||
|
||||
// Zur Info hier die SynFlags von IsVal():
|
||||
// m_iSynFlags = noVAL | noVAR | noFUN | noBO | noINFIXOP | noSTR | noASSIGN;
|
||||
return true;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
bool ParserTokenReader::IsStrVarTok(token_type &a_Tok)
|
||||
{
|
||||
if (!m_pStrVarDef || m_pStrVarDef->empty())
|
||||
return false;
|
||||
|
||||
string_type strTok;
|
||||
int iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos);
|
||||
if (iEnd==m_iPos)
|
||||
return false;
|
||||
|
||||
strmap_type::const_iterator item = m_pStrVarDef->find(strTok);
|
||||
if (item==m_pStrVarDef->end())
|
||||
return false;
|
||||
|
||||
if (m_iSynFlags & noSTR)
|
||||
Error(ecUNEXPECTED_VAR, m_iPos, strTok);
|
||||
|
||||
m_iPos = iEnd;
|
||||
if (!m_pParser->m_vStringVarBuf.size())
|
||||
Error(ecINTERNAL_ERROR);
|
||||
|
||||
a_Tok.SetString(m_pParser->m_vStringVarBuf[item->second], m_pParser->m_vStringVarBuf.size() );
|
||||
|
||||
m_iSynFlags = noANY ^ ( noBC | noOPT | noEND | noARG_SEP);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Check wheter a token at a given position is an undefined variable.
|
||||
|
||||
\param a_Tok [out] If a variable tom_pParser->m_vStringBufken has been found it will be placed here.
|
||||
\return true if a variable token has been found.
|
||||
\throw nothrow
|
||||
*/
|
||||
bool ParserTokenReader::IsUndefVarTok(token_type &a_Tok)
|
||||
{
|
||||
string_type strTok;
|
||||
int iEnd( ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos) );
|
||||
if ( iEnd==m_iPos )
|
||||
return false;
|
||||
|
||||
if (m_iSynFlags & noVAR)
|
||||
{
|
||||
// <ibg/> 20061021 added token string strTok instead of a_Tok.GetAsString() as the
|
||||
// token identifier.
|
||||
// related bug report:
|
||||
// http://sourceforge.net/tracker/index.php?func=detail&aid=1578779&group_id=137191&atid=737979
|
||||
Error(ecUNEXPECTED_VAR, m_iPos - (int)a_Tok.GetAsString().length(), strTok);
|
||||
}
|
||||
|
||||
// If a factory is available implicitely create new variables
|
||||
if (m_pFactory)
|
||||
{
|
||||
value_type *fVar = m_pFactory(strTok.c_str(), m_pFactoryData);
|
||||
a_Tok.SetVar(fVar, strTok );
|
||||
|
||||
// Do not use m_pParser->DefineVar( strTok, fVar );
|
||||
// in order to define the new variable, it will clear the
|
||||
// m_UsedVar array which will kill previously defined variables
|
||||
// from the list
|
||||
// This is safe because the new variable can never override an existing one
|
||||
// because they are checked first!
|
||||
(*m_pVarDef)[strTok] = fVar;
|
||||
m_UsedVar[strTok] = fVar; // Add variable to used-var-list
|
||||
}
|
||||
else
|
||||
{
|
||||
a_Tok.SetVar((value_type*)&m_fZero, strTok);
|
||||
m_UsedVar[strTok] = 0; // Add variable to used-var-list
|
||||
}
|
||||
|
||||
m_iPos = iEnd;
|
||||
|
||||
// Call the variable factory in order to let it define a new parser variable
|
||||
m_iSynFlags = noVAL | noVAR | noFUN | noBO | noPOSTOP | noINFIXOP | noSTR;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Check wheter a token at a given position is a string.
|
||||
\param a_Tok [out] If a variable token has been found it will be placed here.
|
||||
\return true if a string token has been found.
|
||||
\sa IsOprt, IsFunTok, IsStrFunTok, IsValTok, IsVarTok, IsEOF, IsInfixOpTok, IsPostOpTok
|
||||
\throw nothrow
|
||||
*/
|
||||
bool ParserTokenReader::IsString(token_type &a_Tok)
|
||||
{
|
||||
if (m_strFormula[m_iPos]!='"')
|
||||
return false;
|
||||
|
||||
string_type strBuf(&m_strFormula[m_iPos+1]);
|
||||
std::size_t iEnd(0), iSkip(0);
|
||||
|
||||
// parser over escaped '\"' end replace them with '"'
|
||||
for(iEnd=(int)strBuf.find( _T("\"") ); iEnd!=0 && iEnd!=string_type::npos; iEnd=(int)strBuf.find( _T("\""), iEnd))
|
||||
{
|
||||
if (strBuf[iEnd-1]!='\\') break;
|
||||
strBuf.replace(iEnd-1, 2, _T("\"") );
|
||||
iSkip++;
|
||||
}
|
||||
|
||||
if (iEnd==string_type::npos)
|
||||
Error(ecUNTERMINATED_STRING, m_iPos, _T("\"") );
|
||||
|
||||
string_type strTok(strBuf.begin(), strBuf.begin()+iEnd);
|
||||
|
||||
if (m_iSynFlags & noSTR)
|
||||
Error(ecUNEXPECTED_STR, m_iPos, strTok);
|
||||
|
||||
m_pParser->m_vStringBuf.push_back(strTok); // Store string in internal buffer
|
||||
a_Tok.SetString(strTok, m_pParser->m_vStringBuf.size());
|
||||
|
||||
m_iPos += (int)strTok.length() + 2 + (int)iSkip; // +2 wg Anführungszeichen; +iSkip für entfernte escape zeichen
|
||||
m_iSynFlags = noANY ^ ( noARG_SEP | noBC | noOPT | noEND );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Create an error containing the parse error position.
|
||||
|
||||
This function will create an Parser Exception object containing the error text and its position.
|
||||
|
||||
\param a_iErrc [in] The error code of type #EErrorCodes.
|
||||
\param a_iPos [in] The position where the error was detected.
|
||||
\param a_strTok [in] The token string representation associated with the error.
|
||||
\throw ParserException always throws thats the only purpose of this function.
|
||||
*/
|
||||
void ParserTokenReader::Error( EErrorCodes a_iErrc,
|
||||
int a_iPos,
|
||||
const string_type &a_sTok) const
|
||||
{
|
||||
m_pParser->Error(a_iErrc, a_iPos, a_sTok);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
void ParserTokenReader::SetArgSep(char_type cArgSep)
|
||||
{
|
||||
m_cArgSep = cArgSep;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
char_type ParserTokenReader::GetArgSep() const
|
||||
{
|
||||
return m_cArgSep;
|
||||
}
|
||||
} // namespace mu
|
||||
|
Loading…
Reference in a new issue