added latest version of muparser library

This commit is contained in:
Paolo Cignoni cignoni 2010-06-16 19:56:59 +00:00
parent c4dbd15743
commit 1cecdfef49
35 changed files with 19681 additions and 0 deletions

354
src/external/muparser_v132/Changes.txt vendored Normal file
View File

@ -0,0 +1,354 @@
__________
_____ __ __\______ \_____ _______ ______ ____ _______
/ \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
| Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
|__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
\/ \/ \/ \/
Copyright (C) 2010
Ingo Berg
History:
--------
Rev 1.00 : July 21 2004
-----------------------
* Initial release
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.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.03 : August 10 2004
-------------------------
* Support for user-defined unary post value 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, unary minus did not work correctly.
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.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.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.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.08 : November, 2004
-------------------------
* unpublished; experimental template version with respect to data type and underlying string
type (string <-> widestring).
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 dependancies 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.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.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.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 have been removed. If you want to use it with Borland either use the dll version or create your own project files. I can't do 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.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.24: 29. October, 2005
---------------------------
Changes:
Compatibility improvements:
* parser now works on 64 bit compilers
* (bytecode base datatype can now be changed freely)
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.26: (unofficial release)
---------------------------
New Features:
* Unary operator precedence can now be changed by the user.
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.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.29: Januar 2008
---------------------
Unrelease Version available only via SVN.
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.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.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

28
src/external/muparser_v132/Credits.txt vendored Normal file
View File

@ -0,0 +1,28 @@
######################################################################
# #
# __________ #
# _____ __ __\______ \_____ _______ ______ ____ _______ #
# / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ #
# | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ #
# |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| #
# \/ \/ \/ \/ #
# #
# Copyright (C) 2010 #
# Ingo Berg #
# #
######################################################################
Credits:
--------
I'd like to thank all the people contacting me with suggestions and
bug reports. Your feedback is always welcome and helps to improve this
project.
Especially I'd like to thank:
-----------------------------
Francesco Montorsi for setting up the new parser build system as well
as the SVN server at sourceforge. Ion Vasilief for Feedback,
suggestions and help with the MSVC6 adaptation, Giampaolo Belini for
his help in fixing bugs.

126
src/external/muparser_v132/Install.txt vendored Normal file
View File

@ -0,0 +1,126 @@
__________
_____ __ __\______ \_____ _______ ______ ____ _______
/ \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
| Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
|__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
\/ \/ \/ \/
Mathematical expressions parser library
Copyright (C) 2010 Ingo Berg (muparser{at}gmx.de)
Contents
========
1. Installation on win32
2. Installation on unix
2.1 Other miscellaneous info Unix-specific
3. Where to ask for help
1. Installation on win32
========================
muParser supports various win32 command-line compilers:
-> mingw
-> borland
-> watcom
-> microsoft CL
and provides also the project files for MSVC6 IDE.
In order to compile muParser from makefiles, open an MSDOS
prompt and then move to the muParser/build directory and
type:
mingw32-make -fmakefile.mingw for mingw
nmake -fmakefile.vc for msvc
make -fmakefile.bcc for borland
wmake -fmakefile.wat for watcom
All makefiles supports the following options:
# Set to 1 to build debug version [0,1]
# 0 - Release
# 1 - Debug
DEBUG = 0
# Set to 1 to build shared (DLL) version [0,1]
# 0 - Static
# 1 - DLL
SHARED = 0
# Set to 1 to compile samples [0,1]
SAMPLES = 1
The muParser library is created in the 'lib' folder and the sample
binaries are created in samples\example1 or samples\example2.
NOTE: samples\example1 can be compiled *only* when building
muParser as a STATIC library (SHARED=0).
samples\example2 can be compiled *only* when building
muParser as a SHARED library (SHARED=1).
2. Installation on Unix/Linux
=============================
muParser can be installed just extracting the sources somewhere
and then, from a terminal, typing:
cd [path to muParser]
./configure [--enable-shared=yes/no] [--enable-samples=yes/no]
[--enable-debug=yes/no]
make
[sudo*] make install
[sudo*] ldconfig
cd samples/example1
./example1
* = this command must be executed with root permissions and thus
you have to use 'sudo' or just 'su' to gain root access.
Note that installation and ldconfig are not strictly required unless
you built in shared mode.
The "make" step will create the muParser library in 'lib' and the
sample binary in samples/example1.
The samples/example2 is win32-specific and thus won't be built.
2.1 Other miscellaneous info Unix-specific
==========================================
If you don't like to have your muParser folder filled by temporary
files created by GCC, then you can do the following:
mkdir mybuild && cd mybuild && ../configure && make
to put all object files in the "mybuild" directory.
If you want to use muParser library in your programs, you can use
the pkg-config program (this works only if muParser was installed
with 'make install' !). The commands:
pkg-config muparser --cflags
pkg-config muparser --libs
will return all useful info you need to build your programs against
muParser !
3. Where to ask for help
========================
If you find problems with either compilation, installation or usage
of muParser, then you can ask in the muParser forum at:
https://sourceforge.net/forum/forum.php?forum_id=462843
For more info about muParser, visit:
http://sourceforge.net/projects/muparser/
http://muparser.sourceforge.net

28
src/external/muparser_v132/License.txt vendored Normal file
View File

@ -0,0 +1,28 @@
__________
_____ __ __\______ \_____ _______ ______ ____ _______
/ \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
| Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
|__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
\/ \/ \/ \/
Version 1.27
Copyright (C) 2004-2006 Ingo Berg (ingo_berg{at}gmx.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.

376
src/external/muparser_v132/Makefile.in vendored Normal file
View File

@ -0,0 +1,376 @@
# =========================================================================
# This makefile was generated by
# Bakefile 0.2.8 (http://www.bakefile.org)
# Do not modify, all changes will be overwritten!
# =========================================================================
@MAKE_SET@
prefix = @prefix@
exec_prefix = @exec_prefix@
datarootdir = @datarootdir@
INSTALL = @INSTALL@
SHARED_LD_CXX = @SHARED_LD_CXX@
LIBEXT = @LIBEXT@
LIBPREFIX = @LIBPREFIX@
SO_SUFFIX = @SO_SUFFIX@
DLLIMP_SUFFIX = @DLLIMP_SUFFIX@
EXEEXT = @EXEEXT@
LN_S = @LN_S@
SETFILE = @SETFILE@
PIC_FLAG = @PIC_FLAG@
SONAME_FLAG = @SONAME_FLAG@
STRIP = @STRIP@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_DIR = @INSTALL_DIR@
BK_DEPS = @BK_DEPS@
srcdir = @srcdir@
top_builddir = @top_builddir@
libdir = @libdir@
DLLPREFIX = @DLLPREFIX@
LIBS = @LIBS@
AR = @AR@
AROPTIONS = @AROPTIONS@
RANLIB = @RANLIB@
CXX = @CXX@
CXXFLAGS = @CXXFLAGS@
CPPFLAGS = @CPPFLAGS@
LDFLAGS = @LDFLAGS@
### Variables: ###
DESTDIR =
MUPARSER_LIB_CXXFLAGS = $(____DEBUG) $(____SHARED) $(____SHARED_0) \
-I$(srcdir)/include $(CPPFLAGS) $(CXXFLAGS)
MUPARSER_LIB_OBJECTS = \
muParser_lib_muParser.o \
muParser_lib_muParserBase.o \
muParser_lib_muParserBytecode.o \
muParser_lib_muParserCallback.o \
muParser_lib_muParserComplex.o \
muParser_lib_muParserDLL.o \
muParser_lib_muParserError.o \
muParser_lib_muParserInt.o \
muParser_lib_muParserTest.o \
muParser_lib_muParserTokenReader.o
MUPARSER_LIB_HEADERS = \
include/muParser.h \
include/muParserBase.h \
include/muParserBytecode.h \
include/muParserCallback.h \
include/muParserComplex.h \
include/muParserDLL.h \
include/muParserDef.h \
include/muParserError.h \
include/muParserFixes.h \
include/muParserInt.h \
include/muParserStack.h \
include/muParserTest.h \
include/muParserToken.h \
include/muParserTokenReader.h
MUPARSER_DLL_CXXFLAGS = $(____DEBUG) $(____SHARED) $(____SHARED_0) \
-I$(srcdir)/include $(PIC_FLAG) $(CPPFLAGS) $(CXXFLAGS)
MUPARSER_DLL_OBJECTS = \
muParser_dll_muParser.o \
muParser_dll_muParserBase.o \
muParser_dll_muParserBytecode.o \
muParser_dll_muParserCallback.o \
muParser_dll_muParserComplex.o \
muParser_dll_muParserDLL.o \
muParser_dll_muParserError.o \
muParser_dll_muParserInt.o \
muParser_dll_muParserTest.o \
muParser_dll_muParserTokenReader.o
MUPARSER_DLL_HEADERS = \
include/muParser.h \
include/muParserBase.h \
include/muParserBytecode.h \
include/muParserCallback.h \
include/muParserComplex.h \
include/muParserDLL.h \
include/muParserDef.h \
include/muParserError.h \
include/muParserFixes.h \
include/muParserInt.h \
include/muParserStack.h \
include/muParserTest.h \
include/muParserToken.h \
include/muParserTokenReader.h
EXAMPLE1_CXXFLAGS = $(____DEBUG) -I$(srcdir)/include $(CPPFLAGS) $(CXXFLAGS)
EXAMPLE1_OBJECTS = \
example1_Example1.o
### Conditionally set variables: ###
@COND_DEPS_TRACKING_0@CXXC = $(CXX)
@COND_DEPS_TRACKING_1@CXXC = $(BK_DEPS) $(CXX)
@COND_DEBUG_0@DEBUG_BUILD_POSTFIX =
@COND_DEBUG_1@DEBUG_BUILD_POSTFIX = d
@COND_SHARED_0@__muParser_lib___depname = \
@COND_SHARED_0@ $(top_builddir)/lib/$(LIBPREFIX)muparser$(DEBUG_BUILD_POSTFIX)$(LIBEXT)
@COND_SHARED_0@__install_muParser_lib___depname = install_muParser_lib
@COND_SHARED_0@__uninstall_muParser_lib___depname = uninstall_muParser_lib
@COND_SHARED_0@__install_muParser_lib_headers___depname = \
@COND_SHARED_0@ install_muParser_lib_headers
@COND_SHARED_0@__uninstall_muParser_lib_headers___depname = \
@COND_SHARED_0@ uninstall_muParser_lib_headers
COND_SHARED_1___muParser_dll___depname = \
$(top_builddir)/lib/$(DLLPREFIX)muparser$(DEBUG_BUILD_POSTFIX)$(__muParser_dll___targetsuf3)
@COND_SHARED_1@__muParser_dll___depname = $(COND_SHARED_1___muParser_dll___depname)
@COND_SHARED_1@__install_muParser_dll___depname = install_muParser_dll
@COND_SHARED_1@__uninstall_muParser_dll___depname = uninstall_muParser_dll
COND_PLATFORM_MACOSX_1___muParser_dll___macinstnamecmd = -install_name \
$(libdir)/$(DLLPREFIX)muparser$(DEBUG_BUILD_POSTFIX)$(__muParser_dll___targetsuf2)
@COND_PLATFORM_MACOSX_1@__muParser_dll___macinstnamecmd = $(COND_PLATFORM_MACOSX_1___muParser_dll___macinstnamecmd)
@COND_SHARED_1@__install_muParser_dll_headers___depname = \
@COND_SHARED_1@ install_muParser_dll_headers
@COND_SHARED_1@__uninstall_muParser_dll_headers___depname = \
@COND_SHARED_1@ uninstall_muParser_dll_headers
COND_PLATFORM_OS2_1___muParser_dll___importlib = -import \
$(top_builddir)/lib/$(LIBPREFIX)muparser$(DEBUG_BUILD_POSTFIX).$(DLLIMP_SUFFIX)
@COND_PLATFORM_OS2_1@__muParser_dll___importlib = $(COND_PLATFORM_OS2_1___muParser_dll___importlib)
COND_WINDOWS_IMPLIB_1___muParser_dll___importlib = \
-Wl,--out-implib=$(top_builddir)/lib/$(LIBPREFIX)muparser$(DEBUG_BUILD_POSTFIX).$(DLLIMP_SUFFIX)
@COND_WINDOWS_IMPLIB_1@__muParser_dll___importlib = $(COND_WINDOWS_IMPLIB_1___muParser_dll___importlib)
@COND_PLATFORM_MACOSX_0_USE_SOVERSION_1@__muParser_dll___targetsuf2 \
@COND_PLATFORM_MACOSX_0_USE_SOVERSION_1@ = .$(SO_SUFFIX).0
@COND_PLATFORM_MACOSX_1_USE_SOVERSION_1@__muParser_dll___targetsuf2 \
@COND_PLATFORM_MACOSX_1_USE_SOVERSION_1@ = .0.$(SO_SUFFIX)
@COND_USE_SOVERSION_0@__muParser_dll___targetsuf2 = .$(SO_SUFFIX)
@COND_PLATFORM_MACOSX_0_USE_SOVERCYGWIN_0_USE_SOVERSION_1@__muParser_dll___targetsuf3 \
@COND_PLATFORM_MACOSX_0_USE_SOVERCYGWIN_0_USE_SOVERSION_1@ = \
@COND_PLATFORM_MACOSX_0_USE_SOVERCYGWIN_0_USE_SOVERSION_1@ .$(SO_SUFFIX).0.0.0
@COND_PLATFORM_MACOSX_1_USE_SOVERSION_1@__muParser_dll___targetsuf3 \
@COND_PLATFORM_MACOSX_1_USE_SOVERSION_1@ = .0.0.0.$(SO_SUFFIX)
@COND_USE_SOVERSION_1_USE_SOVERSOLARIS_1@__muParser_dll___targetsuf3 \
@COND_USE_SOVERSION_1_USE_SOVERSOLARIS_1@ = .$(SO_SUFFIX).0
@COND_USE_SOVERCYGWIN_1_USE_SOVERSION_1@__muParser_dll___targetsuf3 \
@COND_USE_SOVERCYGWIN_1_USE_SOVERSION_1@ = -0.$(SO_SUFFIX)
@COND_USE_SOVERSION_0@__muParser_dll___targetsuf3 = .$(SO_SUFFIX)
COND_USE_SOVERLINUX_1___muParser_dll___soname_flags = \
$(SONAME_FLAG)$(DLLPREFIX)muparser$(DEBUG_BUILD_POSTFIX)$(__muParser_dll___targetsuf2)
@COND_USE_SOVERLINUX_1@__muParser_dll___soname_flags = $(COND_USE_SOVERLINUX_1___muParser_dll___soname_flags)
COND_USE_SOVERSOLARIS_1___muParser_dll___soname_flags = \
$(SONAME_FLAG)$(DLLPREFIX)muparser$(DEBUG_BUILD_POSTFIX)$(__muParser_dll___targetsuf3)
@COND_USE_SOVERSOLARIS_1@__muParser_dll___soname_flags = $(COND_USE_SOVERSOLARIS_1___muParser_dll___soname_flags)
COND_USE_SOTWOSYMLINKS_1___muParser_dll___so_symlinks_cmd = (cd \
$(top_builddir)/lib/; rm -f \
$(LIBPREFIX)muparser$(DEBUG_BUILD_POSTFIX).$(DLLIMP_SUFFIX) \
$(DLLPREFIX)muparser$(DEBUG_BUILD_POSTFIX)$(__muParser_dll___targetsuf2); \
$(LN_S) \
$(DLLPREFIX)muparser$(DEBUG_BUILD_POSTFIX)$(__muParser_dll___targetsuf3) \
$(DLLPREFIX)muparser$(DEBUG_BUILD_POSTFIX)$(__muParser_dll___targetsuf2); \
$(LN_S) \
$(DLLPREFIX)muparser$(DEBUG_BUILD_POSTFIX)$(__muParser_dll___targetsuf2) \
$(LIBPREFIX)muparser$(DEBUG_BUILD_POSTFIX).$(DLLIMP_SUFFIX))
@COND_USE_SOTWOSYMLINKS_1@__muParser_dll___so_symlinks_cmd = $(COND_USE_SOTWOSYMLINKS_1___muParser_dll___so_symlinks_cmd)
COND_USE_SOVERSOLARIS_1___muParser_dll___so_symlinks_cmd = (cd \
$(top_builddir)/lib/; rm -f \
$(LIBPREFIX)muparser$(DEBUG_BUILD_POSTFIX).$(DLLIMP_SUFFIX); $(LN_S) \
$(DLLPREFIX)muparser$(DEBUG_BUILD_POSTFIX)$(__muParser_dll___targetsuf3) \
$(LIBPREFIX)muparser$(DEBUG_BUILD_POSTFIX).$(DLLIMP_SUFFIX))
@COND_USE_SOVERSOLARIS_1@__muParser_dll___so_symlinks_cmd = $(COND_USE_SOVERSOLARIS_1___muParser_dll___so_symlinks_cmd)
COND_USE_SOTWOSYMLINKS_1___muParser_dll___so_symlinks_inst_cmd = rm -f \
$(LIBPREFIX)muparser$(DEBUG_BUILD_POSTFIX).$(DLLIMP_SUFFIX) \
$(DLLPREFIX)muparser$(DEBUG_BUILD_POSTFIX)$(__muParser_dll___targetsuf2); \
$(LN_S) \
$(DLLPREFIX)muparser$(DEBUG_BUILD_POSTFIX)$(__muParser_dll___targetsuf3) \
$(DLLPREFIX)muparser$(DEBUG_BUILD_POSTFIX)$(__muParser_dll___targetsuf2); \
$(LN_S) \
$(DLLPREFIX)muparser$(DEBUG_BUILD_POSTFIX)$(__muParser_dll___targetsuf2) \
$(LIBPREFIX)muparser$(DEBUG_BUILD_POSTFIX).$(DLLIMP_SUFFIX)
@COND_USE_SOTWOSYMLINKS_1@__muParser_dll___so_symlinks_inst_cmd = $(COND_USE_SOTWOSYMLINKS_1___muParser_dll___so_symlinks_inst_cmd)
COND_USE_SOVERSOLARIS_1___muParser_dll___so_symlinks_inst_cmd = rm -f \
$(LIBPREFIX)muparser$(DEBUG_BUILD_POSTFIX).$(DLLIMP_SUFFIX); $(LN_S) \
$(DLLPREFIX)muparser$(DEBUG_BUILD_POSTFIX)$(__muParser_dll___targetsuf3) \
$(LIBPREFIX)muparser$(DEBUG_BUILD_POSTFIX).$(DLLIMP_SUFFIX);
@COND_USE_SOVERSOLARIS_1@__muParser_dll___so_symlinks_inst_cmd = $(COND_USE_SOVERSOLARIS_1___muParser_dll___so_symlinks_inst_cmd)
COND_USE_SOTWOSYMLINKS_1___muParser_dll___so_symlinks_uninst_cmd = rm -f \
$(DLLPREFIX)muparser$(DEBUG_BUILD_POSTFIX)$(__muParser_dll___targetsuf2) \
$(LIBPREFIX)muparser$(DEBUG_BUILD_POSTFIX).$(DLLIMP_SUFFIX)
@COND_USE_SOTWOSYMLINKS_1@__muParser_dll___so_symlinks_uninst_cmd = $(COND_USE_SOTWOSYMLINKS_1___muParser_dll___so_symlinks_uninst_cmd)
@COND_USE_SOVERSOLARIS_1@__muParser_dll___so_symlinks_uninst_cmd \
@COND_USE_SOVERSOLARIS_1@ = rm -f \
@COND_USE_SOVERSOLARIS_1@ $(LIBPREFIX)muparser$(DEBUG_BUILD_POSTFIX).$(DLLIMP_SUFFIX)
@COND_PLATFORM_MACOSX_1@__muParser_dll___macver = \
@COND_PLATFORM_MACOSX_1@ -compatibility_version 1 -current_version 1
@COND_SAMPLES_1@__example1___depname = \
@COND_SAMPLES_1@ $(top_builddir)/samples/example1/example1$(EXEEXT)
@COND_PLATFORM_MAC_0@__example1___mac_setfilecmd = @true
@COND_PLATFORM_MAC_1@__example1___mac_setfilecmd = \
@COND_PLATFORM_MAC_1@ $(SETFILE) -t APPL \
@COND_PLATFORM_MAC_1@ $(top_builddir)/samples/example1/example1$(EXEEXT)
@COND_SHARED_0@____SHARED =
@COND_SHARED_1@____SHARED = -DMUPARSER_DLL
@COND_SHARED_0@____SHARED_0 =
@COND_SHARED_1@____SHARED_0 = -DMUPARSERLIB_EXPORTS
@COND_DEBUG_0@____DEBUG = -DNDEBUG
@COND_DEBUG_1@____DEBUG =
### Targets: ###
all: $(__muParser_lib___depname) $(__muParser_dll___depname) $(__example1___depname)
install: $(__install_muParser_lib___depname) $(__install_muParser_lib_headers___depname) $(__install_muParser_dll___depname) $(__install_muParser_dll_headers___depname)
$(INSTALL_DIR) $(DESTDIR)$(libdir)/pkgconfig
$(INSTALL_DATA) build/autoconf/muparser.pc $(DESTDIR)$(libdir)/pkgconfig
uninstall: $(__uninstall_muParser_lib___depname) $(__uninstall_muParser_lib_headers___depname) $(__uninstall_muParser_dll___depname) $(__uninstall_muParser_dll_headers___depname)
install-strip: install
$(STRIP) $(DESTDIR)$(libdir)/$(DLLPREFIX)muparser$(DEBUG_BUILD_POSTFIX)$(__muParser_dll___targetsuf3)
clean:
rm -rf ./.deps ./.pch
rm -f ./*.o
rm -f $(top_builddir)/lib/$(LIBPREFIX)muparser$(DEBUG_BUILD_POSTFIX)$(LIBEXT)
rm -f $(top_builddir)/lib/$(DLLPREFIX)muparser$(DEBUG_BUILD_POSTFIX)$(__muParser_dll___targetsuf3)
rm -f $(top_builddir)/lib/$(LIBPREFIX)muparser$(DEBUG_BUILD_POSTFIX).$(DLLIMP_SUFFIX)
rm -f $(top_builddir)/lib/$(LIBPREFIX)muparser$(DEBUG_BUILD_POSTFIX).$(DLLIMP_SUFFIX) $(top_builddir)/lib/$(DLLPREFIX)muparser$(DEBUG_BUILD_POSTFIX)$(__muParser_dll___targetsuf2)
rm -f $(top_builddir)/samples/example1/example1$(EXEEXT)
distclean: clean
rm -f config.cache config.log config.status bk-deps bk-make-pch shared-ld-sh Makefile
rm -f build/autoconf/muparser.pc
@COND_SHARED_0@$(top_builddir)/lib/$(LIBPREFIX)muparser$(DEBUG_BUILD_POSTFIX)$(LIBEXT): $(MUPARSER_LIB_OBJECTS)
@COND_SHARED_0@ rm -f $@
@COND_SHARED_0@ $(AR) $(AROPTIONS) $@ $(MUPARSER_LIB_OBJECTS)
@COND_SHARED_0@ $(RANLIB) $@
@COND_SHARED_0@install_muParser_lib: $(__muParser_lib___depname)
@COND_SHARED_0@ $(INSTALL_DIR) $(DESTDIR)$(libdir)
@COND_SHARED_0@ $(INSTALL_DATA) $(top_builddir)/lib/$(LIBPREFIX)muparser$(DEBUG_BUILD_POSTFIX)$(LIBEXT) $(DESTDIR)$(libdir)
@COND_SHARED_0@uninstall_muParser_lib:
@COND_SHARED_0@ rm -f $(DESTDIR)$(libdir)/$(LIBPREFIX)muparser$(DEBUG_BUILD_POSTFIX)$(LIBEXT)
@COND_SHARED_0@install_muParser_lib_headers:
@COND_SHARED_0@ $(INSTALL_DIR) $(DESTDIR)$(prefix)
@COND_SHARED_0@ for f in $(MUPARSER_LIB_HEADERS); do \
@COND_SHARED_0@ if test ! -d $(DESTDIR)$(prefix)/`dirname $$f` ; then \
@COND_SHARED_0@ $(INSTALL_DIR) $(DESTDIR)$(prefix)/`dirname $$f`; \
@COND_SHARED_0@ fi; \
@COND_SHARED_0@ $(INSTALL_DATA) $(srcdir)/$$f $(DESTDIR)$(prefix)/$$f; \
@COND_SHARED_0@ done
@COND_SHARED_0@uninstall_muParser_lib_headers:
@COND_SHARED_0@ for f in $(MUPARSER_LIB_HEADERS); do \
@COND_SHARED_0@ rm -f $(DESTDIR)$(prefix)/$$f; \
@COND_SHARED_0@ done
@COND_SHARED_1@$(top_builddir)/lib/$(DLLPREFIX)muparser$(DEBUG_BUILD_POSTFIX)$(__muParser_dll___targetsuf3): $(MUPARSER_DLL_OBJECTS)
@COND_SHARED_1@ $(SHARED_LD_CXX) $@ $(MUPARSER_DLL_OBJECTS) $(__muParser_dll___macinstnamecmd) $(__muParser_dll___importlib) $(__muParser_dll___soname_flags) $(__muParser_dll___macver) $(LDFLAGS) $(LIBS)
@COND_SHARED_1@
@COND_SHARED_1@ $(__muParser_dll___so_symlinks_cmd)
@COND_SHARED_1@install_muParser_dll: $(__muParser_dll___depname)
@COND_SHARED_1@ $(INSTALL_DIR) $(DESTDIR)$(libdir)
@COND_SHARED_1@ $(INSTALL_DATA) $(top_builddir)/lib/$(LIBPREFIX)muparser$(DEBUG_BUILD_POSTFIX).$(DLLIMP_SUFFIX) $(DESTDIR)$(libdir)
@COND_SHARED_1@ $(INSTALL_PROGRAM) $(top_builddir)/lib/$(DLLPREFIX)muparser$(DEBUG_BUILD_POSTFIX)$(__muParser_dll___targetsuf3) $(DESTDIR)$(libdir)
@COND_SHARED_1@ (cd $(DESTDIR)$(libdir) ; $(__muParser_dll___so_symlinks_inst_cmd))
@COND_SHARED_1@uninstall_muParser_dll:
@COND_SHARED_1@ rm -f $(DESTDIR)$(libdir)/$(LIBPREFIX)muparser$(DEBUG_BUILD_POSTFIX).$(DLLIMP_SUFFIX)
@COND_SHARED_1@ rm -f $(DESTDIR)$(libdir)/$(DLLPREFIX)muparser$(DEBUG_BUILD_POSTFIX)$(__muParser_dll___targetsuf3)
@COND_SHARED_1@ (cd $(DESTDIR)$(libdir) ; $(__muParser_dll___so_symlinks_uninst_cmd))
@COND_SHARED_1@install_muParser_dll_headers:
@COND_SHARED_1@ $(INSTALL_DIR) $(DESTDIR)$(prefix)
@COND_SHARED_1@ for f in $(MUPARSER_DLL_HEADERS); do \
@COND_SHARED_1@ if test ! -d $(DESTDIR)$(prefix)/`dirname $$f` ; then \
@COND_SHARED_1@ $(INSTALL_DIR) $(DESTDIR)$(prefix)/`dirname $$f`; \
@COND_SHARED_1@ fi; \
@COND_SHARED_1@ $(INSTALL_DATA) $(srcdir)/$$f $(DESTDIR)$(prefix)/$$f; \
@COND_SHARED_1@ done
@COND_SHARED_1@uninstall_muParser_dll_headers:
@COND_SHARED_1@ for f in $(MUPARSER_DLL_HEADERS); do \
@COND_SHARED_1@ rm -f $(DESTDIR)$(prefix)/$$f; \
@COND_SHARED_1@ done
@COND_SAMPLES_1@$(top_builddir)/samples/example1/example1$(EXEEXT): $(EXAMPLE1_OBJECTS) $(__muParser_lib___depname)
@COND_SAMPLES_1@ $(CXX) -o $@ $(EXAMPLE1_OBJECTS) -L$(top_builddir)/lib -L$(srcdir)/lib $(LDFLAGS) -lmuparser$(DEBUG_BUILD_POSTFIX) $(LIBS)
@COND_SAMPLES_1@
@COND_SAMPLES_1@ $(__example1___mac_setfilecmd)
lib: $(__muParser_lib___depname) $(__muParser_dll___depname)
samples: $(__example1___depname)
documentation:
( cd $(srcdir)/docs && doxygen )
muParser_lib_muParser.o: $(srcdir)/src/muParser.cpp
$(CXXC) -c -o $@ $(MUPARSER_LIB_CXXFLAGS) $(srcdir)/src/muParser.cpp
muParser_lib_muParserBase.o: $(srcdir)/src/muParserBase.cpp
$(CXXC) -c -o $@ $(MUPARSER_LIB_CXXFLAGS) $(srcdir)/src/muParserBase.cpp
muParser_lib_muParserBytecode.o: $(srcdir)/src/muParserBytecode.cpp
$(CXXC) -c -o $@ $(MUPARSER_LIB_CXXFLAGS) $(srcdir)/src/muParserBytecode.cpp
muParser_lib_muParserCallback.o: $(srcdir)/src/muParserCallback.cpp
$(CXXC) -c -o $@ $(MUPARSER_LIB_CXXFLAGS) $(srcdir)/src/muParserCallback.cpp
muParser_lib_muParserComplex.o: $(srcdir)/src/muParserComplex.cpp
$(CXXC) -c -o $@ $(MUPARSER_LIB_CXXFLAGS) $(srcdir)/src/muParserComplex.cpp
muParser_lib_muParserDLL.o: $(srcdir)/src/muParserDLL.cpp
$(CXXC) -c -o $@ $(MUPARSER_LIB_CXXFLAGS) $(srcdir)/src/muParserDLL.cpp
muParser_lib_muParserError.o: $(srcdir)/src/muParserError.cpp
$(CXXC) -c -o $@ $(MUPARSER_LIB_CXXFLAGS) $(srcdir)/src/muParserError.cpp
muParser_lib_muParserInt.o: $(srcdir)/src/muParserInt.cpp
$(CXXC) -c -o $@ $(MUPARSER_LIB_CXXFLAGS) $(srcdir)/src/muParserInt.cpp
muParser_lib_muParserTest.o: $(srcdir)/src/muParserTest.cpp
$(CXXC) -c -o $@ $(MUPARSER_LIB_CXXFLAGS) $(srcdir)/src/muParserTest.cpp
muParser_lib_muParserTokenReader.o: $(srcdir)/src/muParserTokenReader.cpp
$(CXXC) -c -o $@ $(MUPARSER_LIB_CXXFLAGS) $(srcdir)/src/muParserTokenReader.cpp
muParser_dll_muParser.o: $(srcdir)/src/muParser.cpp
$(CXXC) -c -o $@ $(MUPARSER_DLL_CXXFLAGS) $(srcdir)/src/muParser.cpp
muParser_dll_muParserBase.o: $(srcdir)/src/muParserBase.cpp
$(CXXC) -c -o $@ $(MUPARSER_DLL_CXXFLAGS) $(srcdir)/src/muParserBase.cpp
muParser_dll_muParserBytecode.o: $(srcdir)/src/muParserBytecode.cpp
$(CXXC) -c -o $@ $(MUPARSER_DLL_CXXFLAGS) $(srcdir)/src/muParserBytecode.cpp
muParser_dll_muParserCallback.o: $(srcdir)/src/muParserCallback.cpp
$(CXXC) -c -o $@ $(MUPARSER_DLL_CXXFLAGS) $(srcdir)/src/muParserCallback.cpp
muParser_dll_muParserComplex.o: $(srcdir)/src/muParserComplex.cpp
$(CXXC) -c -o $@ $(MUPARSER_DLL_CXXFLAGS) $(srcdir)/src/muParserComplex.cpp
muParser_dll_muParserDLL.o: $(srcdir)/src/muParserDLL.cpp
$(CXXC) -c -o $@ $(MUPARSER_DLL_CXXFLAGS) $(srcdir)/src/muParserDLL.cpp
muParser_dll_muParserError.o: $(srcdir)/src/muParserError.cpp
$(CXXC) -c -o $@ $(MUPARSER_DLL_CXXFLAGS) $(srcdir)/src/muParserError.cpp
muParser_dll_muParserInt.o: $(srcdir)/src/muParserInt.cpp
$(CXXC) -c -o $@ $(MUPARSER_DLL_CXXFLAGS) $(srcdir)/src/muParserInt.cpp
muParser_dll_muParserTest.o: $(srcdir)/src/muParserTest.cpp
$(CXXC) -c -o $@ $(MUPARSER_DLL_CXXFLAGS) $(srcdir)/src/muParserTest.cpp
muParser_dll_muParserTokenReader.o: $(srcdir)/src/muParserTokenReader.cpp
$(CXXC) -c -o $@ $(MUPARSER_DLL_CXXFLAGS) $(srcdir)/src/muParserTokenReader.cpp
example1_Example1.o: $(srcdir)/samples/example1/Example1.cpp
$(CXXC) -c -o $@ $(EXAMPLE1_CXXFLAGS) $(srcdir)/samples/example1/Example1.cpp
# Include dependency info, if present:
@IF_GNU_MAKE@-include ./.deps/*.d
.PHONY: all install uninstall clean distclean install_muParser_lib \
uninstall_muParser_lib install_muParser_lib_headers \
uninstall_muParser_lib_headers install_muParser_dll uninstall_muParser_dll \
install_muParser_dll_headers uninstall_muParser_dll_headers lib samples

9059
src/external/muparser_v132/configure vendored Executable file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,156 @@
/*
__________
_____ __ __\______ \_____ _______ ______ ____ _______
/ \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
| Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
|__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
\/ \/ \/ \/
Copyright (C) 2010 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>
#include <locale>
//--- Parser includes --------------------------------------------------------------------------
#include "muParserBase.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) 2010 Ingo Berg<br>
muparser(at)gmx.de
</small>
*/
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);
void SetDecSep(char_type cDecSep);
void SetThousandsSep(char_type cThousandsSep = 0);
void ResetLocale();
value_type Diff(value_type *a_Var,
value_type a_fPos,
value_type a_fEpsilon = 0) const;
private:
/** \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
{
return std::string(1, m_nGroup);
}
private:
int m_nGroup;
char_type m_cDecPoint;
char_type m_cThousandsSep;
};
// Trigonometric functions
static value_type Sin(value_type);
static value_type Cos(value_type);
static value_type Tan(value_type);
// arcus functions
static value_type ASin(value_type);
static value_type ACos(value_type);
static value_type ATan(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);
static value_type Ite(value_type, value_type, value_type);
// Prefix operators
// !!! Unary Minus is a MUST if you want to use negative signs !!!
static value_type UnaryMinus(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);
static std::locale s_locale; ///< The locale used by the parser
};
} // namespace mu
#endif

View File

@ -0,0 +1,283 @@
/*
__________
_____ __ __\______ \_____ _______ ______ ____ _______
/ \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
| Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
|__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
\/ \/ \/ \/
Copyright (C) 2010 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>
//--- 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).
Version 1.32 (20100113)
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.
\author (C) 2010 Ingo Berg
*/
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;
public:
/** \brief Type of the error class.
Included for backwards compatibility.
*/
typedef ParserError exception_type;
ParserBase();
ParserBase(const ParserBase &a_Parser);
ParserBase& operator=(const ParserBase &a_Parser);
virtual ~ParserBase();
//---------------------------------------------------------------------------
/** \brief Calculate the result.
A note on const correctness:
I consider it important that Calc is a const function.
Due to caching operations Calc changes only the state of internal variables with one exception
m_UsedVar this is reset during string parsing and accessible from the outside. Instead of making
Calc non const GetUsedVar is non const because it explicitely calls Eval() forcing this update.
\pre A formula must be set.
\pre Variables must have been set (if needed)
\sa #m_pParseFormula
\return The evaluation result
\throw ParseException if no Formula is set or in case of any other error related to the formula.
*/
inline value_type Eval() const
{
return (this->*m_pParseFormula)();
}
void SetExpr(const string_type &a_sExpr);
void SetVarFactory(facfun_type a_pFactory, void *pUserData = NULL);
void EnableOptimizer(bool a_bIsOn=true);
void EnableByteCode(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
*/
#define MUP_DEFINE_FUNC(TYPE) \
inline void DefineFun(const string_type &a_strName, TYPE a_pFun, bool a_bAllowOpt = true) \
{ \
AddCallback( a_strName, ParserCallback(a_pFun, a_bAllowOpt), \
m_FunDef, ValidNameChars() ); \
}
MUP_DEFINE_FUNC(fun_type0)
MUP_DEFINE_FUNC(fun_type1)
MUP_DEFINE_FUNC(fun_type2)
MUP_DEFINE_FUNC(fun_type3)
MUP_DEFINE_FUNC(fun_type4)
MUP_DEFINE_FUNC(fun_type5)
MUP_DEFINE_FUNC(multfun_type)
MUP_DEFINE_FUNC(strfun_type1)
MUP_DEFINE_FUNC(strfun_type2)
MUP_DEFINE_FUNC(strfun_type3)
#undef MUP_DEFINE_FUNC
void DefineOprt(const string_type &a_strName, fun_type2 a_pFun, unsigned a_iPri=0, 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() 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[];
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 ApplyBinOprt(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 ApplyNumFunc(const token_type &a_FunTok,
const std::vector<token_type> &a_vArg) const;
token_type ApplyStrFunc(const token_type &a_FunTok,
const std::vector<token_type> &a_vArg) const;
int GetOprtPri(const token_type &a_Tok) const;
value_type ParseString() const;
value_type ParseCmdCode() const;
value_type ParseValue() const;
void ClearFormula();
void CheckName(const string_type &a_strName, const string_type &a_CharSet) const;
#if defined(MUP_DUMP_STACK) | defined(MUP_DUMP_CMDCODE)
void StackDump(const ParserStack<token_type > &a_stVal,
const ParserStack<token_type > &a_stOprt) const;
#endif
/** \brief Pointer to the parser function.
Eval() calls the function whose address is stored there.
*/
mutable ParseFunction m_pParseFormula;
mutable const ParserByteCode::map_type *m_pCmdCode; ///< Formula converted to bytecode, points to the data of the bytecode class.
mutable ParserByteCode m_vByteCode; ///< 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_bOptimize; ///< Flag that indicates if the optimizer is on or off.
bool m_bUseByteCode; ///< Flag that indicates if bytecode parsing is on or off.
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 valbuf_type m_vStackBuffer; ///< This is merely a buffer used for the stack in the cmd parsing routine
};
} // namespace mu
#endif

View File

@ -0,0 +1,158 @@
/*
__________
_____ __ __\______ \_____ _______ ______ ____ _______
/ \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
| Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
|__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
\/ \/ \/ \/
Copyright (C) 2004-2009 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
{
/** \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, 2005 Ingo Berg
*/
class ParserByteCode
{
public:
/** \brief Underlying type of the container.
The bytecode is a vector of this type containing control codes,
values and pointers. Values and pointer will be casted to this
type before their storage.
*/
typedef bytecode_type map_type;
private:
/** \brief Token type for internal use only. */
typedef ParserToken<value_type, string_type> token_type;
/** \brief Core type of the bytecode. */
typedef std::vector<map_type> storage_type;
/** \brief Position in the Calculation array. */
unsigned m_iStackPos;
/** \brief Maximum size needed for the stack. */
std::size_t m_iMaxStackSize;
/** \brief Core type of the bytecode. */
storage_type m_vBase;
/** \brief Size of a value entry in the bytecode, relative to TMapType size. */
const int mc_iSizeVal;
/** \brief Size of a pointer, relative to size of underlying TMapType.
\attention The size is related to the size of TMapType not bytes!
*/
const int mc_iSizePtr;
/** \brief A value entry requires that much entires in the bytecode.
Value entry consists of:
<ul>
<li>One entry for Stack index</li>
<li>One entry for Token identifier</li>
<li>mc_iSizeVal entries for the value</li>
<ul>
\sa AddVal(TBaseData a_fVal)
*/
const int mc_iSizeValEntry;
void StorePtr(void *a_pAddr);
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 AddAssignOp(value_type *a_pVar);
void AddFun(void *a_pFun, int a_iArgc);
void AddStrFun(void *a_pFun, int a_iArgc, int a_iIdx);
void Finalize();
void clear();
std::size_t GetMaxStackSize() const;
std::size_t GetBufSize() const;
const map_type* GetRawData() const;
/** \brief Return size of a value entry.
That many bytecode entries are necessary to store a value.
\sa mc_iSizeVal
*/
unsigned GetValSize() const
{
return mc_iSizeVal;
}
/** \brief Return size of a pointer entry.
That many bytecode entries are necessary to store a pointer.
\sa mc_iSizePtr
*/
unsigned GetPtrSize() const
{
return mc_iSizePtr;
}
void RemoveValEntries(unsigned a_iNumber);
void AsciiDump();
};
} // namespace mu
#endif

View File

@ -0,0 +1,98 @@
/*
__________
_____ __ __\______ \_____ _______ ______ ____ _______
/ \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
| Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
|__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
\/ \/ \/ \/
Copyright (C) 2004-2008 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.
This class is not used for string function prototyping.
\author (C) 2004-2007 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 = -1, ECmdCode a_iCode=cmFUNC);
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(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;
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.
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

View File

@ -0,0 +1,83 @@
/*
__________
_____ __ __\______ \_____ _______ ______ ____ _______
/ \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
| Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
|__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
\/ \/ \/ \/
Copyright (C) 2010 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_COMPLEX_H
#define MU_PARSER_COMPLEX_H
#include "muParserBase.h"
#include <vector>
#include <complex>
/** \file
\brief This file contains a definition of a parser using complex numbers.
*/
namespace mu
{
/** \brief Mathematical expressions parser.
This version of the parser handles only complex numbers. It disables the built in operators
thus it is slower than muParser.
*/
class ParserComplex : private ParserBase
{
public:
typedef std::complex<float> complex_type;
ParserComplex();
using ParserBase::SetExpr;
complex_type Eval();
static complex_type UnpackToComplex(double val);
static double PackToDouble(const complex_type &val);
private:
// !! The unary Minus is a MUST, otherwise you cant use negative signs !!
static value_type UnaryMinus(value_type);
// 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 Sin(value_type);
static value_type Cos(value_type);
static value_type Tan(value_type);
static value_type Sqrt(value_type);
static int IsVal(const char_type* a_szExpr, int *a_iPos, value_type *a_iVal);
virtual void InitOprt();
virtual void InitCharSets();
virtual void InitFun();
virtual void InitConst();
};
} // namespace mu
#endif

View File

@ -0,0 +1,172 @@
/*
__________
_____ __ __\______ \_____ _______ ______ ____ _______
/ \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
| Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
|__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
\/ \/ \/ \/
Copyright (C) 2010 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)
#ifdef MUPARSERLIB_EXPORTS
#define API_EXPORT(TYPE) extern "C" __declspec(dllexport) TYPE __stdcall
#else
#define API_EXPORT(TYPE) extern __declspec(dllimport) TYPE __stdcall
#endif
#else
#define API_EXPORT(TYPE) TYPE
#endif
/** \file
\brief This file contains the DLL interface of muparser.
*/
// Basic types
typedef void* muParserHandle_t; // parser handle
typedef char muChar_t; // character type
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 (*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
//-----------------------------------------------------------------------------------------------------
//
//
// muParser C compatible bindings
//
//
//-----------------------------------------------------------------------------------------------------
// Basic operations / initialization
API_EXPORT(muParserHandle_t) mupCreate();
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);
// 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);
// 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_iPri1,
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) 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*);
#endif // include guard

View File

@ -0,0 +1,317 @@
/*
__________
_____ __ __\______ \_____ _______ ______ ____ _______
/ \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
| Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
|__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
\/ \/ \/ \/
Copyright (C) 2010 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("1.32")
/** \brief Define the base datatype for values.
This datatype must be a built in value type. You can not use custom classes.
It has been tested with float, double and long double types, int should
work as well.
*/
#define MUP_BASETYPE double
/** \brief Definition of the basic bytecode datatype.
This defines the smalles entity used in the bytecode.
*/
#define MUP_BYTECODE_TYPE long
#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
#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);
#ifndef _UNICODE
/** \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 << "Assertion \""#COND"\" failed: " \
<< __FILE__ << " line " \
<< __LINE__ << "."; \
throw ParserError( ss.str() ); \
}
#else
#define MUP_ASSERT(COND)
#endif // _UNICODE
#else
#define MUP_FAIL(MSG)
#define MUP_ASSERT(COND)
#endif
//------------------------------------------------------------------------------
//
// do not change anything beyond this point...
//
// !!! This section is devoted to macros that are used for debugging
// !!! or for features that are not fully implemented yet.
//
//#define MUP_DUMP_STACK
//#define MUP_DUMP_CMDCODE
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 ...
cmAND = 11, ///< Operator item: logical and
cmOR = 12, ///< Operator item: logical or
cmXOR = 13, ///< Operator item: logical xor
cmASSIGN = 14, ///< Operator item: Assignment operator
cmBO = 15, ///< Operator item: opening bracket
cmBC = 16, ///< Operator item: closing bracket
cmARG_SEP, ///< function argument separator
cmVAR, ///< variable item
cmVAL, ///< value item
cmFUNC, ///< Code for a function item
cmFUNC_STR, ///< Code for a function with a string parameter
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.
};
//------------------------------------------------------------------------------
/** \brief Parser operator precedence values. */
enum EPrec
{
// binary operators
prLOGIC = 1, ///< logic operators
prCMP = 2, ///< comparsion operators
prADD_SUB = 3, ///< addition
prMUL_DIV = 4, ///< multiplication/division
prPOW = 5, ///< power operator priority (highest)
// infix operators
prINFIX = 4, ///< Signs have a higher priority than ADD_SUB, but lower than power operator
prPOSTFIX = 4 ///< 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 bytecode type used by the parser.
The bytecode type depends on the value_type.
*/
typedef MUP_BYTECODE_TYPE bytecode_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 (*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 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*);
//------------------------------------------------------------------------------
/** \brief Static type checks
I took the static assert from boost, but did not want to
add boost as a dependency to this project. For the original go to:
http://www.boost.org/doc/html/boost_staticassert.html
*/
template <bool> struct STATIC_ASSERTION_FAILURE;
template <> struct STATIC_ASSERTION_FAILURE<true> {};
/** \brief This is a static typecheck.
If you get a compiler error here you tried to use an unsigned bytecode map type!
*/
typedef char MAP_TYPE_CANT_BE_UNSIGNED[ sizeof( STATIC_ASSERTION_FAILURE< bytecode_type(-1)<0 >) ];
} // end fo namespace
#endif

View File

@ -0,0 +1,166 @@
/*
__________
_____ __ __\______ \_____ _______ ______ ____ _______
/ \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
| Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
|__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
\/ \/ \/ \/
Copyright (C) 2004-2008 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.
ecBUILTIN_OVERLOAD = 19, ///< Trying to overload builtin operator
ecINVALID_FUN_PTR = 20, ///< Invalid callback function pointer
ecINVALID_VAR_PTR = 21, ///< Invalid variable pointer
ecEMPTY_EXPRESSION = 22, ///< The Expression is empty
ecNAME_CONFLICT = 23, ///< Name conflict
ecOPT_PRI = 24, ///< Invalid operator priority
//
ecDOMAIN_ERROR = 25, ///< catch division by zero, sqrt(-1), log(0) (currently unused)
ecDIV_BY_ZERO = 26, ///< Division by zero (currently unused)
ecGENERIC = 27, ///< Generic error
ecLOCALE = 28, ///< Conflict with current locale
// internal errors
ecINTERNAL_ERROR = 29, ///< 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.
Part of the math parser package.
\author Ingo Berg
*/
/* final */ 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(_T("(formula is not available)")),
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;
std::size_t 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

View File

@ -0,0 +1,200 @@
/*
__________
_____ __ __\______ \_____ _______ ______ ____ _______
/ \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
| Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
|__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
\/ \/ \/ \/
Copyright (C) 2010 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
//---------------------------------------------------------------------------
//
// MSVC6
//
//---------------------------------------------------------------------------
#if defined(_MSC_VER) && _MSC_VER==1200
/** \brief Macro to replace the MSVC6 auto_ptr with the _my_auto_ptr class.
Hijack auto_ptr and replace it with a version that actually does
what an auto_ptr normally does. If you use std::auto_ptr in your other code
might either explode or work much better. The original crap created
by Microsoft, called auto_ptr and bundled with MSVC6 is not standard compliant.
*/
#define auto_ptr _my_auto_ptr
// This is another stupidity that needs to be undone in order to de-pollute
// the global namespace!
#undef min
#undef max
namespace std
{
typedef ::size_t size_t;
//---------------------------------------------------------------------------
/** \brief MSVC6 fix: Dummy function to put rand into namespace std.
This is a hack for MSVC6 only. It's dirty, it's ugly and it works, provided
inlining is enabled. Necessary because I will not pollute or change my
code in order to adopt it to MSVC6 interpretation of how C++ should look like!
*/
inline int rand(void)
{
return ::rand();
}
//---------------------------------------------------------------------------
/** \brief MSVC6 fix: Dummy function to put strlen into namespace std.
This is a hack for MSVC6 only. It's dirty, it's ugly and it works, provided
inlining is enabled. Necessary because I will not pollute or change my
code in order to adopt it to MSVC6 interpretation of how C++ should look like!
*/
inline size_t strlen(const char *szMsg)
{
return ::strlen(szMsg);
}
//---------------------------------------------------------------------------
/** \brief MSVC6 fix: Dummy function to put strncmp into namespace std.
This is a hack for MSVC6 only. It's dirty, it's ugly and it works, provided
inlining is enabled. Necessary because I will not pollute or change my
code in order to adopt it to MSVC6 interpretation of how C++ should look like!
*/
inline int strncmp(const char *a, const char *b, size_t len)
{
return ::strncmp(a,b,len);
}
//---------------------------------------------------------------------------
template<typename T>
T max(T a, T b)
{
return (a>b) ? a : b;
}
//---------------------------------------------------------------------------
template<typename T>
T min(T a, T b)
{
return (a<b) ? a : b;
}
//---------------------------------------------------------------------------
/** Standard compliant auto_ptr redefinition for MSVC6.
The code is taken from VS.NET 2003, slightly modified to reduce
it's dependencies from other classes.
*/
template<class _Ty>
class _my_auto_ptr
{
public:
typedef _Ty element_type;
explicit _my_auto_ptr(_Ty *_Ptr = 0)
:_Myptr(_Ptr)
{}
_my_auto_ptr(_my_auto_ptr<_Ty>& _Right)
:_Myptr(_Right.release())
{}
template<class _Other>
operator _my_auto_ptr<_Other>()
{
return (_my_auto_ptr<_Other>(*this));
}
template<class _Other>
_my_auto_ptr<_Ty>& operator=(_my_auto_ptr<_Other>& _Right)
{
reset(_Right.release());
return (*this);
}
~auto_ptr() { delete _Myptr; }
_Ty& operator*() const { return (*_Myptr); }
_Ty *operator->() const { return (&**this); }
_Ty *get() const { return (_Myptr); }
_Ty *release()
{
_Ty *_Tmp = _Myptr;
_Myptr = 0;
return (_Tmp);
}
void reset(_Ty* _Ptr = 0)
{
if (_Ptr != _Myptr)
delete _Myptr;
_Myptr = _Ptr;
}
private:
_Ty *_Myptr;
}; // class _my_auto_ptr
} // namespace std
#endif // Microsoft Visual Studio Version 6.0
#endif // include guard

View File

@ -0,0 +1,97 @@
/*
__________
_____ __ __\______ \_____ _______ ______ ____ _______
/ \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
| Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
|__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
\/ \/ \/ \/
Copyright (C) 2004-2008 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 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 LogXor(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);
public:
ParserInt();
virtual void InitFun();
virtual void InitOprt();
virtual void InitConst();
virtual void InitCharSets();
};
} // namespace mu
#endif

View File

@ -0,0 +1,125 @@
/*
__________
_____ __ __\______ \_____ _______ ______ ____ _______
/ \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
| Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
|__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
\/ \/ \/ \/
Copyright (C) 2004-2006 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-2008 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.size()==0;
}
/** \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

View File

@ -0,0 +1,200 @@
/*
__________
_____ __ __\______ \_____ _______ ______ ____ _______
/ \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
| Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
|__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
\/ \/ \/ \/
Copyright (C) 2010 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-2006 Ingo Berg
*/
class ParserTester // final
{
private:
// 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 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 val;
}
static value_type StrFun2(const char_type* v1, value_type v2)
{
int val(0);
stringstream_type(v1) >> val;
return 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)
{
double val(0);
stringstream_type(a_szMsg) >> val;
return val;
// using namespace std; // atof is for some compilers in std for some not...
// return atof(a_szMsg);
}
// postfix operator callback
static value_type Milli(value_type v) { return v/(value_type)1e3; }
static int c_iCount;
int TestNames();
int TestSyntax();
int TestMultiArg();
int TestVolatile();
int TestPostFix();
int TestExpression();
int TestInfixOprt();
int TestBinOprt();
int TestVarConst();
int TestInterface();
int TestException();
int TestStrArg();
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 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);
};
} // namespace Test
} // namespace mu
#endif

View File

@ -0,0 +1,442 @@
/*
__________
_____ __ __\______ \_____ _______ ______ ____ _______
/ \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
| Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
|__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
\/ \/ \/ \/
Copyright (C) 2004-2008 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 Ingo Berg
*/
template<typename TBase, typename TString>
class ParserToken
{
public:
/** \brief Additional token flags. */
enum ETokFlags
{
flVOLATILE = 1 ///< Mark a token that depends on a variable or a function that is not conservative
};
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_iFlags; ///< Additional flags for the token.
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;
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_iFlags(0)
,m_iIdx(-1)
,m_strTok()
,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_iFlags = a_Tok.m_iFlags;
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 Add additional flags to the token.
Flags are currently used to mark volatile (non optimizeable) functions.
\sa m_iFlags, ETokFlags
*/
void AddFlags(int a_iFlags)
{
m_iFlags |= a_iFlags;
}
//------------------------------------------------------------------------------
/** \brief Check if a certain flag ist set.
\throw nothrow
*/
bool IsFlagSet(int a_iFlags) const
{
#if defined(_MSC_VER)
#pragma warning( disable : 4800 )
#endif
return (bool)(m_iFlags & a_iFlags);
#if defined(_MSC_VER)
#pragma warning( default : 4800 ) // int: Variable set to boolean value (may degrade performance)
#endif
}
//------------------------------------------------------------------------------
/** \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_iFlags = 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_iFlags = 0;
m_iIdx = -1;
if (!m_pCallback->IsOptimizable())
AddFlags(flVOLATILE);
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_iFlags = 0;
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_iFlags = 0;
m_strTok = a_strTok;
m_iIdx = -1;
m_pTok = (void*)a_pVar;
m_pCallback.reset(0);
AddFlags(ParserToken::flVOLATILE);
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_iFlags = 0;
m_strTok = a_strTok;
m_iIdx = static_cast<int>(a_iSize);
m_pTok = 0;
m_pCallback.reset(0);
AddFlags(ParserToken::flVOLATILE);
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();
}
//------------------------------------------------------------------------------
/** \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
*/
void* GetFuncAddr() const
{
return (m_pCallback.get()) ? 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

View File

@ -0,0 +1,155 @@
/*
__________
_____ __ __\______ \_____ _______ ______ ____ _______
/ \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
| Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
|__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
\/ \/ \/ \/
Copyright (C) 2004-2008 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 <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& GetFormula() const;
const varmap_type& GetUsedVar() const;
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"
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;
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::vector<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

View File

@ -0,0 +1 @@
Here goes the libraries (both static and shared) for this component.

View File

@ -0,0 +1,448 @@
//---------------------------------------------------------------------------
//
// __________
// _____ __ __\______ \_____ _______ ______ ____ _______
// / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
// | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
// |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
// \/ \/ \/ \/
// (C) 2010 Ingo Berg
//
// Example 1 - using the parser as a static library
//
//---------------------------------------------------------------------------
#include "muParserTest.h"
/** \brief This macro will enable mathematical constants like M_PI. */
#define _USE_MATH_DEFINES
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <string>
#include <iostream>
#include <locale>
#include <limits>
#include <ios>
#include <iomanip>
#include "muParser.h"
#include "muParserInt.h"
//#include "muParserComplex.h"
#if defined( USINGDLL ) && defined( _WIN32 )
#error This sample can be used only with STATIC builds of muParser (on win32)
#endif
using namespace std;
using namespace mu;
// Operator callback functions
value_type Mega(value_type a_fVal) { return a_fVal * 1e6; }
value_type Milli(value_type a_fVal) { return a_fVal / (value_type)1e3; }
value_type Rnd(value_type v) { return v*std::rand()/(value_type)(RAND_MAX+1.0); }
value_type Not(value_type v) { return v==0; }
value_type Add(value_type v1, value_type v2) { return v1+v2; }
value_type Mul(value_type v1, value_type v2) { return v1*v2; }
//---------------------------------------------------------------------------
value_type Or(value_type v1, value_type v2)
{
return v1!=1 || v2!=1;
}
//---------------------------------------------------------------------------
value_type StrFun2(const char_type *v1, value_type v2,value_type v3)
{
mu::console() << v1 << std::endl;
return v2+v3;
}
//---------------------------------------------------------------------------
value_type Ping()
{
mu::console() << "ping\n"; return 0;
}
//---------------------------------------------------------------------------
mu::value_type SampleQuery(const char_type *szMsg)
{
if (szMsg)
mu::console() << szMsg << std::endl;
return 999;
};
//---------------------------------------------------------------------------
// Factory function for creating new parser variables
// This could as well be a function performing database queries.
value_type* AddVariable(const char_type *a_szName, void *a_pUserData)
{
// I don't want dynamic allocation here, so i used this static buffer
// If you want dynamic allocation you must allocate all variables dynamically
// in order to delete them later on. Or you find other ways to keep track of
// variables that have been created implicitely.
static value_type afValBuf[100];
static int iVal = 0;
mu::console() << _T("Generating new variable \"")
<< a_szName << _T("\" (slots left: ")
<< 99-iVal << _T(")")
<< _T(" User data pointer is:")
<< std::hex << a_pUserData <<endl;
afValBuf[iVal] = 0;
if (iVal>=99)
throw mu::ParserError( _T("Variable buffer overflow.") );
return &afValBuf[iVal++];
}
//---------------------------------------------------------------------------
void Splash()
{
mu::console() << _T(" __________ \n");
mu::console() << _T(" _____ __ __\\______ \\_____ _______ ______ ____ _______\n");
mu::console() << _T(" / \\ | | \\| ___/\\__ \\ \\_ __ \\/ ___/_/ __ \\\\_ __ \\ \n");
mu::console() << _T(" | Y Y \\| | /| | / __ \\_| | \\/\\___ \\ \\ ___/ | | \\/ \n");
mu::console() << _T(" |__|_| /|____/ |____| (____ /|__| /____ > \\___ >|__| \n");
mu::console() << _T(" \\/ \\/ \\/ \\/ \n");
mu::console() << _T(" Version ") << Parser().GetVersion() << _T("\n");
mu::console() << _T(" (C) 2010 Ingo Berg\n");
}
//---------------------------------------------------------------------------
void SelfTest()
{
mu::console() << _T( "-----------------------------------------------------------\n");
mu::console() << _T( "Configuration:\n\n");
#if defined(_DEBUG)
mu::console() << _T( "- DEBUG build\n");
#else
mu::console() << _T( "- RELEASE build\n");
#endif
#if defined(_UNICODE)
mu::console() << _T( "- UNICODE build\n");
#else
mu::console() << _T( "- ASCII build\n");
#endif
mu::console() << _T( "-----------------------------------------------------------\n");
mu::console() << _T( "Running test suite:\n\n");
mu::Test::ParserTester pt;
pt.Run();
mu::console() << _T( "-----------------------------------------------------------\n");
mu::console() << _T( "Commands:\n\n");
mu::console() << _T( " list var - list parser variables\n");
mu::console() << _T( " list exprvar - list expression variables\n");
mu::console() << _T( " list const - list all numeric parser constants\n");
mu::console() << _T( " locale de - switch to german locale\n");
mu::console() << _T( " locale en - switch to english locale\n");
mu::console() << _T( " locale reset - reset locale\n");
mu::console() << _T( " quit - exits the parser\n");
mu::console() << _T( "\nConstants:\n\n");
mu::console() << _T( " \"_e\" 2.718281828459045235360287\n");
mu::console() << _T( " \"_pi\" 3.141592653589793238462643\n");
mu::console() << _T( "-----------------------------------------------------------\n");
}
////---------------------------------------------------------------------------
//void CheckLocale()
//{
// // Local names:
// // "C" - the classic C locale
// // "de_DE" - not for Windows?
// // "en_US" - not for Windows?
// // "German_germany" - For MSVC8
// try
// {
// std::locale loc("German_germany");
// console() << _T("Locale settings:\n");
// console() << _T(" Decimal point: '") << std::use_facet<numpunct<char_type> >(loc).decimal_point() << "'\n";
// console() << _T(" Thousands sep: '") << std::use_facet<numpunct<char_type> >(loc).thousands_sep() << "'\n";
// console() << _T(" Grouping: \"") << std::use_facet<numpunct<char_type> >(loc).grouping() << "\"\n";
// console() << _T(" True is named: \"") << std::use_facet<numpunct<char_type> >(loc).truename() << "\"\n";
// console() << _T(" False is named: \"") << std::use_facet<numpunct<char_type> >(loc).falsename() << "\"\n";
// console() << _T("-----------------------------------------------------------\n");
// }
// catch(...)
// {
// console() << _T("Locale settings:\n");
// console() << _T(" invalid locale name\n");
// console() << _T("-----------------------------------------------------------\n");
// }
//}
//---------------------------------------------------------------------------
void ListVar(const mu::ParserBase &parser)
{
// Query the used variables (must be done after calc)
mu::varmap_type variables = parser.GetVar();
if (!variables.size())
return;
cout << "\nParser variables:\n";
cout << "-----------------\n";
cout << "Number: " << (int)variables.size() << "\n";
varmap_type::const_iterator item = variables.begin();
for (; item!=variables.end(); ++item)
mu::console() << _T("Name: ") << item->first << _T(" Address: [0x") << item->second << _T("]\n");
}
//---------------------------------------------------------------------------
void ListConst(const mu::ParserBase &parser)
{
mu::console() << _T("\nParser constants:\n");
mu::console() << _T("-----------------\n");
mu::valmap_type cmap = parser.GetConst();
if (!cmap.size())
{
mu::console() << _T("Expression does not contain constants\n");
}
else
{
valmap_type::const_iterator item = cmap.begin();
for (; item!=cmap.end(); ++item)
mu::console() << _T(" ") << item->first << _T(" = ") << item->second << _T("\n");
}
}
//---------------------------------------------------------------------------
void ListExprVar(const mu::ParserBase &parser)
{
string_type sExpr = parser.GetExpr();
if (sExpr.length()==0)
{
cout << _T("Expression string is empty\n");
return;
}
// Query the used variables (must be done after calc)
mu::console() << _T("\nExpression variables:\n");
mu::console() << _T("---------------------\n");
mu::console() << _T("Expression: ") << parser.GetExpr() << _T("\n");
varmap_type variables = parser.GetUsedVar();
if (!variables.size())
{
mu::console() << _T("Expression does not contain variables\n");
}
else
{
mu::console() << _T("Number: ") << (int)variables.size() << _T("\n");
mu::varmap_type::const_iterator item = variables.begin();
for (; item!=variables.end(); ++item)
mu::console() << _T("Name: ") << item->first << _T(" Address: [0x") << item->second << _T("]\n");
}
}
//---------------------------------------------------------------------------
/** \brief Check for external keywords.
*/
bool CheckKeywords(const mu::char_type *a_szLine, mu::Parser &a_Parser)
{
string_type sLine(a_szLine);
if ( sLine == _T("quit") )
{
exit(0);
}
else if ( sLine == _T("list var") )
{
ListVar(a_Parser);
return true;
}
else if ( sLine == _T("list const") )
{
ListConst(a_Parser);
return true;
}
else if ( sLine == _T("list exprvar") )
{
ListExprVar(a_Parser);
return true;
}
else if ( sLine == _T("list const") )
{
ListConst(a_Parser);
return true;
}
else if ( sLine == _T("locale de") )
{
mu::console() << _T("Setting german locale: ArgSep=';' DecSep=',' ThousandsSep='.'\n");
a_Parser.SetArgSep(';');
a_Parser.SetDecSep(',');
a_Parser.SetThousandsSep('.');
return true;
}
else if ( sLine == _T("locale en") )
{
mu::console() << _T("Setting english locale: ArgSep=',' DecSep='.' ThousandsSep=''\n");
a_Parser.SetArgSep(',');
a_Parser.SetDecSep('.');
a_Parser.SetThousandsSep();
return true;
}
else if ( sLine == _T("locale reset") )
{
mu::console() << _T("Resetting locale\n");
a_Parser.ResetLocale();
return true;
}
return false;
}
//---------------------------------------------------------------------------
void CheckDiff()
{
mu::Parser parser;
value_type x = 1,
v1,
v2,
v3,
eps(pow(std::numeric_limits<value_type>::epsilon(), 0.2));
parser.DefineVar(_T("x"), &x);
parser.SetExpr(_T("_e^-x*sin(x)"));
v1 = parser.Diff(&x, 1),
v2 = parser.Diff(&x, 1, eps);
v3 = cos((value_type)1.0)/exp((value_type)1) - sin((value_type)1.0)/exp((value_type)1); //-0.110793765307;
mu::console() << parser.GetExpr() << "\n";
mu::console() << "v1 = " << v1 << "; v1-v3 = " << v1-v3 << "\n";
mu::console() << "v2 = " << v2 << "; v2-v3 = " << v2-v3 << "\n";
}
//---------------------------------------------------------------------------
void Calc()
{
mu::Parser parser;
mu::ParserInt int_parser;
// mu::ParserComplex cmplx_parser;
// Change locale settings if necessary
// function argument separator: sum(2;3;4) vs. sum(2,3,4)
// decimal separator: 3,14 vs. 3.14
// thousands separator: 1000000 vs 1.000.000
//#define USE_GERMAN_LOCALE
#ifdef USE_GERMAN_LOCALE
parser.SetArgSep(';');
parser.SetDecSep(',');
parser.SetThousandsSep('.');
#else
// this is the default, so i it's commented:
//parser.SetArgSep(',');
//parser.SetDecSep('.');
//parser.SetThousandsSep('');
#endif
// Add some variables
value_type vVarVal[] = { 1, 2 }; // Values of the parser variables
parser.DefineVar(_T("a"), &vVarVal[0]); // Assign Variable names and bind them to the C++ variables
parser.DefineVar(_T("b"), &vVarVal[1]);
parser.DefineStrConst(_T("strBuf"), _T("hello world") );
// Add user defined unary operators
parser.DefinePostfixOprt(_T("M"), Mega);
parser.DefinePostfixOprt(_T("m"), Milli);
parser.DefineInfixOprt(_T("!"), Not);
parser.DefineFun(_T("query"), SampleQuery, false);
parser.DefineFun(_T("rnd"), Rnd, false); // Add an unoptimizeable function
parser.DefineFun(_T("strfun2"), StrFun2, false); // Add an unoptimizeable function
parser.DefineFun(_T("ping"), Ping, false);
parser.DefineOprt(_T("add"), Add, 0);
parser.DefineOprt(_T("mul"), Mul, 1);
parser.DefineOprt(_T("$"), Mul, 1);
// Define the variable factory
parser.SetVarFactory(AddVariable, &parser);
for(;;)
{
try
{
string_type sLine;
std::getline(mu::console_in(), sLine);
if (CheckKeywords(sLine.c_str(), parser))
continue;
//#define MUP_EXAMPLE_INT_PARSER
//#define MUP_EXAMPLE_COMPLEX_PARSER
#ifdef MUP_EXAMPLE_INT_PARSER
int_parser.SetExpr(sLine);
mu::console() << int_parser.Eval() << "\n";
#elif defined MUP_EXAMPLE_COMPLEX_PARSER
cmplx_parser.SetExpr(sLine);
mu::console() << cmplx_parser.Eval() << "\n";
#else
if (!sLine.length())
continue;
parser.SetExpr(sLine);
mu::console() << std::setprecision(12);
// The first call to eval implicitely creates the bytecode, and resets
// an internal pointer to the bytecode parsing function. Next time you call Eval
// the bytecode is used automatically!
mu::console() << "Parsing from string (slow): " << parser.Eval() << "\n";
// the second call automatically uses the bytecode for calculation, no interaction needed
mu::console() << "Parsing from bytecode (fast): " << parser.Eval() << "\n";
// mu::console() << parser.GetExpr() << "\n";
#endif
}
catch(mu::Parser::exception_type &e)
{
mu::console() << _T("\nError:\n");
mu::console() << _T("------\n");
mu::console() << _T("Message: ") << e.GetMsg() << _T("\n");
mu::console() << _T("Expression: \"") << e.GetExpr() << _T("\"\n");
mu::console() << _T("Token: \"") << e.GetToken() << _T("\"\n");
mu::console() << _T("Position: ") << (int)e.GetPos() << _T("\n");
mu::console() << _T("Errc: ") << std::dec << e.GetCode() << _T("\n");
}
} // while running
}
//---------------------------------------------------------------------------
int main(int, char**)
{
Splash();
SelfTest();
// CheckLocale();
// CheckDiff();
mu::console() << _T("Enter an expression or a command:\n");
try
{
Calc();
}
catch(Parser::exception_type &e)
{
// Only erros raised during the initialization will end up here
// formula related errors are treated in Calc()
console() << _T("Initialization error: ") << e.GetMsg() << endl;
string_type sBuf;
console_in() >> sBuf;
}
catch(std::exception & /*exc*/)
{
// there is no unicode compliant way to query exc.what()
// so i'll leave it for this example.
console() << _T("Internal error aborting...\n");
}
return 0;
}

View File

@ -0,0 +1,18 @@
__________
_____ __ __\______ \_____ _______ ______ ____ _______
/ \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
| Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
|__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
\/ \/ \/ \/
Copyright (C) 2010
Ingo Berg
This sample demonstrates using muParsers C-interface. The C-Interface
is usefull when interfacing muParser from different languages such
as C#. This sample is intended for use with the MS-Windows OS.
You may need to copy the muparser.dll file generated in the ..\..\lib
folder in order to run this sample.

View File

@ -0,0 +1,350 @@
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "muParserDLL.h"
#define PARSER_CONST_PI 3.141592653589793238462643
#define PARSER_CONST_E 2.718281828459045235360287
#define PARSER_MAXVARS 10
//---------------------------------------------------------------------------
// Callbacks for postfix operators
double Mega(double a_fVal)
{
return a_fVal * 1.0e6;
}
double Milli(double a_fVal)
{
return a_fVal / 1.0e3;
}
double ZeroArg()
{
printf("i'm a function without arguments.\n");
return 123;
}
//---------------------------------------------------------------------------
// Callbacks for infix operators
double Not(double v) { return v==0; }
//---------------------------------------------------------------------------
// Function callbacks
double Rnd(double v) { return v * rand() / (double)(RAND_MAX+1.0); }
double SampleQuery(const char *szMsg)
{
if (szMsg)
printf("%s\n", szMsg);
return 999;
}
double Sum(const double *a_afArg, int a_iArgc)
{
double fRes=0;
int i=0;
for (i=0; i<a_iArgc; ++i)
fRes += a_afArg[i];
return fRes;
}
//---------------------------------------------------------------------------
// Binarty operator callbacks
muFloat_t Add(muFloat_t v1, muFloat_t v2)
{
return v1+v2;
}
muFloat_t Mul(muFloat_t v1, muFloat_t v2)
{
return v1*v2;
}
//---------------------------------------------------------------------------
// Factory function for creating new parser variables
// This could as well be a function performing database queries.
muFloat_t* AddVariable(const muChar_t* a_szName, void *pUserData)
{
static double afValBuf[PARSER_MAXVARS]; // I don't want dynamic allocation here
static int iVal = 0; // so i used this buffer
printf("Generating new variable \"%s\" (slots left: %d)\n", a_szName, PARSER_MAXVARS-iVal);
afValBuf[iVal] = 0;
if (iVal>=PARSER_MAXVARS-1)
{
printf("Variable buffer overflow.");
return NULL;
}
return &afValBuf[iVal++];
}
//---------------------------------------------------------------------------
void Intro(muParserHandle_t hParser)
{
printf(" __________ \n");
printf(" _____ __ __\\______ \\_____ _______ ______ ____ _______\n");
printf(" / \\ | | \\| ___/\\__ \\ \\_ __ \\/ ___/_/ __ \\\\_ __ \\ \n");
printf(" | Y Y \\| | /| | / __ \\_| | \\/\\___ \\ \\ ___/ | | \\/ \n");
printf(" |__|_| /|____/ |____| (____ /|__| /____ > \\___ >|__| \n");
printf(" \\/ \\/ \\/ \\/ \n");
printf(" Version %s (DLL)\n", mupGetVersion(hParser));
printf(" (C) 2010 Ingo Berg\n");
printf("---------------------------------------\n");
printf("Commands:\n");
printf(" list var - list parser variables\n");
printf(" list exprvar - list expression variables\n");
printf(" list const - list all numeric parser constants\n");
printf(" locale de - switch to german locale\n");
printf(" locale en - switch to english locale\n");
printf(" locale reset - reset locale\n");
printf(" quit - exits the parser\n\n");
printf("Constants:\n");
printf(" \"_e\" 2.718281828459045235360287\n");
printf(" \"_pi\" 3.141592653589793238462643\n");
printf("---------------------------------------\n");
printf("Please enter a formula:\n");
}
//---------------------------------------------------------------------------
// Callback function for parser errors
void OnError(muParserHandle_t hParser)
{
printf("\nError:\n");
printf("------\n");
printf("Message: \"%s\"\n", mupGetErrorMsg(hParser));
printf("Token: \"%s\"\n", mupGetErrorToken(hParser));
printf("Position: %d\n", mupGetErrorPos(hParser));
printf("Errc: %d\n", mupGetErrorCode(hParser));
}
//---------------------------------------------------------------------------
void ListVar(muParserHandle_t a_hParser)
{
int iNumVar = mupGetVarNum(a_hParser);
int i = 0;
if (iNumVar==0)
{
printf("No variables defined\n");
return;
}
printf("\nExpression variables:\n");
printf("---------------------\n");
printf("Number: %d\n", iNumVar);
for (i=0; i<iNumVar; ++i)
{
const muChar_t* szName = 0;
muFloat_t* pVar = 0;
mupGetVar(a_hParser, i, &szName, &pVar);
printf("Name: %s Address: [0x%x]\n", szName, (long long)pVar);
}
}
//---------------------------------------------------------------------------
void ListExprVar(muParserHandle_t a_hParser)
{
muInt_t iNumVar = mupGetExprVarNum(a_hParser),
i = 0;
if (iNumVar==0)
{
printf("Expression dos not contain variables\n");
return;
}
printf("\nExpression variables:\n");
printf("---------------------\n");
printf("Expression: %s\n", mupGetExpr(a_hParser) );
printf("Number: %d\n", iNumVar);
for (i=0; i<iNumVar; ++i)
{
const muChar_t* szName = 0;
muFloat_t* pVar = 0;
mupGetExprVar(a_hParser, i, &szName, &pVar);
printf("Name: %s Address: [0x%x]\n", szName, (long long)pVar);
}
}
//---------------------------------------------------------------------------
void ListConst(muParserHandle_t a_hParser)
{
muInt_t iNumVar = mupGetConstNum(a_hParser),
i = 0;
if (iNumVar==0)
{
printf("No constants defined\n");
return;
}
printf("\nParser constants:\n");
printf("---------------------\n");
printf("Number: %d", iNumVar);
for (i=0; i<iNumVar; ++i)
{
const muChar_t* szName = 0;
muFloat_t fVal = 0;
mupGetConst(a_hParser, i, &szName, &fVal);
printf(" %s = %f\n", szName, fVal);
}
}
//---------------------------------------------------------------------------
/** \brief Check for external keywords.
*/
muBool_t CheckKeywords(const char *a_szLine, muParserHandle_t a_hParser)
{
if (!strcmp(a_szLine, "quit"))
{
exit(0);
}
else if (!strcmp(a_szLine,"list var"))
{
ListVar(a_hParser);
return 1;
}
else if (!strcmp(a_szLine, "list exprvar"))
{
ListExprVar(a_hParser);
return 1;
}
else if (!strcmp(a_szLine, "list const"))
{
ListConst(a_hParser);
return 1;
}
else if (!strcmp(a_szLine, "locale de"))
{
printf("Setting german locale: ArgSep=';' DecSep=',' ThousandsSep='.'\n");
mupSetArgSep(a_hParser, ';');
mupSetDecSep(a_hParser, ',');
mupSetThousandsSep(a_hParser, '.');
return 1;
}
else if (!strcmp(a_szLine, "locale en"))
{
printf("Setting english locale: ArgSep=',' DecSep='.' ThousandsSep=''\n");
mupSetArgSep(a_hParser, ',');
mupSetDecSep(a_hParser, '.');
mupSetThousandsSep(a_hParser, 0);
return 1;
}
else if (!strcmp(a_szLine, "locale reset"))
{
printf("Resetting locale\n");
mupResetLocale(a_hParser);
return 1;
}
return 0;
}
//---------------------------------------------------------------------------
void Calc()
{
muChar_t szLine[100];
muFloat_t fVal = 0,
afVarVal[] = { 1, 2 }; // Values of the parser variables
muParserHandle_t hParser;
hParser = mupCreate(); // initialize the parser
Intro(hParser);
// Set an error handler [optional]
// the only function that does not take a parser instance handle
mupSetErrorHandler(hParser, OnError);
//#define GERMAN_LOCALS
#ifdef GERMAN_LOCALS
mupSetArgSep(hParser, ';');
mupSetDecSep(hParser, ',');
mupSetThousandsSep(hParser, '.');
#else
mupSetArgSep(hParser, ',');
mupSetDecSep(hParser, '.');
#endif
// Set a variable factory
mupSetVarFactory(hParser, AddVariable, NULL);
// Define parser variables and bind them to C++ variables [optional]
mupDefineConst(hParser, "const1", 1);
mupDefineConst(hParser, "const2", 2);
mupDefineStrConst(hParser, "strBuf", "Hallo welt");
// Define parser variables and bind them to C++ variables [optional]
mupDefineVar(hParser, "a", &afVarVal[0]);
mupDefineVar(hParser, "b", &afVarVal[1]);
// Define postfix operators [optional]
mupDefinePostfixOprt(hParser, "M", Mega, 0);
mupDefinePostfixOprt(hParser, "m", Milli, 0);
// Define infix operator [optional]
mupDefineInfixOprt(hParser, "!", Not, 0);
// Define functions [optional]
// mupDefineStrFun(hParser, "query", SampleQuery, 0); // Add an unoptimizeable function
mupDefineFun0(hParser, "zero", ZeroArg, 0);
mupDefineFun1(hParser, "rnd", Rnd, 0); // Add an unoptimizeable function
mupDefineFun1(hParser, "rnd2", Rnd, 1);
mupDefineMultFun(hParser, "_sum", Sum, 0); // "sum" is already a default function
// Define binary operators [optional]
mupDefineOprt(hParser, "add", Add, 0, 0);
mupDefineOprt(hParser, "mul", Mul, 1, 0);
while ( fgets(szLine, 99, stdin) )
{
szLine[strlen(szLine)-1] = 0; // overwrite the newline
if (CheckKeywords(szLine, hParser))
continue;
mupSetExpr(hParser, szLine);
fVal = mupEval(hParser);
// Without an Error handler function
// you must use this for error treatment:
//if (mupError(hParser))
//{
// printf("\nError:\n");
// printf("------\n");
// printf("Message: %s\n", mupGetErrorMsg(hParser) );
// printf("Token: %s\n", mupGetErrorToken(hParser) );
// printf("Position: %s\n", mupGetErrorPos(hParser) );
// printf("Errc: %s\n", mupGetErrorCode(hParser) );
// continue;
//}
if (!mupError(hParser))
printf("%f\n", fVal);
} // while
// finalle free the parser ressources
mupRelease(hParser);
}
//---------------------------------------------------------------------------
int main(int argc, char *argv[])
{
Calc();
}

View File

@ -0,0 +1,394 @@
/*
__________
_____ __ __\______ \_____ _______ ______ ____ _______
/ \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
| Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
|__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
\/ \/ \/ \/
Copyright (C) 2010 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"
//--- 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
{
std::locale Parser::s_locale;
//---------------------------------------------------------------------------
// Trigonometric function
value_type Parser::Sin(value_type v) { return sin(v); }
value_type Parser::Cos(value_type v) { return cos(v); }
value_type Parser::Tan(value_type v) { return tan(v); }
value_type Parser::ASin(value_type v) { return asin(v); }
value_type Parser::ACos(value_type v) { return acos(v); }
value_type Parser::ATan(value_type v) { return atan(v); }
value_type Parser::Sinh(value_type v) { return sinh(v); }
value_type Parser::Cosh(value_type v) { return cosh(v); }
value_type Parser::Tanh(value_type v) { return tanh(v); }
value_type Parser::ASinh(value_type v) { return log(v + sqrt(v * v + 1)); }
value_type Parser::ACosh(value_type v) { return log(v + sqrt(v * v - 1)); }
value_type Parser::ATanh(value_type v) { return ((value_type)0.5 * log((1 + v) / (1 - v))); }
//---------------------------------------------------------------------------
// Logarithm functions
value_type Parser::Log2(value_type v) { return log(v)/log((value_type)2); } // Logarithm base 2
value_type Parser::Log10(value_type v) { return log10(v); } // Logarithm base 10
value_type Parser::Ln(value_type v) { return log(v); } // Logarithm base e (natural logarithm)
//---------------------------------------------------------------------------
// misc
value_type Parser::Exp(value_type v) { return exp(v); }
value_type Parser::Abs(value_type v) { return fabs(v); }
value_type Parser::Sqrt(value_type v) { return sqrt(v); }
value_type Parser::Rint(value_type v) { return floor(v + (value_type)0.5); }
value_type Parser::Sign(value_type v) { return (value_type)((v<0) ? -1 : (v>0) ? 1 : 0); }
//---------------------------------------------------------------------------
/** \brief Conditional (if then else).
\param v1 Condition
\param v2 First value
\param v3 Second value
\return v2 if v1!=0 v3 otherwise.
*/
value_type Parser::Ite(value_type v1, value_type v2, value_type v3)
{
return (v1) ? v2 : v3;
}
//---------------------------------------------------------------------------
/** \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 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/(double)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()
{
// For some reason locale initialization in the dll fails when done in the static
// constructor. I have to do it here
static bool bInitLocale = true;
if (bInitLocale)
{
Parser::s_locale = std::locale(std::locale::classic(), new change_dec_sep<char_type>('.'));
bInitLocale = false;
}
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()
{
// 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);
// 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"), Log10);
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);
DefineFun(_T("if"), Ite);
// 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 Set the decimal separator.
\param cDecSep Decimal separator as a character value.
\sa SetThousandsSep
By default muparser uses the "C" locale. The decimal separator of this
locale is overwritten by the one provided here.
*/
void Parser::SetDecSep(char_type cDecSep)
{
char_type cThousandsSep = std::use_facet< change_dec_sep<char_type> >(s_locale).thousands_sep();
s_locale = std::locale(std::locale("C"), new change_dec_sep<char_type>(cDecSep, cThousandsSep));
}
//---------------------------------------------------------------------------
/** \brief Sets the thousands operator.
\param cThousandsSep The thousands separator as a character
\sa SetDecSep
By default muparser uses the "C" locale. The thousands separator of this
locale is overwritten by the one provided here.
*/
void Parser::SetThousandsSep(char_type cThousandsSep)
{
char_type cDecSep = std::use_facet< change_dec_sep<char_type> >(s_locale).decimal_point();
s_locale = std::locale(std::locale("C"), new change_dec_sep<char_type>(cDecSep, cThousandsSep));
}
//---------------------------------------------------------------------------
/** \brief Resets the locale.
The default locale used "." as decimal separator, no thousands separator and
"," as function argument separator.
*/
void Parser::ResetLocale()
{
s_locale = std::locale(std::locale("C"), new change_dec_sep<char_type>('.'));
SetArgSep(',');
}
//---------------------------------------------------------------------------
/** \brief Initialize operators.
By default only the unary minus operator is added.
*/
void Parser::InitOprt()
{
DefineInfixOprt(_T("-"), UnaryMinus);
}
//---------------------------------------------------------------------------
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
numerical_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 doesnt provide
// his own epsilon
if (fEpsilon==0)
fEpsilon = (a_fPos==0) ? (value_type)1e-10 : 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

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,407 @@
/*
__________
_____ __ __\______ \_____ _______ ______ ____ _______
/ \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
| Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
|__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
\/ \/ \/ \/
Copyright (C) 2010 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 <cassert>
#include <string>
#include <stack>
#include <vector>
#include <iostream>
#include "muParserDef.h"
#include "muParserError.h"
#include "muParserToken.h"
/** \file
\brief Implementation of the parser bytecode class.
*/
namespace mu
{
//---------------------------------------------------------------------------
/** Bytecode default constructor. */
ParserByteCode::ParserByteCode()
:m_iStackPos(0)
,m_iMaxStackSize(0)
,m_vBase()
,mc_iSizeVal( std::max( (int)sizeof(value_type) / (int)sizeof(map_type), 1 ) )
,mc_iSizePtr( std::max( (int)sizeof(value_type*) / (int)sizeof(map_type), 1 ) )
,mc_iSizeValEntry( 2 + mc_iSizeVal)
{
m_vBase.reserve(1000);
}
//---------------------------------------------------------------------------
/** \brief Copy constructor.
Implemented in Terms of Assign(const ParserByteCode &a_ByteCode)
*/
ParserByteCode::ParserByteCode(const ParserByteCode &a_ByteCode)
:mc_iSizeVal( sizeof(value_type)/sizeof(map_type) )
,mc_iSizePtr( sizeof(value_type*) / sizeof(map_type) )
,mc_iSizeValEntry( 2 + mc_iSizeVal)
{
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;
}
//---------------------------------------------------------------------------
/** \brief Store an address in bytecode.
\param a_pAddr Address to be stored.
\throw nothrow
*/
void ParserByteCode::StorePtr(void *a_pAddr)
{
#if defined(_MSC_VER)
#pragma warning( disable : 4311 )
#endif
// demo code for packing / unpacking pointers into bytecode
// void *ptr(NULL);
// double **pVal;
// double fVal;
// map_type dbg[2];
// dbg[0] = *( reinterpret_cast<map_type*>(&a_pAddr) ),
// dbg[1] = *( reinterpret_cast<map_type*>(&a_pAddr) + 1 );
// Version 1:
// *( (map_type*)&ptr+0) = dbg[0];
// *( (map_type*)&ptr+1) = dbg[1];
// Version 2:
// memcpy(&ptr, dbg, sizeof(dbg));
// Version 3:
// pVal = (double**)dbg;
// fVal = **(double**)dbg;
for (int i=0; i<mc_iSizePtr; ++i)
m_vBase.push_back( *( reinterpret_cast<map_type*>(&a_pAddr) + i ) );
#if defined(_MSC_VER)
#pragma warning( default : 4311 )
#endif
}
//---------------------------------------------------------------------------
/** \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_vBase = a_ByteCode.m_vBase;
m_iMaxStackSize = a_ByteCode.m_iMaxStackSize;
}
//---------------------------------------------------------------------------
/** \brief Add a Variable pointer to bytecode.
\param a_pVar Pointer to be added.
\throw nothrow
*/
void ParserByteCode::AddVar(value_type *a_pVar)
{
m_vBase.push_back( ++m_iStackPos );
m_vBase.push_back( cmVAR );
m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos);
StorePtr(a_pVar);
const int iSize = mc_iSizeVal - mc_iSizePtr;
assert(iSize>=0);
// Make sure variable entries have the same size as value entries.
// (necessary for optimization; fill with zeros)
for (int i=0; i<iSize; ++i)
m_vBase.push_back(0);
}
//---------------------------------------------------------------------------
/** \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_vBase.push_back( ++m_iStackPos );
m_vBase.push_back( cmVAL );
m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos);
for (int i=0; i<mc_iSizeVal; ++i)
m_vBase.push_back( *(reinterpret_cast<map_type*>(&a_fVal) + i) );
}
//---------------------------------------------------------------------------
/** \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)
{
m_vBase.push_back(--m_iStackPos);
m_vBase.push_back(a_Oprt);
}
//---------------------------------------------------------------------------
/** \brief Add an assignement 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_vBase.push_back(--m_iStackPos);
m_vBase.push_back(cmASSIGN);
StorePtr(a_pVar);
}
//---------------------------------------------------------------------------
/** \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(void *a_pFun, int a_iArgc)
{
if (a_iArgc>=0)
{
m_iStackPos = m_iStackPos - a_iArgc + 1;
}
else
{
m_iStackPos = m_iStackPos + a_iArgc + 1;
}
m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos);
m_vBase.push_back(m_iStackPos);
m_vBase.push_back(cmFUNC);
m_vBase.push_back(a_iArgc);
StorePtr(a_pFun);
}
//---------------------------------------------------------------------------
/** \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(void *a_pFun, int a_iArgc, int a_iIdx)
{
m_iStackPos = m_iStackPos - a_iArgc + 1;
m_vBase.push_back(m_iStackPos);
m_vBase.push_back(cmFUNC_STR);
m_vBase.push_back(a_iArgc);
m_vBase.push_back(a_iIdx);
m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos);
StorePtr(a_pFun);
}
//---------------------------------------------------------------------------
/** \brief Add end marker to bytecode.
\throw nothrow
*/
void ParserByteCode::Finalize()
{
m_vBase.push_back(cmEND);
m_vBase.push_back(cmEND);
// m_vBase.push_back(cmEND);
// shrink bytecode vector to fit
storage_type(m_vBase).swap(m_vBase);
}
//---------------------------------------------------------------------------
/** \brief Get Pointer to bytecode data storage. */
const ParserByteCode::map_type* ParserByteCode::GetRawData() const
{
assert(m_vBase.size());
return &m_vBase[0];
}
//---------------------------------------------------------------------------
std::size_t ParserByteCode::GetMaxStackSize() const
{
return m_iMaxStackSize+1;
}
//---------------------------------------------------------------------------
std::size_t ParserByteCode::GetBufSize() const
{
return m_vBase.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_vBase.clear();
m_iStackPos = 0;
m_iMaxStackSize = 0;
}
//---------------------------------------------------------------------------
/** \brief Remove a value number of entries from the bytecode.
\attention Currently I don't test if the entries are really value entries.
*/
void ParserByteCode::RemoveValEntries(unsigned a_iNumber)
{
unsigned iSize = a_iNumber * mc_iSizeValEntry;
assert( m_vBase.size() >= iSize );
m_vBase.resize(m_vBase.size()-iSize);
assert(m_iStackPos >= a_iNumber);
m_iStackPos -= (a_iNumber);
}
//---------------------------------------------------------------------------
/** \brief Dump bytecode (for debugging only!). */
void ParserByteCode::AsciiDump()
{
if (!m_vBase.size())
{
std::cout << "No bytecode available\n";
return;
}
std::cout << "Entries:" << (int)m_vBase.size()
<< " (ValSize:" << mc_iSizeVal
<< " entries, PtrSize:" << mc_iSizePtr
<< " entries, MapSize:" << sizeof(map_type)
<< " byte)\n";
int i = 0;
while ( i<(int)m_vBase.size() && m_vBase[i] != cmEND)
{
std::cout << "IDX[" << (int)m_vBase[i++] << "]\t";
switch (m_vBase[i])
{
case cmVAL: std::cout << "VAL "; ++i;
std::cout << "[" << *( reinterpret_cast<double*>(&m_vBase[i]) ) << "]\n";
i += mc_iSizeVal;
break;
case cmVAR: std::cout << "VAR "; ++i;
std::cout << "[ADDR: 0x" << std::hex << *(value_type**)&m_vBase[i] << "]\n";
i += mc_iSizePtr;
// Variable entries have the same size like value entries
// the remaining spave must be skipped
i+= std::max(mc_iSizeVal - mc_iSizePtr, 0);
break;
case cmFUNC:
std::cout << "CALL\t"; ++i;
std::cout << "[ARG:" << std::dec << (int)m_vBase[i] << "]"; ++i;
std::cout << "[ADDR: 0x" << std::hex << *(value_type**)&m_vBase[i] << "]\n";
i += mc_iSizePtr;
break;
case cmFUNC_STR:
std::cout << "CALL STRFUNC\t"; ++i;
std::cout << "[ARG:" << std::dec << (int)m_vBase[i] << "]"; ++i;
std::cout << "[IDX:" << std::dec << (int)m_vBase[i] << "]"; ++i;
std::cout << "[ADDR: 0x" << *(value_type**)&m_vBase[i] << "]\n";
i += mc_iSizePtr;
break;
case cmLT: std::cout << "LT\n"; ++i; break;
case cmGT: std::cout << "GT\n"; ++i; break;
case cmLE: std::cout << "LE\n"; ++i; break;
case cmGE: std::cout << "GE\n"; ++i; break;
case cmEQ: std::cout << "EQ\n"; ++i; break;
case cmNEQ: std::cout << "NEQ\n"; ++i; break;
case cmADD: std::cout << "ADD\n"; ++i; break;
case cmAND: std::cout << "AND\n"; ++i; break;
case cmOR: std::cout << "OR\n"; ++i; break;
case cmXOR: std::cout << "XOR\n"; ++i; break;
case cmSUB: std::cout << "SUB\n"; ++i; break;
case cmMUL: std::cout << "MUL\n"; ++i; break;
case cmDIV: std::cout << "DIV\n"; ++i; break;
case cmPOW: std::cout << "POW\n"; ++i; break;
case cmASSIGN:
std::cout << "ASSIGN\t"; ++i;
std::cout << "[ADDR: 0x" << *(value_type**)&m_vBase[i] << "]\n";
i += mc_iSizePtr;
break;
default: std::cout << "(unknown code: " << (int)m_vBase[i] << ")\n";
++i;
break;
} // switch cmdCode
} // while bytecode
std::cout << "END" << std::endl;
}
} // namespace mu

View File

@ -0,0 +1,241 @@
/*
__________
_____ __ __\______ \_____ _______ ______ ____ _______
/ \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
| Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
|__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
\/ \/ \/ \/
Copyright (C) 2004-2008 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_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_iCode(a_iCode)
,m_iType(tpDBL)
,m_bAllowOpti(a_bAllowOpti)
{}
//---------------------------------------------------------------------------
ParserCallback::ParserCallback( fun_type2 a_pFun, bool a_bAllowOpti, int a_iPrec, ECmdCode a_iCode)
:m_pFun((void*)a_pFun)
,m_iArgc(2)
,m_iPri(a_iPrec)
,m_iCode(a_iCode)
,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_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_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_iCode(cmFUNC)
,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_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_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_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_iCode(cmFUNC_STR)
,m_iType(tpSTR)
,m_bAllowOpti(a_bAllowOpti)
{}
//---------------------------------------------------------------------------
/** \brief Default constructor.
\throw nothrow
*/
ParserCallback::ParserCallback()
:m_pFun(0)
,m_iArgc(0)
,m_iCode(cmUNKNOWN)
,m_iType(tpVOID)
,m_bAllowOpti(0)
{}
//---------------------------------------------------------------------------
/** \brief Copy constructor.
\throw nothrow
*/
ParserCallback::ParserCallback(const ParserCallback &a_Fun)
{
m_pFun = a_Fun.m_pFun;
m_iArgc = a_Fun.m_iArgc;
m_bAllowOpti = a_Fun.m_bAllowOpti;
m_iCode = a_Fun.m_iCode;
m_iType = a_Fun.m_iType;
m_iPri = a_Fun.m_iPri;
}
//---------------------------------------------------------------------------
/** \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 priority.
Only valid if the callback token is an operator token (binary or infix).
*/
int ParserCallback::GetPri() const
{
return m_iPri;
}
//---------------------------------------------------------------------------
/** \brief Returns the number of function Arguments. */
int ParserCallback::GetArgc() const
{
return m_iArgc;
}
} // namespace mu

View File

@ -0,0 +1,218 @@
/*
__________
_____ __ __\______ \_____ _______ ______ ____ _______
/ \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
| Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
|__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
\/ \/ \/ \/
Copyright (C) 2010 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 "muParserComplex.h"
#include "muParserFixes.h"
#include <cmath>
#include <complex>
#include <algorithm>
#include <numeric>
using namespace std;
/** \file
\brief This file contains the implementation of a parser using complex numbers.
*/
/** \brief Namespace for mathematical applications. */
namespace mu
{
//---------------------------------------------------------------------------
value_type ParserComplex::Sin(value_type v)
{
complex_type c = UnpackToComplex(v);
return PackToDouble(sin(c));
}
//---------------------------------------------------------------------------
value_type ParserComplex::Cos(value_type v)
{
complex_type c = UnpackToComplex(v);
return PackToDouble(cos(c));
}
//---------------------------------------------------------------------------
value_type ParserComplex::Tan(value_type v)
{
complex_type c = UnpackToComplex(v);
return PackToDouble(tan(c));
}
//---------------------------------------------------------------------------
value_type ParserComplex::Sqrt(value_type v)
{
complex_type c = UnpackToComplex(v);
return PackToDouble(sqrt(c));
}
//---------------------------------------------------------------------------
value_type ParserComplex::Add(value_type v1, value_type v2)
{
complex_type c1 = UnpackToComplex(v1),
c2 = UnpackToComplex(v2);
return PackToDouble(c1+c2);
}
//---------------------------------------------------------------------------
value_type ParserComplex::Sub(value_type v1, value_type v2)
{
complex_type c1 = UnpackToComplex(v1),
c2 = UnpackToComplex(v2);
return PackToDouble(c1-c2);
}
//---------------------------------------------------------------------------
value_type ParserComplex::Mul(value_type v1, value_type v2)
{
complex_type c1 = UnpackToComplex(v1),
c2 = UnpackToComplex(v2);
return PackToDouble(c1*c2);
}
//---------------------------------------------------------------------------
value_type ParserComplex::Div(value_type v1, value_type v2)
{
complex_type c1 = UnpackToComplex(v1),
c2 = UnpackToComplex(v2);
return PackToDouble(c1/c2);
}
//---------------------------------------------------------------------------
// Unary operator Callbacks: Infix operators
value_type ParserComplex::UnaryMinus(value_type v)
{
return -v;
}
//---------------------------------------------------------------------------
// Default value recognition callback
int ParserComplex::IsVal(const char_type *a_szExpr, int *a_iPos, value_type *a_fVal)
{
string_type buf(a_szExpr);
float real, imag;
int stat, len;
#if defined (_UNICODE)
stat = swscanf(buf.c_str(), _T("{%f,%f}%n"), &real, &imag, &len);
#else
stat = sscanf(buf.c_str(), "{%f,%f}%n", &real, &imag, &len);
#endif
if (stat!=2)
return 0;
*a_iPos += len;
*a_fVal = PackToDouble(complex_type(real, imag));
return 1;
}
//---------------------------------------------------------------------------
/** \brief Constructor.
Call ParserBase class constructor and trigger Function, Operator and Constant initialization.
*/
ParserComplex::ParserComplex()
:ParserBase()
{
AddValIdent(IsVal);
InitCharSets();
InitFun();
InitOprt();
}
//---------------------------------------------------------------------------
void ParserComplex::InitCharSets()
{
DefineNameChars( _T("0123456789_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") );
DefineOprtChars( _T("+-*^/?<>=!%&|~'_") );
DefineInfixOprtChars( _T("/+-*^?<>=!%&|~'_") );
}
//---------------------------------------------------------------------------
/** \brief Initialize operators. */
void ParserComplex::InitOprt()
{
// disable all built in operators, not all of them usefull 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);
DefineOprt( _T("+"), Add, prADD_SUB);
DefineOprt( _T("-"), Sub, prADD_SUB);
DefineOprt( _T("*"), Mul, prMUL_DIV);
DefineOprt( _T("/"), Div, prMUL_DIV);
}
//---------------------------------------------------------------------------
void ParserComplex::InitFun()
{
DefineFun( _T("sin"), Sin);
DefineFun( _T("cos"), Cos);
DefineFun( _T("tan"), Tan);
DefineFun( _T("sqrt"), Sqrt);
}
//---------------------------------------------------------------------------
void ParserComplex::InitConst()
{}
//---------------------------------------------------------------------------
ParserComplex::complex_type ParserComplex::UnpackToComplex(double val)
{
float imag(0), real(0);
real = *((float*)(&val));
imag = *((float*)(&val)+1);
return complex_type(real, imag);
}
//---------------------------------------------------------------------------
double ParserComplex::PackToDouble(const complex_type &val)
{
double packed = 0;
float *real = (float*)(&packed),
*imag = (float*)(&packed)+1;
*real = val.real();
*imag = val.imag();
return packed;
}
//---------------------------------------------------------------------------
ParserComplex::complex_type ParserComplex::Eval()
{
return UnpackToComplex(ParserBase::Eval());
}
} // namespace mu

View File

@ -0,0 +1,820 @@
/*
__________
_____ __ __\______ \_____ _______ ______ ____ _______
/ \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
| Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
|__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
\/ \/ \/ \/
Copyright (C) 2004-2010 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.
*/
#if defined(MUPARSER_DLL)
#if defined(_WIN32)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif
#include "muParserDLL.h"
#include "muParser.h"
#include "muParserError.h"
#define MU_TRY \
try \
{
#define MU_CATCH \
} \
catch(muError_t &e) \
{ \
ParserTag *pTag = static_cast<ParserTag*>(a_hParser); \
pTag->exc = e; \
pTag->bError = true; \
if (pTag->errHandler) \
(pTag->errHandler)(a_hParser); \
} \
catch(...) \
{ \
ParserTag *pTag = static_cast<ParserTag*>(a_hParser); \
pTag->exc = muError_t(mu::ecINTERNAL_ERROR); \
pTag->bError = true; \
if (pTag->errHandler) \
(pTag->errHandler)(a_hParser); \
}
/** \file
\brief This file contains the implementation of the DLL interface of muparser.
*/
//---------------------------------------------------------------------------
class ParserTag
{
public:
ParserTag()
:pParser(new mu::Parser())
,exc()
,errHandler(NULL)
,bError(false)
{}
~ParserTag()
{
delete pParser;
}
mu::Parser *pParser;
mu::ParserBase::exception_type exc;
muErrorHandler_t errHandler;
bool bError;
private:
ParserTag(const ParserTag &ref);
ParserTag& operator=(const ParserTag &ref);
};
static muChar_t s_tmpOutBuf[2048];
//---------------------------------------------------------------------------
// private types
typedef mu::ParserBase::exception_type muError_t;
typedef mu::Parser muParser_t;
//---------------------------------------------------------------------------
//
//
// unexported functions
//
//
//---------------------------------------------------------------------------
muParser_t* AsParser(muParserHandle_t a_hParser)
{
return static_cast<ParserTag*>(a_hParser)->pParser;
}
//---------------------------------------------------------------------------
ParserTag* AsParserTag(muParserHandle_t a_hParser)
{
return static_cast<ParserTag*>(a_hParser);
}
//---------------------------------------------------------------------------
#if defined(_WIN32)
#define _CRT_SECURE_NO_DEPRECATE
BOOL APIENTRY DllMain( HANDLE /*hModule*/,
DWORD ul_reason_for_call,
LPVOID /*lpReserved*/ )
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
#endif
//---------------------------------------------------------------------------
//
//
// exported functions
//
//
//---------------------------------------------------------------------------
API_EXPORT(void) mupSetVarFactory(muParserHandle_t a_hParser, muFacFun_t a_pFactory, void *pUserData)
{
MU_TRY
muParser_t* p(AsParser(a_hParser));
p->SetVarFactory(a_pFactory, pUserData);
MU_CATCH
}
//---------------------------------------------------------------------------
/** \brief Create a new Parser instance and return its handle.
*/
API_EXPORT(muParserHandle_t) mupCreate()
{
return (void*)(new ParserTag());
}
//---------------------------------------------------------------------------
/** \brief Release the parser instance related with a parser handle.
*/
API_EXPORT(void) mupRelease(muParserHandle_t a_hParser)
{
MU_TRY
ParserTag* p = static_cast<ParserTag*>(a_hParser);
delete p;
MU_CATCH
}
//---------------------------------------------------------------------------
API_EXPORT(const muChar_t*) mupGetVersion(muParserHandle_t a_hParser)
{
MU_TRY
muParser_t* const p(AsParser(a_hParser));
sprintf(s_tmpOutBuf, "%s", p->GetVersion().c_str());
return s_tmpOutBuf;
MU_CATCH
return "";
}
//---------------------------------------------------------------------------
/** \brief Evaluate the expression.
*/
API_EXPORT(double) mupEval(muParserHandle_t a_hParser)
{
MU_TRY
muParser_t* const p(AsParser(a_hParser));
return p->Eval();
MU_CATCH
return 0;
}
//---------------------------------------------------------------------------
API_EXPORT(void) mupSetExpr(muParserHandle_t a_hParser, const muChar_t* a_szExpr)
{
MU_TRY
muParser_t* const p(AsParser(a_hParser));
p->SetExpr(a_szExpr);
MU_CATCH
}
//---------------------------------------------------------------------------
API_EXPORT(void) mupRemoveVar(muParserHandle_t a_hParser, const muChar_t* a_szName)
{
MU_TRY
muParser_t* const p(AsParser(a_hParser));
p->RemoveVar( a_szName );
MU_CATCH
}
//---------------------------------------------------------------------------
/** \brief Release all parser variables.
\param a_hParser Handle to the parser instance.
*/
API_EXPORT(void) mupClearVar(muParserHandle_t a_hParser)
{
MU_TRY
muParser_t* const p(AsParser(a_hParser));
p->ClearVar();
MU_CATCH
}
//---------------------------------------------------------------------------
/** \brief Release all parser variables.
\param a_hParser Handle to the parser instance.
*/
API_EXPORT(void) mupClearConst(muParserHandle_t a_hParser)
{
MU_TRY
muParser_t* const p(AsParser(a_hParser));
p->ClearConst();
MU_CATCH
}
//---------------------------------------------------------------------------
/** \brief Clear all user defined operators.
\param a_hParser Handle to the parser instance.
*/
API_EXPORT(void) mupClearOprt(muParserHandle_t a_hParser)
{
MU_TRY
muParser_t* const p(AsParser(a_hParser));
p->ClearOprt();
MU_CATCH
}
//---------------------------------------------------------------------------
API_EXPORT(void) mupClearFun(muParserHandle_t a_hParser)
{
MU_TRY
muParser_t* const p(AsParser(a_hParser));
p->ClearFun();
MU_CATCH
}
//---------------------------------------------------------------------------
API_EXPORT(void) mupDefineFun0( muParserHandle_t a_hParser,
const muChar_t* a_szName,
muFun0_t a_pFun,
muBool_t a_bAllowOpt )
{
MU_TRY
muParser_t* const p(AsParser(a_hParser));
p->DefineFun(a_szName, a_pFun, a_bAllowOpt!=0);
MU_CATCH
}
//---------------------------------------------------------------------------
API_EXPORT(void) mupDefineFun1( muParserHandle_t a_hParser,
const muChar_t* a_szName,
muFun1_t a_pFun,
muBool_t a_bAllowOpt )
{
MU_TRY
muParser_t* const p(AsParser(a_hParser));
p->DefineFun(a_szName, a_pFun, a_bAllowOpt!=0);
MU_CATCH
}
//---------------------------------------------------------------------------
API_EXPORT(void) mupDefineFun2( muParserHandle_t a_hParser,
const muChar_t* a_szName,
muFun2_t a_pFun,
muBool_t a_bAllowOpt )
{
MU_TRY
muParser_t* const p(AsParser(a_hParser));
p->DefineFun(a_szName, a_pFun, a_bAllowOpt!=0);
MU_CATCH
}
//---------------------------------------------------------------------------
API_EXPORT(void) mupDefineFun3( muParserHandle_t a_hParser,
const muChar_t *a_szName,
muFun3_t a_pFun,
muBool_t a_bAllowOpt )
{
MU_TRY
muParser_t* const p(AsParser(a_hParser));
p->DefineFun(a_szName, a_pFun, a_bAllowOpt!=0);
MU_CATCH
}
//---------------------------------------------------------------------------
API_EXPORT(void) mupDefineFun4( muParserHandle_t a_hParser,
const muChar_t *a_szName,
muFun4_t a_pFun,
muBool_t a_bAllowOpt )
{
MU_TRY
muParser_t* const p(AsParser(a_hParser));
p->DefineFun(a_szName, a_pFun, a_bAllowOpt!=0);
MU_CATCH
}
//---------------------------------------------------------------------------
API_EXPORT(void) mupDefineFun5( muParserHandle_t a_hParser,
const muChar_t *a_szName,
muFun5_t a_pFun,
muBool_t a_bAllowOpt )
{
MU_TRY
muParser_t* const p(AsParser(a_hParser));
p->DefineFun(a_szName, a_pFun, a_bAllowOpt!=0);
MU_CATCH
}
//---------------------------------------------------------------------------
API_EXPORT(void) mupDefineStrFun1( muParserHandle_t a_hParser,
const muChar_t *a_szName,
muStrFun1_t a_pFun )
{
MU_TRY
muParser_t* const p(AsParser(a_hParser));
p->DefineFun(a_szName, a_pFun, false);
MU_CATCH
}
//---------------------------------------------------------------------------
API_EXPORT(void) mupDefineStrFun2( muParserHandle_t a_hParser,
const muChar_t* a_szName,
muStrFun2_t a_pFun )
{
MU_TRY
muParser_t* const p(AsParser(a_hParser));
p->DefineFun(a_szName, a_pFun, false);
MU_CATCH
}
//---------------------------------------------------------------------------
API_EXPORT(void) mupDefineStrFun3( muParserHandle_t a_hParser,
const muChar_t* a_szName,
muStrFun3_t a_pFun )
{
MU_TRY
muParser_t* const p(AsParser(a_hParser));
p->DefineFun(a_szName, a_pFun, false);
MU_CATCH
}
//---------------------------------------------------------------------------
API_EXPORT(void) mupDefineMultFun( muParserHandle_t a_hParser,
const muChar_t *a_szName,
muMultFun_t a_pFun,
muBool_t a_bAllowOpt )
{
MU_TRY
muParser_t* const p(AsParser(a_hParser));
p->DefineFun(a_szName, a_pFun, a_bAllowOpt!=0);
MU_CATCH
}
//---------------------------------------------------------------------------
API_EXPORT(void) mupDefineOprt( muParserHandle_t a_hParser,
const muChar_t* a_szName,
muFun2_t a_pFun,
muInt_t a_iPri,
muBool_t a_bAllowOpt)
{
MU_TRY
muParser_t* const p(AsParser(a_hParser));
p->DefineOprt(a_szName, a_pFun, a_iPri, a_bAllowOpt!=0);
MU_CATCH
}
//---------------------------------------------------------------------------
API_EXPORT(void) mupDefineVar(muParserHandle_t a_hParser, const char *a_szName, double *a_pVar)
{
MU_TRY
muParser_t* const p(AsParser(a_hParser));
p->DefineVar(a_szName, a_pVar);
MU_CATCH
}
//---------------------------------------------------------------------------
API_EXPORT(void) mupDefineConst(muParserHandle_t a_hParser, const char *a_szName, double a_fVal)
{
MU_TRY
muParser_t* const p(AsParser(a_hParser));
p->DefineConst(a_szName, a_fVal);
MU_CATCH
}
//---------------------------------------------------------------------------
API_EXPORT(void) mupDefineStrConst(muParserHandle_t a_hParser, const char *a_szName, const char *a_szVal)
{
MU_TRY
muParser_t* const p(AsParser(a_hParser));
p->DefineStrConst(a_szName, a_szVal);
MU_CATCH
}
//---------------------------------------------------------------------------
API_EXPORT(const muChar_t*) mupGetExpr(muParserHandle_t a_hParser)
{
MU_TRY
muParser_t* const p(AsParser(a_hParser));
// return p->GetExpr().c_str();
// C# explodes when pMsg is returned directly. For some reason it can't access
// the memory where the message lies directly.
// static char szBuf[1024];
sprintf(s_tmpOutBuf, "%s", p->GetExpr().c_str());
return s_tmpOutBuf;
MU_CATCH
return "";
}
//---------------------------------------------------------------------------
API_EXPORT(void) mupDefinePostfixOprt( muParserHandle_t a_hParser,
const muChar_t* a_szName,
muFun1_t a_pOprt,
muBool_t a_bAllowOpt )
{
MU_TRY
muParser_t* const p(AsParser(a_hParser));
p->DefinePostfixOprt(a_szName, a_pOprt, a_bAllowOpt!=0);
MU_CATCH
}
//---------------------------------------------------------------------------
API_EXPORT(void) mupDefineInfixOprt( muParserHandle_t a_hParser,
const muChar_t* a_szName,
muFun1_t a_pOprt,
muBool_t a_bAllowOpt )
{
MU_TRY
muParser_t* const p(AsParser(a_hParser));
p->DefineInfixOprt(a_szName, a_pOprt, a_bAllowOpt!=0);
MU_CATCH
}
// Define character sets for identifiers
//---------------------------------------------------------------------------
API_EXPORT(void) mupDefineNameChars( muParserHandle_t a_hParser,
const muChar_t* a_szCharset )
{
muParser_t* const p(AsParser(a_hParser));
p->DefineNameChars(a_szCharset);
}
//---------------------------------------------------------------------------
API_EXPORT(void) mupDefineOprtChars( muParserHandle_t a_hParser,
const muChar_t* a_szCharset )
{
muParser_t* const p(AsParser(a_hParser));
p->DefineOprtChars(a_szCharset);
}
//---------------------------------------------------------------------------
API_EXPORT(void) mupDefineInfixOprtChars(muParserHandle_t a_hParser, const char *a_szCharset)
{
muParser_t* const p(AsParser(a_hParser));
p->DefineInfixOprtChars(a_szCharset);
}
//---------------------------------------------------------------------------
/** \brief Get the number of variables defined in the parser.
\param a_hParser [in] Must be a valid parser handle.
\return The number of used variables.
\sa mupGetExprVar
*/
API_EXPORT(int) mupGetVarNum(muParserHandle_t a_hParser)
{
MU_TRY
muParser_t* const p(AsParser(a_hParser));
const mu::varmap_type VarMap = p->GetVar();
return (int)VarMap.size();
MU_CATCH
return 0; // never reached
}
//---------------------------------------------------------------------------
/** \brief Return a variable that is used in an expression.
\param a_hParser [in] A valid parser handle.
\param a_iVar [in] The index of the variable to return.
\param a_szName [out] Pointer to the variable name.
\param a_pVar [out] Pointer to the variable.
\throw nothrow
Prior to calling this function call mupGetExprVarNum in order to get the
number of variables in the expression. If the parameter a_iVar is greater
than the number of variables both a_szName and a_pVar will be set to zero.
As a side effect this function will trigger an internal calculation of the
expression undefined variables will be set to zero during this calculation.
During the calculation user defined callback functions present in the expression
will be called, this is unavoidable.
*/
API_EXPORT(void) mupGetVar(muParserHandle_t a_hParser, unsigned a_iVar, const char **a_szName, double **a_pVar)
{
// A static buffer is needed for the name since i cant return the
// pointer from the map.
static char szName[1024];
MU_TRY
muParser_t* const p(AsParser(a_hParser));
const mu::varmap_type VarMap = p->GetVar();
if (a_iVar>=VarMap.size())
{
*a_szName = 0;
*a_pVar = 0;
return;
}
mu::varmap_type::const_iterator item;
item = VarMap.begin();
for (unsigned i=0; i<a_iVar; ++i)
item++;
strncpy(szName, item->first.c_str(), sizeof(szName));
szName[sizeof(szName)-1] = 0;
*a_szName = &szName[0];
*a_pVar = item->second;
return;
MU_CATCH
*a_szName = 0;
*a_pVar = 0;
}
//---------------------------------------------------------------------------
/** \brief Get the number of variables used in the expression currently set in the parser.
\param a_hParser [in] Must be a valid parser handle.
\return The number of used variables.
\sa mupGetExprVar
*/
API_EXPORT(int) mupGetExprVarNum(muParserHandle_t a_hParser)
{
MU_TRY
muParser_t* const p(AsParser(a_hParser));
const mu::varmap_type VarMap = p->GetUsedVar();
return (int)VarMap.size();
MU_CATCH
return 0; // never reached
}
//---------------------------------------------------------------------------
/** \brief Return a variable that is used in an expression.
Prior to calling this function call mupGetExprVarNum in order to get the
number of variables in the expression. If the parameter a_iVar is greater
than the number of variables both a_szName and a_pVar will be set to zero.
As a side effect this function will trigger an internal calculation of the
expression undefined variables will be set to zero during this calculation.
During the calculation user defined callback functions present in the expression
will be called, this is unavoidable.
\param a_hParser [in] A valid parser handle.
\param a_iVar [in] The index of the variable to return.
\param a_szName [out] Pointer to the variable name.
\param a_pVar [out] Pointer to the variable.
\throw nothrow
*/
API_EXPORT(void) mupGetExprVar(muParserHandle_t a_hParser, unsigned a_iVar, const char **a_szName, double **a_pVar)
{
// A static buffer is needed for the name since i cant return the
// pointer from the map.
static char szName[1024];
MU_TRY
muParser_t* const p(AsParser(a_hParser));
const mu::varmap_type VarMap = p->GetUsedVar();
if (a_iVar>=VarMap.size())
{
*a_szName = 0;
*a_pVar = 0;
return;
}
mu::varmap_type::const_iterator item;
item = VarMap.begin();
for (unsigned i=0; i<a_iVar; ++i)
item++;
strncpy(szName, item->first.c_str(), sizeof(szName));
szName[sizeof(szName)-1] = 0;
*a_szName = &szName[0];
*a_pVar = item->second;
return;
MU_CATCH
*a_szName = 0;
*a_pVar = 0;
}
//---------------------------------------------------------------------------
/** \brief Return the number of constants defined in a parser. */
API_EXPORT(int) mupGetConstNum(muParserHandle_t a_hParser)
{
MU_TRY
muParser_t* const p(AsParser(a_hParser));
const mu::valmap_type ValMap = p->GetConst();
return (int)ValMap.size();
MU_CATCH
return 0; // never reached
}
//-----------------------------------------------------------------------------------------------------
API_EXPORT(void) mupSetArgSep(muParserHandle_t a_hParser, const muChar_t cArgSep)
{
MU_TRY
muParser_t* const p(AsParser(a_hParser));
p->SetArgSep(cArgSep);
MU_CATCH
}
//-----------------------------------------------------------------------------------------------------
API_EXPORT(void) mupResetLocale(muParserHandle_t a_hParser)
{
MU_TRY
muParser_t* const p(AsParser(a_hParser));
p->ResetLocale();
MU_CATCH
}
//-----------------------------------------------------------------------------------------------------
API_EXPORT(void) mupSetDecSep(muParserHandle_t a_hParser, const muChar_t cDecSep)
{
MU_TRY
muParser_t* const p(AsParser(a_hParser));
p->SetDecSep(cDecSep);
MU_CATCH
}
//-----------------------------------------------------------------------------------------------------
API_EXPORT(void) mupSetThousandsSep(muParserHandle_t a_hParser, const muChar_t cThousandsSep)
{
MU_TRY
muParser_t* const p(AsParser(a_hParser));
p->SetThousandsSep(cThousandsSep);
MU_CATCH
}
//---------------------------------------------------------------------------
/** \brief Retrieve name and value of a single parser constant.
\param a_hParser [in] a valid parser handle
\param a_iVar [in] Index of the constant to query
\param a_pszName [out] pointer to a null terminated string with the constant name
\param [out] The constant value
*/
API_EXPORT(void) mupGetConst( muParserHandle_t a_hParser,
unsigned a_iVar,
const muChar_t **a_pszName,
muFloat_t *a_fVal)
{
// A static buffer is needed for the name since i cant return the
// pointer from the map.
static char szName[1024];
MU_TRY
muParser_t* const p(AsParser(a_hParser));
const mu::valmap_type ValMap = p->GetConst();
if (a_iVar>=ValMap.size())
{
*a_pszName = 0;
*a_fVal = 0;
return;
}
mu::valmap_type::const_iterator item;
item = ValMap.begin();
for (unsigned i=0; i<a_iVar; ++i)
item++;
strncpy(szName, item->first.c_str(), sizeof(szName));
szName[sizeof(szName)-1] = 0;
*a_pszName = &szName[0];
*a_fVal = item->second;
return;
MU_CATCH
*a_pszName = 0;
*a_fVal = 0;
}
//---------------------------------------------------------------------------
/** \brief Add a custom value regognition function.
*/
/*
MU_PARSER_API void mupAddValIdent(muParserHandle_t a_hParser, identfun_type a_pFun)
{
MU_TRY
parser_type p(AsParser(a_hParser));
p->AddValIdent(a_pFun);
MU_CATCH
}
*/
//---------------------------------------------------------------------------
/** \brief Query if an error occured.
After querying the internal error bit will be reset. So a consecutive call
will return false.
*/
API_EXPORT(muBool_t) mupError(muParserHandle_t a_hParser)
{
bool bError( AsParserTag(a_hParser)->bError );
AsParserTag(a_hParser)->bError = false;
return bError;
}
//---------------------------------------------------------------------------
/** \brief Reset the internal error flag.
*/
API_EXPORT(void) mupErrorReset(muParserHandle_t a_hParser)
{
AsParserTag(a_hParser)->bError = false;
}
//---------------------------------------------------------------------------
API_EXPORT(void) mupSetErrorHandler(muParserHandle_t a_hParser, muErrorHandler_t a_pHandler)
{
AsParserTag(a_hParser)->errHandler = a_pHandler;
}
//---------------------------------------------------------------------------
/** \brief Return the message associated with the last error.
*/
API_EXPORT(const muChar_t*) mupGetErrorMsg(muParserHandle_t a_hParser)
{
ParserTag* const p(AsParserTag(a_hParser));
const char *pMsg = p->exc.GetMsg().c_str();
// C# explodes when pMsg is returned directly. For some reason it can't access
// the memory where the message lies directly.
// static char szBuf[1024];
sprintf(s_tmpOutBuf, "%s", pMsg);
return s_tmpOutBuf;
}
//---------------------------------------------------------------------------
/** \brief Return the message associated with the last error.
*/
API_EXPORT(const muChar_t*) mupGetErrorToken(muParserHandle_t a_hParser)
{
ParserTag* const p(AsParserTag(a_hParser));
const char *pToken = p->exc.GetToken().c_str();
// C# explodes when pMsg is returned directly. For some reason it can't access
// the memory where the message lies directly.
// static char szBuf[1024];
sprintf(s_tmpOutBuf, "%s", pToken);
return s_tmpOutBuf;
}
//---------------------------------------------------------------------------
/** \brief Return the code associated with the last error.
*/
API_EXPORT(int) mupGetErrorCode(muParserHandle_t a_hParser)
{
return AsParserTag(a_hParser)->exc.GetCode();
}
//---------------------------------------------------------------------------
/** \brief Return the postion associated with the last error. */
API_EXPORT(int) mupGetErrorPos(muParserHandle_t a_hParser)
{
return (int)AsParserTag(a_hParser)->exc.GetPos();
}
////-----------------------------------------------------------------------------------------------------
//API_EXPORT(const muChar_t*) mupGetErrorExpr(muParserHandle_t a_hParser)
//{
// return AsParserTag(a_hParser)->exc.GetExpr().c_str();
//}
//-----------------------------------------------------------------------------------------------------
API_EXPORT(muFloat_t*) mupCreateVar()
{
return new muFloat_t(0);
}
//-----------------------------------------------------------------------------------------------------
API_EXPORT(void) mupReleaseVar(muFloat_t *ptr)
{
delete ptr;
}
#endif // MUPARSER_DLL

View File

@ -0,0 +1,327 @@
/*
__________
_____ __ __\______ \_____ _______ ______ ____ _______
/ \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
| Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
|__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
\/ \/ \/ \/
Copyright (C) 2010 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("Undefined token \"$TOK$\" found at position $POS$.");
m_vErrMsg[ecINTERNAL_ERROR] = _T("Internal error");
m_vErrMsg[ecINVALID_NAME] = _T("Invalid function-, variable- or constant name.");
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[ecGENERIC] = _T("Parser error.");
m_vErrMsg[ecLOCALE] = _T("Decimal separator is identic to function argument separator.");
m_vErrMsg[ecSTR_RESULT] = _T("Function result is a string.");
#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_ErrMsg(ParserErrorMsg::Instance())
{
Reset();
m_strMsg = _T("parser error");
}
//------------------------------------------------------------------------------
/** \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 occured.
*/
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 occured.
\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 ocuurences 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
*/
std::size_t 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

View File

@ -0,0 +1,262 @@
/*
__________
_____ __ __\______ \_____ _______ ______ ____ _______
/ \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
| Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
|__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
\/ \/ \/ \/
Copyright (C) 2010 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 Round(fabs(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::LogXor(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); }
//---------------------------------------------------------------------------
// 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;
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 = (value_type)iVal;
return 1;
}
//---------------------------------------------------------------------------
int ParserInt::IsHexVal(const char_type *a_szExpr, int *a_iPos, value_type *a_fVal)
{
if (a_szExpr[0]!='$')
return 0;
unsigned iVal(0);
// New code based on streams for UNICODE compliance:
stringstream_type::pos_type nPos(0);
stringstream_type ss(a_szExpr+1);
ss >> std::hex >> iVal;
nPos = ss.tellg();
if (nPos==(stringstream_type::pos_type)0)
return 1;
*a_iPos += (int)(1 + nPos);
*a_fVal = iVal;
return true;
}
//---------------------------------------------------------------------------
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);
AddValIdent(IsHexVal);
AddValIdent(IsBinVal);
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 usefull 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("^"), LogXor, 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(">>"), Shr, prMUL_DIV+1);
DefineOprt( _T("<<"), Shl, prMUL_DIV+1);
}
} // namespace mu

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,852 @@
/*
__________
_____ __ __\______ \_____ _______ ______ ____ _______
/ \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
| Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
|__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
\/ \/ \/ \/
Copyright (C) 2010 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 Assignement operator.
Self assignement 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;
}
//---------------------------------------------------------------------------
/** \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)
{
m_vIdentFun.push_back(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::GetFormula() const
{
return m_strFormula;
}
//---------------------------------------------------------------------------
/** \brief Return a map containing the used variables only. */
const varmap_type& ParserTokenReader::GetUsedVar() const
{
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 contronls behaviour in case of undefined variables beeing 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 supresses 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 = noOPT | noBC | noPOSTOP | noASSIGN;
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);
std::stack<int> FunArgs;
const char_type *szFormula = m_strFormula.c_str();
token_type tok;
while (szFormula[m_iPos]==' ')
++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 supress 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();
a_sTok = string_type( m_strFormula.begin()+a_iPos, m_strFormula.begin()+iEnd);
a_iPos = iEnd;
return iEnd;
}
//---------------------------------------------------------------------------
/** \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 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 assignement 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;
m_iSynFlags |= ( (i != cmEND) && ( i != cmBC) ) ? noEND : 0;
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;
else
m_iSynFlags = noBC | noOPT | noEND | noARG_SEP | noPOSTOP | noASSIGN;
++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;
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;
funmap_type::const_iterator item = m_pInfixOprtDef->find(sTok);
if (item==m_pInfixOprtDef->end())
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)
{
string_type strTok;
int iEnd = ExtractToken(m_pParser->ValidOprtChars(), strTok, m_iPos);
if (iEnd==m_iPos)
return false;
funmap_type::const_iterator item = m_pOprtDef->find(strTok);
if (item==m_pOprtDef->end())
return false;
a_Tok.Set(item->second, strTok);
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;
// nope, no infix operator
Error(ecUNEXPECTED_OPERATOR, m_iPos, a_Tok.GetAsString());
}
m_iPos = (int)iEnd;
m_iSynFlags = noBC | noOPT | noARG_SEP | noPOSTOP | noEND | noBC | noASSIGN;
return true;
}
//---------------------------------------------------------------------------
/** \brief Check if a string position contains a unary post value operator. */
bool ParserTokenReader::IsPostOpTok(token_type &a_Tok)
{
// 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;
// iteraterate over all postfix operator strings
funmap_type::const_iterator item = m_pPostOprtDef->begin();
for (item=m_pPostOprtDef->begin(); item!=m_pPostOprtDef->end(); ++item)
{
if (sTok.find(item->first)!=0)
continue;
a_Tok.Set(item->second, sTok);
m_iPos += (int)item->first.length();
if (m_iSynFlags & noPOSTOP)
Error(ecUNEXPECTED_OPERATOR, m_iPos-(int)item->first.length(), item->first);
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);
#if defined(_MSC_VER)
#pragma warning( disable : 4244 )
#endif
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::vector<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 )
{
strTok.assign(m_strFormula.c_str(), iStart, m_iPos);
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;
#if defined(_MSC_VER)
#pragma warning( default : 4244 )
#endif
}
//---------------------------------------------------------------------------
/** \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->size())
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 | noPOSTOP | noINFIXOP | noSTR;
return true;
}
//---------------------------------------------------------------------------
bool ParserTokenReader::IsStrVarTok(token_type &a_Tok)
{
if (!m_pStrVarDef || !m_pStrVarDef->size())
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 = 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 previousely 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!=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 = 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

29
src/external/muparser_v132/src/src.pro vendored Normal file
View File

@ -0,0 +1,29 @@
######################################################################
# Automatically generated by qmake (2.01a) Wed Mar 4 01:57:13 2009
######################################################################
TEMPLATE = lib
TARGET = muparser
CONFIG += staticlib
DEPENDPATH += .
INCLUDEPATH += ../include
macx:DESTDIR = ../../lib/macx
win32-g++:DESTDIR = ../../lib/win32-gcc
win32-msvc2005:DESTDIR = ../../lib/win32-msvc2005
win32-msvc2008:DESTDIR = ../../lib/win32-msvc2008
linux-g++:DESTDIR = ../../lib/linux-g++
linux-g++-32:DESTDIR = ../../lib/linux-g++-32
linux-g++-64:DESTDIR = ../../lib/linux-g++-64
# Input
SOURCES += muParser.cpp \
muParserBase.cpp \
muParserBytecode.cpp \
muParserCallback.cpp \
muParserComplex.cpp \
muParserDLL.cpp \
muParserError.cpp \
muParserInt.cpp \
muParserTest.cpp \
muParserTokenReader.cpp