[cig-commits] commit: Add in original muparserx
Mercurial
hg at geodynamics.org
Wed Nov 9 00:47:47 PST 2011
changeset: 388:5a4d909d9533
user: Walter Landry <wlandry at caltech.edu>
date: Tue Nov 08 10:39:59 2011 -0800
files: muparserx/COPYING.txt muparserx/Makefile muparserx/Readme.txt muparserx/doc/custom/Main.txt muparserx/doc/custom/calc.cpp muparserx/doc/custom/example.txt muparserx/doc/custom/features.txt muparserx/doc/custom/footer.html muparserx/doc/custom/list_expr_var.cpp muparserx/doc/custom/listvar.cpp muparserx/doc/doxyfile.dox muparserx/doc/muParserX.jpg muparserx/doc/muParserX.png muparserx/doc/muParserX_2.png muparserx/parser/Lib_Parser.vcproj muparserx/parser/mpDefines.h muparserx/parser/mpError.cpp muparserx/parser/mpError.h muparserx/parser/mpFuncCmplx.cpp muparserx/parser/mpFuncCmplx.h muparserx/parser/mpFuncCommon.cpp muparserx/parser/mpFuncCommon.h muparserx/parser/mpFuncMatrix.cpp muparserx/parser/mpFuncMatrix.h muparserx/parser/mpFuncNonCmplx.cpp muparserx/parser/mpFuncNonCmplx.h muparserx/parser/mpFuncStr.cpp muparserx/parser/mpFuncStr.h muparserx/parser/mpFwdDecl.h muparserx/parser/mpICallback.cpp muparserx/parser/mpICallback.h muparserx/parser/mpIOprt.cpp muparserx/parser/mpIOprt.h muparserx/parser/mpIPackage.cpp muparserx/parser/mpIPackage.h muparserx/parser/mpIPrecedence.h muparserx/parser/mpIToken.cpp muparserx/parser/mpIToken.h muparserx/parser/mpIValReader.cpp muparserx/parser/mpIValReader.h muparserx/parser/mpIValue.cpp muparserx/parser/mpIValue.h muparserx/parser/mpIfThenElse.cpp muparserx/parser/mpIfThenElse.h muparserx/parser/mpMatrix.h muparserx/parser/mpMatrixError.h muparserx/parser/mpOprtBinAssign.cpp muparserx/parser/mpOprtBinAssign.h muparserx/parser/mpOprtBinCommon.cpp muparserx/parser/mpOprtBinCommon.h muparserx/parser/mpOprtCmplx.cpp muparserx/parser/mpOprtCmplx.h muparserx/parser/mpOprtIndex.cpp muparserx/parser/mpOprtIndex.h muparserx/parser/mpOprtMatrix.cpp muparserx/parser/mpOprtMatrix.h muparserx/parser/mpOprtNonCmplx.cpp muparserx/parser/mpOprtNonCmplx.h muparserx/parser/mpPackageCmplx.cpp muparserx/parser/mpPackageCmplx.h muparserx/parser/mpPackageCommon.cpp muparserx/parser/mpPackageCommon.h muparserx/parser/mpPackageMatrix.cpp muparserx/parser/mpPackageMatrix.h muparserx/parser/mpPackageNonCmplx.cpp muparserx/parser/mpPackageNonCmplx.h muparserx/parser/mpPackageStr.cpp muparserx/parser/mpPackageStr.h muparserx/parser/mpPackageUnit.cpp muparserx/parser/mpPackageUnit.h muparserx/parser/mpParser.cpp muparserx/parser/mpParser.h muparserx/parser/mpParserBase.cpp muparserx/parser/mpParserBase.h muparserx/parser/mpRPN.cpp muparserx/parser/mpRPN.h muparserx/parser/mpScriptTokens.cpp muparserx/parser/mpScriptTokens.h muparserx/parser/mpStack.h muparserx/parser/mpTest.cpp muparserx/parser/mpTest.h muparserx/parser/mpTokenReader.cpp muparserx/parser/mpTokenReader.h muparserx/parser/mpTypes.h muparserx/parser/mpValReader.cpp muparserx/parser/mpValReader.h muparserx/parser/mpValue.cpp muparserx/parser/mpValue.h muparserx/parser/mpValueCache.cpp muparserx/parser/mpValueCache.h muparserx/parser/mpVariable.cpp muparserx/parser/mpVariable.h muparserx/parser/muParser.suo muparserx/parser/suSortPred.h muparserx/parser/utGeneric.h muparserx/sample/example.cpp muparserx/sample/timer.cpp muparserx/sample/timer.h muparserx/value_test/AssemblyInfo.cpp muparserx/value_test/ReadMe.txt muparserx/value_test/UpgradeLog.XML muparserx/value_test/app.ico muparserx/value_test/app.rc muparserx/value_test/mpDefines.h muparserx/value_test/mpError.cpp muparserx/value_test/mpError.h muparserx/value_test/mpFwdDecl.h muparserx/value_test/mpIPrecedence.h muparserx/value_test/mpIToken.cpp muparserx/value_test/mpIToken.h muparserx/value_test/mpIValReader.h muparserx/value_test/mpIValue.cpp muparserx/value_test/mpIValue.h muparserx/value_test/mpTypes.h muparserx/value_test/mpValue.cpp muparserx/value_test/mpValue.h muparserx/value_test/mpValueCache.cpp muparserx/value_test/mpValueCache.h muparserx/value_test/mpVariable.cpp muparserx/value_test/mpVariable.h muparserx/value_test/muMatrix.h muparserx/value_test/muMatrixError.h muparserx/value_test/muMatrixTest.cpp muparserx/value_test/muMatrixTest.h muparserx/value_test/resource.h muparserx/value_test/stdafx.cpp muparserx/value_test/stdafx.h muparserx/value_test/suSortPred.h muparserx/value_test/value_test.cpp muparserx/value_test/value_test.sln muparserx/value_test/value_test.sln.old muparserx/value_test/value_test.suo.old muparserx/value_test/value_test.vcproj muparserx/value_test/value_test.vcproj.NB1.user.user muparserx/value_test/value_test.vcxproj muparserx/value_test/value_test.vcxproj.filters muparserx/value_test/value_test.vcxproj.user muparserx/vs8/muparserX.sln muparserx/vs8/muparserx.vcproj
description:
Add in original muparserx
diff -r 458e51062300 -r 5a4d909d9533 muparserx/COPYING.txt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/COPYING.txt Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,165 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+ This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
+
+ 0. Additional Definitions.
+
+ As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
+
+ "The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
+
+ An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
+
+ A "Combined Work" is a work produced by combining or linking an
+Application with the Library. The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
+
+ The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
+
+ The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
+
+ 1. Exception to Section 3 of the GNU GPL.
+
+ You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
+
+ 2. Conveying Modified Versions.
+
+ If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
+
+ a) under this License, provided that you make a good faith effort to
+ ensure that, in the event an Application does not supply the
+ function or data, the facility still operates, and performs
+ whatever part of its purpose remains meaningful, or
+
+ b) under the GNU GPL, with none of the additional permissions of
+ this License applicable to that copy.
+
+ 3. Object Code Incorporating Material from Library Header Files.
+
+ The object code form of an Application may incorporate material from
+a header file that is part of the Library. You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
+
+ a) Give prominent notice with each copy of the object code that the
+ Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the object code with a copy of the GNU GPL and this license
+ document.
+
+ 4. Combined Works.
+
+ You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following:
+
+ a) Give prominent notice with each copy of the Combined Work that
+ the Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the Combined Work with a copy of the GNU GPL and this license
+ document.
+
+ c) For a Combined Work that displays copyright notices during
+ execution, include the copyright notice for the Library among
+ these notices, as well as a reference directing the user to the
+ copies of the GNU GPL and this license document.
+
+ d) Do one of the following:
+
+ 0) Convey the Minimal Corresponding Source under the terms of this
+ License, and the Corresponding Application Code in a form
+ suitable for, and under terms that permit, the user to
+ recombine or relink the Application with a modified version of
+ the Linked Version to produce a modified Combined Work, in the
+ manner specified by section 6 of the GNU GPL for conveying
+ Corresponding Source.
+
+ 1) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (a) uses at run time
+ a copy of the Library already present on the user's computer
+ system, and (b) will operate properly with a modified version
+ of the Library that is interface-compatible with the Linked
+ Version.
+
+ e) Provide Installation Information, but only if you would otherwise
+ be required to provide such information under section 6 of the
+ GNU GPL, and only to the extent that such information is
+ necessary to install and execute a modified version of the
+ Combined Work produced by recombining or relinking the
+ Application with a modified version of the Linked Version. (If
+ you use option 4d0, the Installation Information must accompany
+ the Minimal Corresponding Source and Corresponding Application
+ Code. If you use option 4d1, you must provide the Installation
+ Information in the manner specified by section 6 of the GNU GPL
+ for conveying Corresponding Source.)
+
+ 5. Combined Libraries.
+
+ You may place library facilities that are a work based on the
+Library side by side in a single library together with other library
+facilities that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
+
+ a) Accompany the combined library with a copy of the same work based
+ on the Library, uncombined with any other library facilities,
+ conveyed under the terms of this License.
+
+ b) Give prominent notice with the combined library that part of it
+ is a work based on the Library, and explaining where to find the
+ accompanying uncombined form of the same work.
+
+ 6. Revised Versions of the GNU Lesser General Public License.
+
+ The Free Software Foundation may publish revised and/or new versions
+of the GNU Lesser General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Library as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
+
+ If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
+Library.
diff -r 458e51062300 -r 5a4d909d9533 muparserx/Makefile
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/Makefile Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,74 @@
+CC = g++
+# debug version
+#CFLAGS = -Wall -ggdb
+# release version:
+CFLAGS = -O3 -ffast-math -fomit-frame-pointer
+
+PATH_BIN = ./bin
+
+########################################################################################################
+# muParser library sources
+PATH_LIB = ./parser
+PATH_OBJ = ./obj
+LIB_SRC = mpError.cpp mpRPN.cpp mpICallback.cpp mpIValReader.cpp mpParserBase.cpp mpTokenReader.cpp\
+ mpVariable.cpp mpIOprt.cpp mpIValue.cpp mpParser.cpp mpValReader.cpp mpFuncStr.cpp\
+ mpFuncCommon.cpp mpFuncNonCmplx.cpp mpFuncCmplx.cpp mpIToken.cpp mpOprtCmplx.cpp \
+ mpOprtNonCmplx.cpp mpOprtBinCommon.cpp mpOprtBinAssign.cpp mpOprtMatrix.cpp\
+ mpIPackage.cpp mpPackageCommon.cpp mpPackageStr.cpp mpPackageCmplx.cpp mpPackageNonCmplx.cpp\
+ mpPackageMatrix.cpp mpPackageUnit.cpp mpIfThenElse.cpp mpValueCache.cpp mpValue.cpp mpTest.cpp\
+ mpScriptTokens.cpp mpFuncMatrix.cpp mpOprtIndex.cpp
+LIB_OBJ = ${LIB_SRC:.cpp=.o}
+NAME_LIB = libmuparserx.a
+
+########################################################################################################
+# example application
+PATH_SAMPLE = ./sample
+
+
+all: example
+
+new: clean example
+
+$(NAME_LIB): $(LIB_OBJ)
+ @echo ""
+ @echo "#########################################################"
+ @echo "# #"
+ @echo "# Building libmuparserX #"
+ @echo "# #"
+ @echo "#########################################################"
+ @echo ""
+
+ ar ru $(NAME_LIB) $(LIB_OBJ:%.o=$(PATH_OBJ)/%.o)
+ ranlib $(NAME_LIB)
+ mv $(NAME_LIB) bin/
+
+$(LIB_OBJ):
+ $(CC) $(CFLAGS) -c $(PATH_LIB)/${@:.o=.cpp} -o $(PATH_OBJ)/$@
+
+example: $(NAME_LIB)
+ @echo ""
+ @echo "#########################################################"
+ @echo "# #"
+ @echo "# Building sample #"
+ @echo "# #"
+ @echo "#########################################################"
+ @echo ""
+ $(CC) $(CFLAGS) -I$(PATH_LIB) -L$(PATH_BIN) -o $(PATH_BIN)/$@ $(PATH_SAMPLE)/example.cpp $(PATH_SAMPLE)/timer.cpp -lmuparserx -lm
+
+clean:
+ #@clear
+ @echo "########################################################"
+ @echo "# #"
+ @echo "# Cleaning up #"
+ @echo "# #"
+ @echo "########################################################"
+ @echo ""
+ rm -rf *.o
+ rm -rf *~
+ rm -rf libmuparserx.a
+ rm -rf $(PATH_OBJ)/*
+ rm -rf $(PATH_BIN)/*
+
+new:
+ $(MAKE) clean
+ $(MAKE) all
diff -r 458e51062300 -r 5a4d909d9533 muparserx/Readme.txt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/Readme.txt Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,198 @@
+#########################################################################
+# #
+# #
+# #
+# __________ ____ ___ #
+# _____ __ _\______ \_____ _______ ______ __________\ \/ / #
+# / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ / #
+# | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \ #
+# |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \ #
+# \/ \/ \/ \/ \_/ #
+# #
+# http://muparserx.beltoforion.de #
+# (C) 2011 Ingo Berg #
+# #
+#########################################################################
+
+#########################################################################
+# #
+# Version history #
+# #
+#########################################################################
+
+V2.0.1 (20111014)
+-----------------
+Bugfixes:
+ - Issue 1 fixed: Assertion when using a function with multiple arguments
+ in the same expression twice with different number of arguments.
+ (Reference: http://code.google.com/p/muparserx/issues/detail?id=1)
+
+V2.0.0 (20111009)
+-----------------
+
+Changes:
+- Fundamental datatype changed to a matrix type instead of a vector type
+- Multidimensional index operator added
+ old:
+ "m[1][2] = 1"
+ new:
+ "m[1,2] = 1"
+
+- type identifier for matrices is now 'm', formerly 'a' was used to
+ indicate arrays. An arrays are now seen as subsets of matrices, there is no
+ special type for arrays.
+
+Bugfixes:
+- Matrix addition and subtraction work properly now.
+
+
+V1.10.2 (20110911)
+------------------
+Bugfixes:
+- Fix for changed behaviour of tellg in GCC 4.6.1. A Space is now appended
+ to every expression in order to avoid problems.
+
+
+V1.10 (20110310)
+----------------
+Warning:
+The API of this version is not backwards compatible and requires minor
+changes to client code!
+
+Changes:
+- Static type checking removed entirely
+ (All type checking must be made at runtime by the callbacks themself)
+- Optimizer removed. The optimizer had only limited effect since it only
+ implemented a very simple constant folding mechanism. It collided with
+ the new if-then-else logic and had to go. It will probably be reintroduced
+ in one of the next versions using a different implementation.
+- Expressions can now span multiple lines. This only makes sense when used
+ together with the assignment operator i.e.:
+
+ a=1
+ b=2
+ c=3
+ sin(a+b+c)
+
+
+Bugfixes:
+- Nested if-then-else did not work properly
+- Sign operators extended to work with arrays
+- Operators "==" and "!=" did not work properly for arrays
+- Relational operators "<", ">", "<=", ">=" did not work for complex numbers
+- GCC makefile was broken in V1.09
+- complex multiplication did not work correctly;
+ was:
+ (a+ib)(c+id)=>re=ac-bd;im=ad-bc
+ instead of:
+ (a+ib)(c+id)=>re=ac-bd;im=ad+bc
+- Expressions with parameterless functions like a=foo() did not evaluate properly.
+
+
+V1.09 (20101120)
+----------------
+Changes:
+- Performance increased by factor 4 due to introducing a simple memory pool for value items.
+- C++ like if-then-else operator added ( "(a<b) ? c : d")
+
+Bugfixes:
+- Memory leak fixed which prevented operator and funtion items from beeing released.
+
+
+V1.08 (20100902)
+----------------
+Changes:
+- Implicit creation of unknown variables at parser runtime is now possibe
+ (i.e. expressions like "a=0"; with a beeing a undefined variable).
+- Callbacks can now be organized in packages
+- Callbacks split into a complex and a non complex package
+- Complex power operator added
+
+Bugfixes:
+- Assignment operators did not work properly for complex values
+- Complex sign operator fixed in order not to mess up 0 by
+ multiplying it with -1 (-0 and 0 ar not the same according to
+ IEEE754)
+
+
+V1.07 (20100818)
+----------------
+Changes:
+- Parsing performance improved by 20 - 30 % due to removing unnecessary
+ copy constructor calls when returning the final result.
+- License changed from GPLv3 to LGPLv3
+- Assignment to vector elements is now possible (i.e.: va[1]=9)
+
+Bugfixes:
+- The Value type could not properly handle matrices (vector of vector)
+ uses the reverse polish notation of an expression for the evaluation.
+- Error messages did not display the proper type id's when compiled
+ with UNICODE support.
+
+
+V1.06 (20100710)
+----------------
+- Parsing performance improved by factor 2-3 due to a change which
+ uses the reverse polish notation of an expression for the evaluation.
+
+
+V1.05 (20100530)
+----------------
+- The parser now handles the associativity of binary operators properly
+- Parsing performance improved by factor 7 due to caching tokens
+ once an expression is parsed. Successive evaluations will use
+ the cached tokens instead of parsing from string again.
+
+
+V1.04 (20100516):
+-----------------
+- Querying of expression variables implemented
+- Bugfix for incorrect evaluation of expressions using the index
+ operator added
+- nil values removed
+- Support for functions without parameters added
+- UNICODE support added
+
+
+V1.03:
+------
+- basic functions rewritten to complex valued functions
+- Unit postfix operators added to the standard setup
+
+
+V1.02:
+------
+- Index operator added
+- addition/subtraction of vectors added
+
+
+V1.01:
+------
+- Complex numbers added with support for basic binary operators
+- Vector type added with support for basic operations (v*v, v+v)
+- Variable class changed to take a pointer to a value class instead
+ of base types like int or double.
+
+
+#########################################################################
+# #
+# Licence #
+# #
+#########################################################################
+
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
diff -r 458e51062300 -r 5a4d909d9533 muparserx/doc/custom/Main.txt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/doc/custom/Main.txt Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,16 @@
+/** \mainpage
+
+<div>
+ <img src="../muParserX.png"/>
+</div>
+
+ \section intro_sec Introduction
+
+ muParserX is a mathematical expression parser with support for complex numbers and matrix calculations. This is the API documentation of muParserX.
+ For additional documentation consult the <a href="http://code.google.com/p/muparserx/">project home page at google code</a>.
+
+ \section toc Table of content
+ \ref page_features<br/>
+*/
+
+
diff -r 458e51062300 -r 5a4d909d9533 muparserx/doc/custom/calc.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/doc/custom/calc.cpp Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,59 @@
+#include "mpParser.h"
+
+
+void Calc()
+{
+ char line[100];
+ try
+ {
+ // Create value objects that will be bound to parser variables
+ Value fVal = 1.11;
+ Value sVal = "hello world";
+ Value arr1(3, 0);
+ arr1[0] = 1.11,
+ arr1[1] = 2.22;
+ arr1[2] = 3.33;
+
+ Parser parser;
+
+ // Define parser variables and bind them to their value objects
+ parser.DefineVar("va", Variable(&arr1));
+ parser.DefineVar("a", Variable(&fVal));
+ parser.DefineVar("sa", Variable(&sVal));
+
+ parser.SetExpr("sin(a)+b");
+
+ // The returned result is of type Value, value is a Variant like
+ // type that can be either a boolean an integer or a floating point value
+ Value result = parser.Eval();
+
+ // Value supports C++ streaming like this:
+ cout << "Result:\n" << result << "\n";
+
+ // Or if you need the specific type use this:
+ switch (result.GetType())
+ {
+ case 's': cout << result.GetString() << " (string)" << "\n"; break;
+ case 'i': cout << result.GetInt() << " (int)" << "\n"; break;
+ case 'f': cout << result.GetFloat() << " (float)" << "\n"; break;
+ case 'c': cout << result.GetFloat() << "+" << result.GetImag() << "i (complex)" << "\n"; break;
+ case 'b': break;
+ }
+ }
+ catch(ParserError &e)
+ {
+ cout << e.GetMsg() << "\n\n";
+
+ if (e.GetContext().Ident.length())
+ cout << "Ident.: " << e.GetContext().Ident << "\n";
+
+ if (e.GetExpr().length())
+ cout << "Expr.: " << e.GetExpr() << "\n";
+
+ if (e.GetToken().length())
+ cout << "Token: " << e.GetToken() << "\n";
+
+ cout << "Pos: " << e.GetPos() << "\n";
+ cout << "Errc: " << e.GetCode() << "\n";
+ }
+} // Calc()
\ No newline at end of file
diff -r 458e51062300 -r 5a4d909d9533 muparserx/doc/custom/example.txt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/doc/custom/example.txt Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,15 @@
+/** \example listvar.cpp
+ This example shows how to list parser variables.
+*/
+
+/** \example list_expr_var.cpp
+ This example shows how to list variables used in an expression.
+*/
+
+/** \example calc.cpp
+ This example shows a typical use case of muParser. It sets up the parser
+ engine and is defining several variables.
+*/
+}
+*/
+
diff -r 458e51062300 -r 5a4d909d9533 muparserx/doc/custom/features.txt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/doc/custom/features.txt Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,69 @@
+/*! \page page_features Features
+\section fea_overview Feature overview
+
+<ul>
+<li>Supported data types: <b>double, integer, complex, boolean, string, array</b></li>
+<li>Extensible with custom operators (<b>binary, infix or postfix</b>)</li>
+<li>Extensible with custom functions with an arbitrary number of function arguments</li>
+<li>Support for an unlimited number of variables and constants</li>
+<li>No limit on expression complexity</li>
+<li>Reads binary, hexadecimal, complex, integer and string values from expressions and
+ can be extended to read user defined values as well.</li>
+<li>Supports a large variety of predefined \ref fea_predefined_op, \ref fea_predefined_fun
+ and \ref fea_predefined_const.</li>
+</ul>
+
+\section fea_predefined_const Predefined Constants
+By default the parser supports the following mathematical constants:
+<ul>
+ <li>The eulerian number with:<br/>
+ <b>e</b> = 2.718281828459045235360287<br/> </li>
+ <li>The mathematical constant equal to a circle's circumference divided by its diameter.<br/>
+ <b>pi</b> = 3.141592653589793238462643<br/> </li>
+ <li>The imaginary unit with:<br/>
+ <b>i</b> = sqrt(-1)<br/> </li>
+</ul>
+
+\section fea_predefined_op Predefined Operators
+<h3>Binary operators:</h3>
+<ul>
+ <li>Standard operators:<br/>
+ <b>"+", "-", "*", "/", "^"</b><br/> </li>
+ <li>Assignment operators:<br/>
+ <b>"=", "+=", "-=", "*=", "/="</b><br/> </li>
+ <li>Logical operators:<br/>
+ <b>"and", "or", "xor","==", "!=", ">", "<", "<=", ">="</b><br/> </li>
+ <li>Bit manipulation:<br/>
+ <b>"&", "|", "<<", ">>"</b><br/> </li>
+ <li>String concatenation:<br/>
+ <b>"//"</b><br/> </li>
+</ul>
+
+<h3>Postfix operators:</h3>
+<ul>
+ <li>Unit postfixes (nano, micro, milli, kilo, giga, mega):<br/>
+ <b>"{n}", "{mu}", "{m}", "{k}", "{G}", "{M}"</b><br/> </li>
+</ul>
+
+<p/>
+<h3>Infix operators:</h3>
+<ul>
+ <li>Sign operator and type conversions:<br/>
+ <b>"-", "(float)", "(int)"</b><br/> </li>
+</ul>
+
+\section fea_predefined_fun Predefined Functions
+<ul>
+ <li>Standard functions:<br/>
+ <b>abs, sin, cos, tan, sinh, cosh, tanh, ln, log, log10, exp, sqrt</b><br/> </li>
+ <li>Unlimited number of arguments:<br/>
+ <b>min, max, sum</b><br/> </li>
+ <li>String functions:<br/>
+ <b>str2dbl, strlen, toupper</b><br/> </li>
+ <li>Complex functions:<br/>
+ <b>real, imag, conj, arg, norm</b><br/> </li>
+ <li>Array functions:<br/>
+ <b>sizeof</b><br/> </li>
+</ul>
+
+*/
\ No newline at end of file
diff -r 458e51062300 -r 5a4d909d9533 muparserx/doc/custom/footer.html
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/doc/custom/footer.html Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,19 @@
+<div style="position:absolute; width:100%; height:100%; text-align:center;">
+<p>
+<hr/>
+<strong>muParserX</strong> documentation - (C) 2010 <a href="http://beltoforion.de">Ingo Berg</a>
+</p>
+</div>
+
+<script type="text/javascript">
+var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
+document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
+</script>
+<script type="text/javascript">
+try {
+var pageTracker = _gat._getTracker("UA-1019178-3");
+pageTracker._trackPageview();
+} catch(err) {}</script>
+
+</body>
+</html>
\ No newline at end of file
diff -r 458e51062300 -r 5a4d909d9533 muparserx/doc/custom/list_expr_var.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/doc/custom/list_expr_var.cpp Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,15 @@
+void ListExprVar(const mu::ParserBase &parser)
+{
+ varmap_type variables = parser.GetUsedVar();
+ if (!variables.size())
+ mu::console() << "Expression does not contain variables\n";
+ else
+ {
+ mu::console() << "Number: " << (int)variables.size() << "\n";
+ mu::varmap_type::const_iterator item = variables.begin();
+
+ for (; item!=variables.end(); ++item)
+ mu::console() << "Name: " << item->first << " Address: [0x" << item->second << "]\n";
+ }
+}
+
diff -r 458e51062300 -r 5a4d909d9533 muparserx/doc/custom/listvar.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/doc/custom/listvar.cpp Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,13 @@
+void ListVar(const mu::ParserBase &parser)
+{
+ 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");
+}
diff -r 458e51062300 -r 5a4d909d9533 muparserx/doc/doxyfile.dox
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/doc/doxyfile.dox Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,1755 @@
+# Doxyfile 1.7.5.1
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+# TAG = value [value, ...]
+# For lists items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
+# iconv built into libc) for the transcoding. See
+# http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or sequence of words) that should
+# identify the project. Note that if you do not use Doxywizard you need
+# to put quotes around the project name if it contains spaces.
+
+PROJECT_NAME = muParserX
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER = 2.0.0
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer
+# a quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF =
+
+# With the PROJECT_LOGO tag one can specify an logo or icon that is
+# included in the documentation. The maximum height of the logo should not
+# exceed 55 pixels and the maximum width should not exceed 200 pixels.
+# Doxygen will copy the logo to the output directory.
+
+PROJECT_LOGO =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY =
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
+# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German,
+# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English
+# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian,
+# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak,
+# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese.
+
+OUTPUT_LANGUAGE = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful if your file system
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like regular Qt-style comments
+# (thus requiring an explicit @brief command for a brief description.)
+
+JAVADOC_AUTOBRIEF = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
+# interpret the first line (until the first dot) of a Qt-style
+# comment as the brief description. If set to NO, the comments
+# will behave just like regular Qt-style comments (thus requiring
+# an explicit \brief command for a brief description.)
+
+QT_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 8
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
+# sources only. Doxygen will then generate output that is more tailored for
+# Java. For instance, namespaces will be presented as packages, qualified
+# scopes will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources only. Doxygen will then generate output that is more tailored for
+# Fortran.
+
+OPTIMIZE_FOR_FORTRAN = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for
+# VHDL.
+
+OPTIMIZE_OUTPUT_VHDL = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given extension.
+# Doxygen has a built-in mapping, but you can override or extend it using this
+# tag. The format is ext=language, where ext is a file extension, and language
+# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C,
+# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make
+# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C
+# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions
+# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen.
+
+EXTENSION_MAPPING =
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should
+# set this tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
+# func(std::string) {}). This also makes the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+
+CPP_CLI_SUPPORT = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
+# Doxygen will parse them like normal C++ but will assume all classes use public
+# instead of private inheritance when no explicit protection keyword is present.
+
+SIP_SUPPORT = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate getter
+# and setter methods for a property. Setting this option to YES (the default)
+# will make doxygen replace the get and set methods by a property in the
+# documentation. This will only work if the methods are indeed getting or
+# setting a simple type. If this is not the case, or you want to show the
+# methods anyway, you should set this option to NO.
+
+IDL_PROPERTY_SUPPORT = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and
+# unions are shown inside the group in which they are included (e.g. using
+# @ingroup) instead of on a separate page (for HTML and Man pages) or
+# section (for LaTeX and RTF).
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and
+# unions with only public data fields will be shown inline in the documentation
+# of the scope in which they are defined (i.e. file, namespace, or group
+# documentation), provided this scope is documented. If set to NO (the default),
+# structs, classes, and unions are shown on a separate page (for HTML and Man
+# pages) or section (for LaTeX and RTF).
+
+INLINE_SIMPLE_STRUCTS = NO
+
+# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
+# is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically
+# be useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+
+TYPEDEF_HIDES_STRUCT = NO
+
+# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to
+# determine which symbols to keep in memory and which to flush to disk.
+# When the cache is full, less often used symbols will be written to disk.
+# For small to medium size projects (<1000 input files) the default value is
+# probably good enough. For larger projects a too small cache size can cause
+# doxygen to be busy swapping symbols to and from disk most of the time
+# causing a significant performance penalty.
+# If the system has enough physical memory increasing the cache will improve the
+# performance by keeping more symbols in memory. Note that the value works on
+# a logarithmic scale so increasing the size by one will roughly double the
+# memory usage. The cache size is given by this formula:
+# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0,
+# corresponding to a cache size of 2^16 = 65536 symbols
+
+SYMBOL_CACHE_SIZE = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES = NO
+
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base
+# name of the file that contains the anonymous namespace. By default
+# anonymous namespaces are hidden.
+
+EXTRACT_ANON_NSPACES = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = YES
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES = NO
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = NO
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen
+# will list include files with double quotes in the documentation
+# rather than with sharp brackets.
+
+FORCE_LOCAL_INCLUDES = NO
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen
+# will sort the (brief and detailed) documentation of class members so that
+# constructors and destructors are listed first. If set to NO (the default)
+# the constructors will appear in the respective orders defined by
+# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS.
+# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO
+# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
+# hierarchy of group names into alphabetical order. If set to NO (the default)
+# the group names will appear in their defined order.
+
+SORT_GROUP_NAMES = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to
+# do proper type resolution of all parameters of a function it will reject a
+# match between the prototype and the implementation of a member function even
+# if there is only one candidate or it is obvious which candidate to choose
+# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen
+# will still accept a match between prototype and implementation in such cases.
+
+STRICT_PROTO_MATCHING = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or macro consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and macros in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES = NO
+
+# If the sources in your project are distributed over multiple directories
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
+# in the documentation. The default is NO.
+
+SHOW_DIRECTORIES = NO
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
+# This will remove the Files entry from the Quick Index and from the
+# Folder Tree View (if specified). The default is YES.
+
+SHOW_FILES = NO
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the
+# Namespaces page. This will remove the Namespaces entry from the Quick Index
+# and from the Folder Tree View (if specified). The default is YES.
+
+SHOW_NAMESPACES = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command <command> <input-file>, where <command> is the value of
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
+# provided by doxygen. Whatever the program writes to standard output
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. The create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option.
+# You can optionally specify a file name after the option, if omitted
+# DoxygenLayout.xml will be used as the name of the layout file.
+
+LAYOUT_FILE =
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files
+# containing the references data. This must be a list of .bib files. The
+# .bib extension is automatically appended if omitted. Using this command
+# requires the bibtex tool to be installed. See also
+# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style
+# of the bibliography can be controlled using LATEX_BIB_STYLE.
+
+CITE_BIB_FILES =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR = YES
+
+# The WARN_NO_PARAMDOC option can be enabled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
+# documentation.
+
+WARN_NO_PARAMDOC = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT = ../parser \
+ custom
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
+# also the default input encoding. Doxygen uses libiconv (or the iconv built
+# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
+# the list of possible encodings.
+
+INPUT_ENCODING = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh
+# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py
+# *.f90 *.f *.for *.vhd *.vhdl
+
+FILE_PATTERNS = *.txt \
+ *.cpp \
+ *.h \
+ *.hpp \
+ *.hh \
+ *.cc \
+ *.c
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+# Note that relative paths are relative to directory from which doxygen is run.
+
+EXCLUDE =
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH = custom
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output. If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty or if
+# non of the patterns match the file name, INPUT_FILTER is applied.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any)
+# and it is also possible to disable source filtering for a specific pattern
+# using *.ext= (so without naming a filter). This option only has effect when
+# FILTER_SOURCE_FILES is enabled.
+
+FILTER_SOURCE_PATTERNS =
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS = NO
+
+# If the REFERENCED_BY_RELATION tag is set to YES
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code. Otherwise they will link to the documentation.
+
+REFERENCES_LINK_SOURCE = NO
+
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html). You
+# will need version 4.8.6 or higher.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX = YES
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header. Note that when using a custom header you are responsible
+# for the proper inclusion of any scripts and style sheets that doxygen
+# needs, which is dependent on the configuration options used.
+# It is adviced to generate a default header using "doxygen -w html
+# header.html footer.html stylesheet.css YourConfigFile" and then modify
+# that header. Note that the header is subject to change so you typically
+# have to redo this when upgrading to a newer version of doxygen or when
+# changing the value of configuration settings such as GENERATE_TREEVIEW!
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER = custom/footer.html
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET =
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that
+# the files will be copied as-is; there are no commands or markers available.
+
+HTML_EXTRA_FILES =
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output.
+# Doxygen will adjust the colors in the stylesheet and background images
+# according to this color. Hue is specified as an angle on a colorwheel,
+# see http://en.wikipedia.org/wiki/Hue for more information.
+# For instance the value 0 represents red, 60 is yellow, 120 is green,
+# 180 is cyan, 240 is blue, 300 purple, and 360 is red again.
+# The allowed range is 0 to 359.
+
+HTML_COLORSTYLE_HUE = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of
+# the colors in the HTML output. For a value of 0 the output will use
+# grayscales only. A value of 255 will produce the most vivid colors.
+
+HTML_COLORSTYLE_SAT = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to
+# the luminance component of the colors in the HTML output. Values below
+# 100 gradually make the output lighter, whereas values above 100 make
+# the output darker. The value divided by 100 is the actual gamma applied,
+# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2,
+# and 100 does not change the gamma.
+
+HTML_COLORSTYLE_GAMMA = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting
+# this to NO can help when comparing the output of multiple runs.
+
+HTML_TIMESTAMP = YES
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded. For this to work a browser that supports
+# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox
+# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
+
+HTML_DYNAMIC_SECTIONS = NO
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files
+# will be generated that can be used as input for Apple's Xcode 3
+# integrated development environment, introduced with OSX 10.5 (Leopard).
+# To create a documentation set, doxygen will generate a Makefile in the
+# HTML output directory. Running make will produce the docset in that
+# directory and running "make install" will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
+# it at startup.
+# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
+# for more information.
+
+GENERATE_DOCSET = NO
+
+# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
+# feed. A documentation feed provides an umbrella under which multiple
+# documentation sets from a single provider (such as a company or product suite)
+# can be grouped.
+
+DOCSET_FEEDNAME = "Doxygen generated docs"
+
+# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
+# should uniquely identify the documentation set bundle. This should be a
+# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
+# will append .docset to the name.
+
+DOCSET_BUNDLE_ID = org.doxygen.Project
+
+# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify
+# the documentation publisher. This should be a reverse domain-name style
+# string, e.g. com.mycompany.MyDocSet.documentation.
+
+DOCSET_PUBLISHER_ID = org.doxygen.Publisher
+
+# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher.
+
+DOCSET_PUBLISHER_NAME = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
+# is used to encode HtmlHelp index (hhk), content (hhc) and project file
+# content.
+
+CHM_INDEX_ENCODING =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated
+# that can be used as input for Qt's qhelpgenerator to generate a
+# Qt Compressed Help (.qch) of the generated HTML documentation.
+
+GENERATE_QHP = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can
+# be used to specify the file name of the resulting .qch file.
+# The path specified is relative to the HTML output folder.
+
+QCH_FILE =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#namespace
+
+QHP_NAMESPACE = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#virtual-folders
+
+QHP_VIRTUAL_FOLDER = doc
+
+# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to
+# add. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#custom-filters
+
+QHP_CUST_FILTER_NAME =
+
+# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see
+# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters">
+# Qt Help Project / Custom Filters</a>.
+
+QHP_CUST_FILTER_ATTRS =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's
+# filter section matches.
+# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes">
+# Qt Help Project / Filter Attributes</a>.
+
+QHP_SECT_FILTER_ATTRS =
+
+# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can
+# be used to specify the location of Qt's qhelpgenerator.
+# If non-empty doxygen will try to run qhelpgenerator on the generated
+# .qhp file.
+
+QHG_LOCATION =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files
+# will be generated, which together with the HTML files, form an Eclipse help
+# plugin. To install this plugin and make it available under the help contents
+# menu in Eclipse, the contents of the directory containing the HTML and XML
+# files needs to be copied into the plugins directory of eclipse. The name of
+# the directory within the plugins directory should be the same as
+# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before
+# the help appears.
+
+GENERATE_ECLIPSEHELP = NO
+
+# A unique identifier for the eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have
+# this name.
+
+ECLIPSE_DOC_ID = org.doxygen.Project
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX = NO
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values
+# (range [0,1..20]) that doxygen will group on one line in the generated HTML
+# documentation. Note that a value of 0 will completely suppress the enum
+# values from appearing in the overview section.
+
+ENUM_VALUES_PER_LINE = 4
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information.
+# If the tag value is set to YES, a side panel will be generated
+# containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser).
+# Windows users are probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW = NO
+
+# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories,
+# and Class Hierarchy pages using a tree view instead of an ordered list.
+
+USE_INLINE_TREES = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH = 250
+
+# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open
+# links to external symbols imported via tag files in a separate window.
+
+EXT_LINKS_IN_WINDOW = NO
+
+# Use this tag to change the font size of Latex formulas included
+# as images in the HTML documentation. The default is 10. Note that
+# when you change the font size after a successful doxygen run you need
+# to manually remove any form_*.png images from the HTML output directory
+# to force them to be regenerated.
+
+FORMULA_FONTSIZE = 10
+
+# Use the FORMULA_TRANPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are
+# not supported properly for IE 6.0, but are supported on all modern browsers.
+# Note that when changing this option you need to delete any form_*.png files
+# in the HTML output before the changes have effect.
+
+FORMULA_TRANSPARENT = YES
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax
+# (see http://www.mathjax.org) which uses client side Javascript for the
+# rendering instead of using prerendered bitmaps. Use this if you do not
+# have LaTeX installed or if you want to formulas look prettier in the HTML
+# output. When enabled you also need to install MathJax separately and
+# configure the path to it using the MATHJAX_RELPATH option.
+
+USE_MATHJAX = NO
+
+# When MathJax is enabled you need to specify the location relative to the
+# HTML output directory using the MATHJAX_RELPATH option. The destination
+# directory should contain the MathJax.js script. For instance, if the mathjax
+# directory is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to the
+# mathjax.org site, so you can quickly see the result without installing
+# MathJax, but it is strongly recommended to install a local copy of MathJax
+# before deployment.
+
+MATHJAX_RELPATH = http://www.mathjax.org/mathjax
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension
+# names that should be enabled during MathJax rendering.
+
+MATHJAX_EXTENSIONS =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box
+# for the HTML output. The underlying search engine uses javascript
+# and DHTML and should work on any modern browser. Note that when using
+# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets
+# (GENERATE_DOCSET) there is already a search function so this one should
+# typically be disabled. For large projects the javascript based search engine
+# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution.
+
+SEARCHENGINE = YES
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a PHP enabled web server instead of at the web client
+# using Javascript. Doxygen will generate the search PHP script and index
+# file to put on the web server. The advantage of the server
+# based approach is that it scales better to large projects and allows
+# full text search. The disadvantages are that it is more difficult to setup
+# and does not have live searching capabilities.
+
+SERVER_BASED_SEARCH = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+# Note that when enabling USE_PDFLATEX this option is only used for
+# generating bitmaps for formulas in the HTML output, but not in the
+# Makefile that is written to the output directory.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for
+# the generated latex document. The footer should contain everything after
+# the last chapter. If it is left blank doxygen will generate a
+# standard footer. Notice: only use this tag if you know what you are doing!
+
+LATEX_FOOTER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = YES
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES = NO
+
+# If LATEX_SOURCE_CODE is set to YES then doxygen will include
+# source code with syntax highlighting in the LaTeX output.
+# Note that which sources are shown also depends on other settings
+# such as SOURCE_BROWSER.
+
+LATEX_SOURCE_CODE = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See
+# http://en.wikipedia.org/wiki/BibTeX for more info.
+
+LATEX_BIB_STYLE = plain
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader. This is useful
+# if you want to understand what is going on. On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = YES
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# pointed to by INCLUDE_PATH will be searched when a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
+
+PREDEFINED =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition that
+# overrules the definition found in the source code.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all references to function-like macros
+# that are alone on a line, have an all uppercase name, and do not end with a
+# semicolon, because these will confuse the parser if not removed.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option also works with HAVE_DOT disabled, but it is recommended to
+# install and use dot, since it yields more powerful graphs.
+
+CLASS_DIAGRAMS = NO
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see
+# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH =
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = YES
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is
+# allowed to run in parallel. When set to 0 (the default) doxygen will
+# base this on the number of processors available in the system. You can set it
+# explicitly to a value larger than 0 to get control over the balance
+# between CPU load and processing speed.
+
+DOT_NUM_THREADS = 0
+
+# By default doxygen will use the Helvetica font for all dot files that
+# doxygen generates. When you want a differently looking font you can specify
+# the font name using DOT_FONTNAME. You need to make sure dot is able to find
+# the font, which can be done by putting it in a standard location or by setting
+# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the
+# directory containing the font.
+
+DOT_FONTNAME = FreeSans
+
+# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs.
+# The default size is 10pt.
+
+DOT_FONTSIZE = 10
+
+# By default doxygen will tell dot to use the Helvetica font.
+# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to
+# set the path where dot can find it.
+
+DOT_FONTPATH =
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH and HAVE_DOT options are set to YES then
+# doxygen will generate a call dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable call graphs
+# for selected functions only using the \callgraph command.
+
+CALL_GRAPH = YES
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
+# doxygen will generate a caller dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable caller
+# graphs for selected functions only using the \callergraph command.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will generate a graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are svg, png, jpg, or gif.
+# If left blank png will be used. If you choose svg you need to set
+# HTML_FILE_EXTENSION to xhtml in order to make the SVG files
+# visible in IE 9+ (other browsers do not have this requirement).
+
+DOT_IMAGE_FORMAT = png
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+# Note that this requires a modern browser other than Internet Explorer.
+# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you
+# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files
+# visible. Older versions of IE do not have SVG support.
+
+INTERACTIVE_SVG = NO
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS =
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the
+# \mscfile command).
+
+MSCFILE_DIRS =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
+# nodes that will be shown in the graph. If the number of nodes in a graph
+# becomes larger than this value, doxygen will truncate the graph, which is
+# visualized by representing a node as a red box. Note that doxygen if the
+# number of direct children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+
+DOT_GRAPH_MAX_NODES = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes
+# that lay further from the root node will be omitted. Note that setting this
+# option to 1 or 2 may greatly reduce the computation time needed for large
+# code bases. Also note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not
+# seem to support this out of the box. Warning: Depending on the platform used,
+# enabling this option may lead to badly anti-aliased labels on the edges of
+# a graph (i.e. they become hard to read).
+
+DOT_TRANSPARENT = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP = YES
diff -r 458e51062300 -r 5a4d909d9533 muparserx/doc/muParserX.jpg
Binary file muparserx/doc/muParserX.jpg has changed
diff -r 458e51062300 -r 5a4d909d9533 muparserx/doc/muParserX.png
Binary file muparserx/doc/muParserX.png has changed
diff -r 458e51062300 -r 5a4d909d9533 muparserx/doc/muParserX_2.png
Binary file muparserx/doc/muParserX_2.png has changed
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/Lib_Parser.vcproj
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/Lib_Parser.vcproj Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,638 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9,00"
+ Name="muParser2"
+ ProjectGUID="{D8ADEC17-F606-46E1-82CF-DB6339A59287}"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="131072"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="obj"
+ IntermediateDirectory="obj"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ CharacterSet="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS"
+ MinimalRebuild="false"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ RuntimeTypeInfo="true"
+ UsePrecompiledHeader="0"
+ WarningLevel="4"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="muparser2.lib"
+ ModuleDefinitionFile=""
+ IgnoreAllDefaultLibraries="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="obj"
+ IntermediateDirectory="obj"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""C:\Dokumente und Einstellungen\Ingo\Eigene Dateien\Projekte\Uni_Hydrosim\SharedFiles""
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS"
+ RuntimeLibrary="0"
+ UsePrecompiledHeader="0"
+ WarningLevel="4"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="muparser2.lib"
+ IgnoreAllDefaultLibraries="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release (SingleThread)|Win32"
+ OutputDirectory="obj"
+ IntermediateDirectory="obj"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""C:\Dokumente und Einstellungen\Ingo\Eigene Dateien\Projekte\Uni_Hydrosim\SharedFiles""
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
+ RuntimeLibrary="0"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="muParser.lib"
+ IgnoreAllDefaultLibraries="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release (MultiThread)|Win32"
+ OutputDirectory="obj"
+ IntermediateDirectory="obj"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""C:\Dokumente und Einstellungen\Ingo\Eigene Dateien\Projekte\Uni_Hydrosim\SharedFiles""
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
+ RuntimeLibrary="0"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="muParserMT.lib"
+ IgnoreAllDefaultLibraries="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release (MT-DLL)|Win32"
+ OutputDirectory="obj"
+ IntermediateDirectory="obj"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ RuntimeLibrary="2"
+ DebugInformationFormat="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="muParserMTD.lib"
+ IgnoreAllDefaultLibraries="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug (Multithread)|Win32"
+ OutputDirectory="obj"
+ IntermediateDirectory="obj"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
+ MinimalRebuild="false"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ WarningLevel="4"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="muParserMT_Dbg.lib"
+ ModuleDefinitionFile=""
+ IgnoreAllDefaultLibraries="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug (MTD)|Win32"
+ OutputDirectory="obj"
+ IntermediateDirectory="obj"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
+ MinimalRebuild="false"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="4"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="muParserMTD_Dbg.lib"
+ IgnoreAllDefaultLibraries="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Quelldateien"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\mpError.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\mpFuncBasic.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\mpFuncStr.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\mpICallback.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\mpIOprt.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\mpIToken.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\mpIValReader.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\mpIValue.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\mpOprtBasic.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\mpParser.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\mpParserBase.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\mpTokenReader.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\mpValReader.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\mpValue.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\mpVariable.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Headerdateien"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\mpDefines.h"
+ >
+ </File>
+ <File
+ RelativePath=".\mpError.h"
+ >
+ </File>
+ <File
+ RelativePath=".\mpFuncBasic.h"
+ >
+ </File>
+ <File
+ RelativePath=".\mpFuncStr.h"
+ >
+ </File>
+ <File
+ RelativePath=".\mpICallback.h"
+ >
+ </File>
+ <File
+ RelativePath=".\mpIOprt.h"
+ >
+ </File>
+ <File
+ RelativePath=".\mpIToken.h"
+ >
+ </File>
+ <File
+ RelativePath=".\mpIValReader.h"
+ >
+ </File>
+ <File
+ RelativePath=".\mpIValue.h"
+ >
+ </File>
+ <File
+ RelativePath=".\mpOprtBasic.h"
+ >
+ </File>
+ <File
+ RelativePath=".\mpOprtBin.h"
+ >
+ </File>
+ <File
+ RelativePath=".\mpOprtBinAssign.h"
+ >
+ </File>
+ <File
+ RelativePath=".\mpParser.h"
+ >
+ </File>
+ <File
+ RelativePath=".\mpParserBase.h"
+ >
+ </File>
+ <File
+ RelativePath=".\mpStack.h"
+ >
+ </File>
+ <File
+ RelativePath=".\mpTokenPtr.h"
+ >
+ </File>
+ <File
+ RelativePath=".\mpTokenReader.h"
+ >
+ </File>
+ <File
+ RelativePath=".\mpTypes.h"
+ >
+ </File>
+ <File
+ RelativePath=".\mpValReader.h"
+ >
+ </File>
+ <File
+ RelativePath=".\mpValue.h"
+ >
+ </File>
+ <File
+ RelativePath=".\mpVariable.h"
+ >
+ </File>
+ <File
+ RelativePath=".\suSortPred.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Ressourcendateien"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpDefines.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpDefines.h Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,100 @@
+/** \file
+ \brief A file containing macros used by muParserX
+
+<pre>
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2011 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+</pre>
+*/
+#ifndef MUP_DEFINES_H
+#define MUP_DEFINES_H
+
+#include <cassert>
+
+
+#if defined(_UNICODE)
+ #if !defined(_T)
+ #define _T(x) L##x
+ #endif // not defined _T
+ #define MUP_STRING_TYPE std::wstring
+#else
+ #ifndef _T
+ /** \brief Macro needed for the "unicodification" of strings.
+ */
+ #define _T(x) x
+ #endif
+
+ /** \brief The string type used by muParserX.
+
+ This macro is needed for UNICODE support.
+ */
+ #define MUP_STRING_TYPE std::string
+#endif
+
+/** \brief A macro containing the version of muParserX. */
+#define MUP_PARSER_VERSION _T("2.0.1 (20111009)")
+
+/** \brief A macro for setting the parser namespace. */
+#define MUP_NAMESPACE_START namespace mup {
+
+/** \brief Closing bracket for the parser namespace macro. */
+#define MUP_NAMESPACE_END }
+
+
+#if defined(_DEBUG)
+ #define MUP_TOK_CAST(TYPE, POINTER) dynamic_cast<TYPE>(POINTER);
+
+ /** \brief Debug macro to force an abortion of the programm with a certain message.
+ */
+ #define MUP_FAIL(MSG) \
+ bool MSG=false; \
+ assert(MSG);
+
+ /** \brief An assertion that does not kill the program.
+
+ This macro is neutralised in UNICODE builds. It's
+ too difficult to translate.
+ */
+ #define MUP_ASSERT(COND) \
+ if (!(COND)) \
+ { \
+ stringstream_type ss; \
+ ss << _T("Assertion \"") _T(#COND) _T("\" failed: ") \
+ << __FILE__ << _T(" line ") \
+ << __LINE__ << _T("."); \
+ throw ParserError( ss.str() ); \
+ }
+ #define MUP_LEAKAGE_REPORT
+#else
+ #define MUP_FAIL(MSG)
+ #define MUP_ASSERT(COND)
+ #define MUP_TOK_CAST(TYPE, POINTER) static_cast<TYPE>(POINTER);
+#endif
+
+ /** \brief Include tests for features about to be implemented in
+ the future in the unit test.
+ */
+ //#define MUP_NICE_TO_HAVE
+#endif
+
+
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpError.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpError.cpp Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,310 @@
+/*
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+*/
+#include "mpError.h"
+#include "mpIToken.h"
+
+
+MUP_NAMESPACE_START
+
+ 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 \"$IDENT$\" 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[ecINVALID_VAR_PTR] = _T("Invalid pointer to variable");
+ m_vErrMsg[ecUNEXPECTED_OPERATOR] = _T("Unexpected operator \"$IDENT$\" found at position $POS$");
+ m_vErrMsg[ecUNEXPECTED_EOF] = _T("Unexpected end of expression at position $POS$");
+ m_vErrMsg[ecUNEXPECTED_COMMA] = _T("Unexpected comma at position $POS$");
+ m_vErrMsg[ecUNEXPECTED_PARENS ] = _T("Unexpected parenthesis \"$IDENT$\" at position $POS$");
+ m_vErrMsg[ecUNEXPECTED_FUN] = _T("Unexpected function \"$IDENT$\" at position $POS$");
+ m_vErrMsg[ecUNEXPECTED_VAL] = _T("Unexpected value \"$IDENT$\" found at position $POS$");
+ m_vErrMsg[ecUNEXPECTED_VAR] = _T("Unexpected variable \"$IDENT$\" found at position $POS$");
+ m_vErrMsg[ecUNEXPECTED_STR] = _T("Unexpected string token found at position $POS$");
+ m_vErrMsg[ecUNEXPECTED_CONDITIONAL] = _T("The \"$IDENT$\" operator must be preceeded by a closing bracket");
+ m_vErrMsg[ecUNEXPECTED_NEWLINE] = _T("Unexprected newline");
+ m_vErrMsg[ecMISSING_PARENS] = _T("Missing parenthesis");
+ m_vErrMsg[ecMISSING_ELSE_CLAUSE] = _T("If-then-else operator is missing an else clause");
+ m_vErrMsg[ecMISPLACED_COLON] = _T("Misplaced colon at position $POS$");
+ m_vErrMsg[ecTOO_MANY_PARAMS] = _T("Too many parameters for function \"$IDENT$\"");
+ m_vErrMsg[ecTOO_FEW_PARAMS] = _T("Too few parameters for function \"$IDENT$\"");
+ 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("Binary operator identifier conflicts with a built in operator");
+ 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("Numerical function called with a non value type of argument");
+ m_vErrMsg[ecTYPE_CONFLICT] = _T("Value \"$IDENT$\" is of type '$TYPE1$'. There is no implicit conversion to type '$TYPE2$'");
+ m_vErrMsg[ecTYPE_CONFLICT_FUN] = _T("Argument $ARG$ of function/operator \"$IDENT$\" is of type '$TYPE1$' whereas type '$TYPE2$' was expected");
+ m_vErrMsg[ecTYPE_CONFLICT_IDX] = _T("Index to \"$IDENT$\" must be a positive integer value. '$TYPE1$' is not an acceptable type.");
+ m_vErrMsg[ecGENERIC] = _T("Parser error");
+ m_vErrMsg[ecINVALID_TYPE] = _T("Invalid argument type");
+ m_vErrMsg[ecINVALID_TYPECAST] = _T("Value type conversion from type '$TYPE1$' to '$TYPE2$' is not supported!");
+ m_vErrMsg[ecARRAY_SIZE_MISMATCH] = _T("Array size mismatch");
+ m_vErrMsg[ecNOT_AN_ARRAY] = _T("Using the index operator on the scalar variable \"$IDENT$\" is not allowed");
+ m_vErrMsg[ecUNEXPECTED_SQR_BRACKET] = _T("Unexpected \"]\"");
+ m_vErrMsg[ecAPI_INVALID_PROTOTYPE] = _T("Invalid prototype (use something like: \"f:fff\")");
+ m_vErrMsg[ecAPI_NOT_AN_ARRAY] = _T("Not an array");
+ m_vErrMsg[ecAPI_INVALID_DIMENSION] = _T("Invalid matrix dimensions");
+ m_vErrMsg[ecINDEX_OUT_OF_BOUNDS] = _T("Index to variable \"$IDENT$\" is out of bounds");
+ m_vErrMsg[ecINDEX_DIMENSION] = _T("Index operator dimension error");
+ m_vErrMsg[ecMISSING_SQR_BRACKET] = _T("Missing \"]\"");
+ m_vErrMsg[ecASSIGNEMENT_TO_VALUE] = _T("Assignment operator \"$IDENT$\" can't be used in this context");
+ m_vErrMsg[ecEVAL] = _T("Can't evaluate function/operator \"$IDENT$\": $HINT$");
+ m_vErrMsg[ecINVALID_PARAMETER] = _T("Parameter $ARG$ of function \"$IDENT$\" is invalid");
+ m_vErrMsg[ecINVALID_NUMBER_OF_PARAMETERS] = _T("Invalid number of function arguments");
+
+ #if defined(_DEBUG)
+ for (int i=0; i<ecCOUNT; ++i)
+ if (!m_vErrMsg[i].length())
+ assert(false);
+ #endif
+ }
+
+ //---------------------------------------------------------------------------
+ //
+ // Error context
+ //
+ //---------------------------------------------------------------------------
+
+ /** \brief Constructs an empty Error context structure. */
+ ErrorContext::ErrorContext(EErrorCodes a_iErrc,
+ int a_iPos,
+ string_type a_sIdent)
+ :Expr()
+ ,Ident(a_sIdent)
+ ,Hint()
+ ,Errc(a_iErrc)
+ ,Type1(0)
+ ,Type2(0)
+ ,Arg(-1)
+ ,Pos(a_iPos)
+ {}
+
+ //---------------------------------------------------------------------------
+ ErrorContext::ErrorContext(EErrorCodes iErrc,
+ int iPos,
+ string_type sIdent,
+ char_type cType1,
+ char_type cType2,
+ int nArg)
+ :Expr()
+ ,Ident(sIdent)
+ ,Hint()
+ ,Errc(iErrc)
+ ,Type1(cType1)
+ ,Type2(cType2)
+ ,Arg(nArg)
+ ,Pos(iPos)
+ {}
+
+ //---------------------------------------------------------------------------
+ //
+ // ParserError class
+ //
+ //---------------------------------------------------------------------------
+
+ ParserError::ParserError()
+ :m_Err()
+ ,m_sMsg()
+ ,m_ErrMsg(ParserErrorMsg::Instance())
+ {}
+
+ //------------------------------------------------------------------------------
+ ParserError::ParserError(const string_type &sMsg)
+ :m_Err()
+ ,m_sMsg(sMsg)
+ ,m_ErrMsg(ParserErrorMsg::Instance())
+ {}
+
+ //------------------------------------------------------------------------------
+ ParserError::ParserError(const ErrorContext &a_Err)
+ :m_Err(a_Err)
+ ,m_sMsg()
+ ,m_ErrMsg(ParserErrorMsg::Instance())
+ {
+ m_sMsg = m_ErrMsg[a_Err.Errc];
+ }
+
+ //------------------------------------------------------------------------------
+ ParserError::ParserError(const ParserError &a_Obj)
+ :m_Err(a_Obj.m_Err)
+ ,m_sMsg(a_Obj.m_sMsg)
+ ,m_ErrMsg(ParserErrorMsg::Instance())
+ {}
+
+ //------------------------------------------------------------------------------
+ ParserError& ParserError::operator=(const ParserError &a_Obj)
+ {
+ if (this==&a_Obj)
+ return *this;
+
+ m_sMsg = a_Obj.m_sMsg;
+ m_Err = a_Obj.m_Err;
+ return *this;
+ }
+
+ //------------------------------------------------------------------------------
+ /** \brief Replace all occurences of a substring with another string. */
+ void ParserError::ReplaceSubString( string_type &sSource,
+ const string_type &sFind,
+ const string_type &sReplaceWith) const
+ {
+ string_type sResult;
+ string_type::size_type iPos(0), iNext(0);
+
+ for(;;)
+ {
+ iNext = sSource.find(sFind, iPos);
+ sResult.append(sSource, iPos, iNext-iPos);
+
+ if( iNext==string_type::npos )
+ break;
+
+ sResult.append(sReplaceWith);
+ iPos = iNext + sFind.length();
+ }
+
+ sSource.swap(sResult);
+ }
+
+
+ //------------------------------------------------------------------------------
+ /** \brief Replace all occurences of a substring with another string. */
+ void ParserError::ReplaceSubString( string_type &sSource,
+ const string_type &sFind,
+ int iReplaceWith) const
+ {
+ stringstream_type stream;
+ stream << iReplaceWith;
+ ReplaceSubString(sSource, sFind, stream.str());
+ }
+
+ //------------------------------------------------------------------------------
+ /** \brief Replace all occurences of a substring with another string. */
+ void ParserError::ReplaceSubString( string_type &sSource,
+ const string_type &sFind,
+ char_type cReplaceWith) const
+ {
+ stringstream_type stream;
+ stream << cReplaceWith;
+ ReplaceSubString(sSource, sFind, stream.str());
+ }
+
+ //------------------------------------------------------------------------------
+ void ParserError::Reset()
+ {
+ m_sMsg = _T("");
+ m_Err = ErrorContext();
+ }
+
+ //------------------------------------------------------------------------------
+ const string_type& ParserError::GetExpr() const
+ {
+ return m_Err.Expr;
+ }
+
+ //------------------------------------------------------------------------------
+ string_type ParserError::GetMsg() const
+ {
+ string_type sMsg(m_sMsg);
+ ReplaceSubString(sMsg, _T("$EXPR$"), m_Err.Expr);
+ ReplaceSubString(sMsg, _T("$IDENT$"), m_Err.Ident);
+ ReplaceSubString(sMsg, _T("$POS$"), m_Err.Pos);
+ ReplaceSubString(sMsg, _T("$ARG$"), m_Err.Arg);
+ ReplaceSubString(sMsg, _T("$TYPE1$"), m_Err.Type1);
+ ReplaceSubString(sMsg, _T("$TYPE2$"), m_Err.Type2);
+ ReplaceSubString(sMsg, _T("$HINT$"), m_Err.Hint);
+ return sMsg;
+ }
+
+ //------------------------------------------------------------------------------
+ ErrorContext& ParserError::GetContext()
+ {
+ return m_Err;
+ }
+
+ //------------------------------------------------------------------------------
+ /** \brief Return the expression position related to the error.
+
+ If the error is not related to a distinct position this will return -1
+ */
+ int ParserError::GetPos() const
+ {
+ return m_Err.Pos;
+ }
+
+ //------------------------------------------------------------------------------
+ /** \brief Return string related with this token (if available). */
+ const string_type& ParserError::GetToken() const
+ {
+ return m_Err.Ident;
+ }
+
+ //------------------------------------------------------------------------------
+ /** \brief Return the error code. */
+ EErrorCodes ParserError::GetCode() const
+ {
+ return m_Err.Errc;
+ }
+} // namespace mu
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpError.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpError.h Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,203 @@
+/*
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+*/
+#ifndef MUP_ERROR_H
+#define MUP_ERROR_H
+
+#include <cassert>
+#include <stdexcept>
+#include <string>
+#include <sstream>
+#include <vector>
+#include <memory>
+
+#include "mpTypes.h"
+
+
+MUP_NAMESPACE_START
+
+ /** \brief Error codes.
+
+ This is the complete list of all error codes used by muParserX
+ */
+ enum EErrorCodes
+ {
+ // Expression syntax errors
+ ecUNEXPECTED_OPERATOR = 0, ///< Unexpected binary operator found
+ ecUNASSIGNABLE_TOKEN = 1, ///< Token cant be identified.
+ ecUNEXPECTED_EOF = 2, ///< Unexpected end of expression. (Example: "2+sin(")
+ ecUNEXPECTED_COMMA = 3, ///< An unexpected comma has been found. (Example: "1,23")
+ ecUNEXPECTED_VAL = 4, ///< An unexpected value token has been found
+ ecUNEXPECTED_VAR = 5, ///< An unexpected variable token has been found
+ ecUNEXPECTED_PARENS = 6, ///< Unexpected Parenthesis, opening or closing
+ ecUNEXPECTED_STR = 7, ///< A string has been found at an inapropriate position
+ ecUNEXPECTED_CONDITIONAL = 8,
+ ecUNEXPECTED_NEWLINE = 9,
+ ecSTRING_EXPECTED = 10, ///< A string function has been called with a different type of argument
+ ecVAL_EXPECTED = 11, ///< A numerical function has been called with a non value type of argument
+ ecMISSING_PARENS = 12, ///< Missing parens. (Example: "3*sin(3")
+ ecMISSING_ELSE_CLAUSE = 13,
+ ecMISPLACED_COLON = 14,
+ ecUNEXPECTED_FUN = 15, ///< Unexpected function found. (Example: "sin(8)cos(9)")
+ ecUNTERMINATED_STRING = 16, ///< unterminated string constant. (Example: "3*valueof("hello)")
+ ecTOO_MANY_PARAMS = 17, ///< Too many function parameters
+ ecTOO_FEW_PARAMS = 18, ///< Too few function parameters. (Example: "ite(1<2,2)")
+ ecTYPE_CONFLICT = 19, ///< Generic type conflict
+ ecTYPE_CONFLICT_FUN = 20, ///< Function argument type conflict.
+ ecTYPE_CONFLICT_IDX = 21, ///< Function argument type conflict.
+ ecINVALID_TYPE = 22,
+ ecINVALID_TYPECAST = 23, ///< Invalid Value token cast.
+ ecARRAY_SIZE_MISMATCH = 24, ///< Array size mismatch during a vector operation
+ ecNOT_AN_ARRAY = 25, ///< Using the index operator on a scalar variable
+ ecUNEXPECTED_SQR_BRACKET = 26, ///< Invalid use of the index operator
+
+ ecINVALID_NAME = 27, ///< Invalid function, variable or constant name.
+ ecBUILTIN_OVERLOAD = 28, ///< Trying to overload builtin operator
+ ecINVALID_FUN_PTR = 29, ///< Invalid callback function pointer
+ ecINVALID_VAR_PTR = 30, ///< Invalid variable pointer
+ ecINVALID_PARAMETER = 31, ///< Invalid function parameter
+ ecINVALID_NUMBER_OF_PARAMETERS = 32,
+
+ ecNAME_CONFLICT = 33, ///< Name conflict
+ ecOPT_PRI = 34, ///< Invalid operator priority
+ ecASSIGNEMENT_TO_VALUE = 35, ///< Assignment to operator (3=4 instead of a=4)
+
+ //
+ ecDOMAIN_ERROR = 36, ///< catch division by zero, sqrt(-1), log(0) (currently unused)
+ ecDIV_BY_ZERO = 37, ///< Division by zero (currently unused)
+ ecGENERIC = 38, ///< Generic error
+
+ ecAPI_INVALID_PROTOTYPE = 39, ///< API error: tried to create a callback with an invalid prototype definition
+ ecAPI_NOT_AN_ARRAY = 40, ///< Trying to access a non array type as an array
+ ecAPI_INVALID_DIMENSION = 41, ///< Trying to access a non array type as an array
+ ecINDEX_OUT_OF_BOUNDS = 42, ///< Array index is out of bounds
+ ecINDEX_DIMENSION = 43,
+ ecMISSING_SQR_BRACKET = 44, ///< The index operator was not closed properly (i.e. "v[3")
+ ecEVAL = 45, ///< Error while evaluating function / operator
+
+ // internal errors
+ ecINTERNAL_ERROR = 46, ///< 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
+ };
+
+ //---------------------------------------------------------------------------
+ class ParserErrorMsg
+ {
+ public:
+ typedef ParserErrorMsg self_type;
+
+ ~ParserErrorMsg();
+
+ static const ParserErrorMsg& Instance();
+ string_type operator[](unsigned a_iIdx) const;
+
+ private:
+ std::vector<string_type> m_vErrMsg;
+ static const self_type m_Instance;
+
+ ParserErrorMsg& operator=(const ParserErrorMsg &);
+ ParserErrorMsg(const ParserErrorMsg&);
+ ParserErrorMsg();
+ };
+
+ //---------------------------------------------------------------------------
+ /** \brief Error context class.
+
+ This struct contains the data associated with parser erros.
+ */
+ struct ErrorContext
+ {
+ /** \brief Creates an empty ErrorContext object.
+
+ All Members are initialised to an invalid state.
+ */
+ ErrorContext(EErrorCodes a_iErrc = ecUNDEFINED,
+ int a_iPos = -1,
+ string_type a_sIdent = string_type() );
+
+ ErrorContext(EErrorCodes a_iErrc,
+ int a_iPos,
+ string_type a_sIdent,
+ char_type cType1,
+ char_type cType2,
+ int nArg);
+
+ string_type Expr; ///> The expression string.
+ string_type Ident; ///> The identifier of the token that caused the error.
+ string_type Hint; ///> Additional message
+ EErrorCodes Errc; ///> The error code
+ char_type Type1; ///> For type conflicts only! This is the type that was expected.
+ char_type Type2; ///> For type conflicts only! This is the type that was actually found.
+ int Arg; ///> The number of arguments that were expected.
+ int Pos; ///> Position inside the expression where the error occured.
+ };
+
+ //---------------------------------------------------------------------------
+ /** \brief Error class of the parser.
+ \author Ingo Berg
+
+ Part of the math parser package.
+ */
+ class ParserError
+ {
+ private:
+ //------------------------------------------------------------------------------
+ /** \brief Replace all ocuurences of a substring with another string. */
+ void ReplaceSubString(string_type &strSource,
+ const string_type &strFind,
+ const string_type &strReplaceWith) const;
+ void ReplaceSubString(string_type &sSource,
+ const string_type &sFind,
+ int iReplaceWith) const;
+ void ReplaceSubString(string_type &sSource,
+ const string_type &sFind,
+ char_type cReplaceWith) const;
+ void Reset();
+
+ public:
+ ParserError();
+ ParserError(const string_type &sMsg);
+ ParserError(const ErrorContext &a_Err);
+ ParserError(const ParserError &a_Obj);
+ ParserError& operator=(const ParserError &a_Obj);
+
+ const string_type& GetExpr() const;
+ string_type GetMsg() const;
+ int GetPos() const;
+ const string_type& GetToken() const;
+ EErrorCodes GetCode() const;
+ ErrorContext& GetContext();
+
+ private:
+ ErrorContext m_Err; ///< Error context data
+ string_type m_sMsg; ///< The message string with all wildcards still in place.
+ const ParserErrorMsg &m_ErrMsg;
+ };
+} // namespace mu
+
+#endif
+
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpFuncCmplx.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpFuncCmplx.cpp Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,595 @@
+/** \file
+ \brief Definition of functions for complex valued operations.
+
+<pre>
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2011 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+</pre>
+*/
+#include "mpFuncCmplx.h"
+
+//--- Standard includes ----------------------------------------------------
+#include <cmath>
+#include <cassert>
+#include <complex>
+#include <iostream>
+
+//--- Parser framework -----------------------------------------------------
+#include "mpValue.h"
+#include "mpError.h"
+
+
+MUP_NAMESPACE_START
+
+ //-----------------------------------------------------------------------
+ //
+ // class FunCmplxReal
+ //
+ //-----------------------------------------------------------------------
+
+ FunCmplxReal::FunCmplxReal(IPackage *package)
+ :ICallback(cmFUNC, _T("real"), 1, package)
+ {}
+
+ //-----------------------------------------------------------------------
+ FunCmplxReal::~FunCmplxReal()
+ {}
+
+ //-----------------------------------------------------------------------
+ void FunCmplxReal::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int)
+ {
+ float_type v = a_pArg[0]->GetFloat();
+ *ret = v;
+ }
+
+ //-----------------------------------------------------------------------
+ const char_type* FunCmplxReal::GetDesc() const
+ {
+ return _T("real(x) - Returns the real part of the complex number x.");
+ }
+
+ //-----------------------------------------------------------------------
+ IToken* FunCmplxReal::Clone() const
+ {
+ return new FunCmplxReal(*this);
+ }
+
+ //-----------------------------------------------------------------------
+ //
+ // class FunCmplxImag
+ //
+ //-----------------------------------------------------------------------
+
+ FunCmplxImag::FunCmplxImag()
+ :ICallback(cmFUNC, _T("imag"), 1)
+ {}
+
+ //-----------------------------------------------------------------------
+ void FunCmplxImag::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int)
+ {
+ float_type v = a_pArg[0]->GetImag();
+ *ret = v;
+ }
+
+ //-----------------------------------------------------------------------
+ const char_type* FunCmplxImag::GetDesc() const
+ {
+ return _T("imag(x) - Returns the imaginary part of the complex number x.");
+ }
+
+ //-----------------------------------------------------------------------
+ IToken* FunCmplxImag::Clone() const
+ {
+ return new FunCmplxImag(*this);
+ }
+
+ //-----------------------------------------------------------------------
+ //
+ // class FunCmplxConj
+ //
+ //-----------------------------------------------------------------------
+
+ FunCmplxConj::FunCmplxConj()
+ :ICallback(cmFUNC, _T("conj"), 1)
+ {}
+
+ //-----------------------------------------------------------------------
+ void FunCmplxConj::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int)
+ {
+ *ret = cmplx_type(a_pArg[0]->GetFloat(), -a_pArg[0]->GetImag());
+ }
+
+ //-----------------------------------------------------------------------
+ const char_type* FunCmplxConj::GetDesc() const
+ {
+ return _T("conj(x) - Returns the complex conjugate of the complex number x.");
+ }
+
+ //-----------------------------------------------------------------------
+ IToken* FunCmplxConj::Clone() const
+ {
+ return new FunCmplxConj(*this);
+ }
+
+ //-----------------------------------------------------------------------
+ //
+ // class FunCmplxArg
+ //
+ //-----------------------------------------------------------------------
+
+ FunCmplxArg::FunCmplxArg()
+ :ICallback(cmFUNC, _T("arg"), 1)
+ {}
+
+ //-----------------------------------------------------------------------
+ void FunCmplxArg::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int)
+ {
+ cmplx_type v(a_pArg[0]->GetFloat(), a_pArg[0]->GetImag());
+ *ret = std::arg(v);
+ }
+
+ //-----------------------------------------------------------------------
+ const char_type* FunCmplxArg::GetDesc() const
+ {
+ return _T("arg(x) - Returns the phase angle (or angular component) of the complex number x, expressed in radians.");
+ }
+
+ //-----------------------------------------------------------------------
+ IToken* FunCmplxArg::Clone() const
+ {
+ return new FunCmplxArg(*this);
+ }
+
+ //-----------------------------------------------------------------------
+ //
+ // class FunCmplxNorm
+ //
+ //-----------------------------------------------------------------------
+
+ FunCmplxNorm::FunCmplxNorm()
+ :ICallback(cmFUNC, _T("norm"), 1)
+ {}
+
+ //-----------------------------------------------------------------------
+ void FunCmplxNorm::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int)
+ {
+ cmplx_type v(a_pArg[0]->GetFloat(), a_pArg[0]->GetImag());
+ *ret = std::norm(v);
+ }
+
+ //-----------------------------------------------------------------------
+ const char_type* FunCmplxNorm::GetDesc() const
+ {
+ return _T("norm(x) - Returns the norm value of the complex number x.")
+ _T(" The norm value of a complex number is the squared magnitude,")
+ _T(" defined as the addition of the square of both the real part")
+ _T(" and the imaginary part (without the imaginary unit). This is")
+ _T(" the square of abs (x).");
+ }
+
+ //-----------------------------------------------------------------------
+ IToken* FunCmplxNorm::Clone() const
+ {
+ return new FunCmplxNorm(*this);
+ }
+
+ //-----------------------------------------------------------------------
+ //
+ // class FunCmplxCos
+ //
+ //-----------------------------------------------------------------------
+
+ FunCmplxCos::FunCmplxCos()
+ :ICallback(cmFUNC, _T("cos"), 1)
+ {}
+
+ //-----------------------------------------------------------------------
+ void FunCmplxCos::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int)
+ {
+ if (a_pArg[0]->IsNonComplexScalar())
+ {
+ *ret = cos(a_pArg[0]->GetFloat());
+ }
+ else
+ {
+ cmplx_type v(a_pArg[0]->GetFloat(), a_pArg[0]->GetImag());
+ *ret = cos(v);
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ const char_type* FunCmplxCos::GetDesc() const
+ {
+ return _T("cos(x) - Returns the cosine of the number x.");
+ }
+
+ //-----------------------------------------------------------------------
+ IToken* FunCmplxCos::Clone() const
+ {
+ return new FunCmplxCos(*this);
+ }
+
+ //-----------------------------------------------------------------------
+ //
+ // class FunCmplxSin
+ //
+ //-----------------------------------------------------------------------
+
+ FunCmplxSin::FunCmplxSin()
+ :ICallback(cmFUNC, _T("sin"), 1)
+ {}
+
+ //-----------------------------------------------------------------------
+ void FunCmplxSin::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int)
+ {
+ if (a_pArg[0]->IsNonComplexScalar())
+ {
+ *ret = sin(a_pArg[0]->GetFloat());
+ }
+ else
+ {
+ cmplx_type v(a_pArg[0]->GetFloat(), a_pArg[0]->GetImag());
+ *ret = sin(v);
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ const char_type* FunCmplxSin::GetDesc() const
+ {
+ return _T("sin(x) - Returns the sine of the number x.");
+ }
+
+ //-----------------------------------------------------------------------
+ IToken* FunCmplxSin::Clone() const
+ {
+ return new FunCmplxSin(*this);
+ }
+
+ //-----------------------------------------------------------------------
+ //
+ // class FunCmplxCosH
+ //
+ //-----------------------------------------------------------------------
+
+ FunCmplxCosH::FunCmplxCosH()
+ :ICallback(cmFUNC, _T("cosh"), 1)
+ {}
+
+ //-----------------------------------------------------------------------
+ void FunCmplxCosH::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int)
+ {
+ cmplx_type v(a_pArg[0]->GetFloat(), a_pArg[0]->GetImag());
+ *ret = cosh(v);
+ }
+
+ //-----------------------------------------------------------------------
+ const char_type* FunCmplxCosH::GetDesc() const
+ {
+ return _T("cosh(x) - Returns the hyperbolic cosine of the number x.");
+ }
+
+ //-----------------------------------------------------------------------
+ IToken* FunCmplxCosH::Clone() const
+ {
+ return new FunCmplxCosH(*this);
+ }
+
+ //-----------------------------------------------------------------------
+ //
+ // class FunCmplxSinH
+ //
+ //-----------------------------------------------------------------------
+
+ FunCmplxSinH::FunCmplxSinH()
+ :ICallback(cmFUNC, _T("sinh"), 1)
+ {}
+
+ //-----------------------------------------------------------------------
+ void FunCmplxSinH::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int)
+ {
+ cmplx_type v(a_pArg[0]->GetFloat(), a_pArg[0]->GetImag());
+ *ret = sinh(v);
+ }
+
+ //-----------------------------------------------------------------------
+ const char_type* FunCmplxSinH::GetDesc() const
+ {
+ return _T("sinh(x) - Returns the hyperbolic sine of the complex number x.");
+ }
+
+ //-----------------------------------------------------------------------
+ IToken* FunCmplxSinH::Clone() const
+ {
+ return new FunCmplxSinH(*this);
+ }
+
+ //-----------------------------------------------------------------------
+ //
+ // class FunCmplxTan
+ //
+ //-----------------------------------------------------------------------
+
+ FunCmplxTan::FunCmplxTan()
+ :ICallback(cmFUNC, _T("tan"), 1)
+ {}
+
+ //-----------------------------------------------------------------------
+ void FunCmplxTan::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int)
+ {
+ if (a_pArg[0]->IsNonComplexScalar())
+ {
+ *ret = tan(a_pArg[0]->GetFloat());
+ }
+ else
+ {
+ cmplx_type v(a_pArg[0]->GetFloat(), a_pArg[0]->GetImag());
+ *ret = tan(v);
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ const char_type* FunCmplxTan::GetDesc() const
+ {
+ return _T("tan(x) - Returns the tangens of the number x.");
+ }
+
+ //-----------------------------------------------------------------------
+ IToken* FunCmplxTan::Clone() const
+ {
+ return new FunCmplxTan(*this);
+ }
+
+ //-----------------------------------------------------------------------
+ //
+ // class FunCmplxTanH
+ //
+ //-----------------------------------------------------------------------
+
+ FunCmplxTanH::FunCmplxTanH()
+ :ICallback(cmFUNC, _T("tanh"), 1)
+ {}
+
+ //-----------------------------------------------------------------------
+ void FunCmplxTanH::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int)
+ {
+ cmplx_type v(a_pArg[0]->GetFloat(), a_pArg[0]->GetImag());
+ *ret = tanh(v);
+ }
+
+ //-----------------------------------------------------------------------
+ const char_type* FunCmplxTanH::GetDesc() const
+ {
+ return _T("tanh(x) - Returns the hyperbolic tangent of the complex number x.");
+ }
+
+ //-----------------------------------------------------------------------
+ IToken* FunCmplxTanH::Clone() const
+ {
+ return new FunCmplxTanH(*this);
+ }
+
+ //-----------------------------------------------------------------------
+ //
+ // class FunCmplxSqrt
+ //
+ //-----------------------------------------------------------------------
+
+ FunCmplxSqrt::FunCmplxSqrt()
+ :ICallback(cmFUNC, _T("sqrt"), 1)
+ {}
+
+ //-----------------------------------------------------------------------
+ void FunCmplxSqrt::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int)
+ {
+ *ret = sqrt((*a_pArg[0]).GetComplex());
+ }
+
+ //-----------------------------------------------------------------------
+ const char_type* FunCmplxSqrt::GetDesc() const
+ {
+ return _T("sqrt(x) - Returns the square root of x.");
+ }
+
+ //-----------------------------------------------------------------------
+ IToken* FunCmplxSqrt::Clone() const
+ {
+ return new FunCmplxSqrt(*this);
+ }
+
+ //-----------------------------------------------------------------------
+ //
+ // class FunCmplxExp
+ //
+ //-----------------------------------------------------------------------
+
+ FunCmplxExp::FunCmplxExp()
+ :ICallback(cmFUNC, _T("exp"), 1)
+ {}
+
+ //-----------------------------------------------------------------------
+ void FunCmplxExp::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int)
+ {
+ cmplx_type v(a_pArg[0]->GetFloat(), a_pArg[0]->GetImag());
+ *ret = exp(v);
+ }
+
+ //-----------------------------------------------------------------------
+ const char_type* FunCmplxExp::GetDesc() const
+ {
+ return _T("exp(x) - Returns the base-e exponential of the complex number x.");
+ }
+
+ //-----------------------------------------------------------------------
+ IToken* FunCmplxExp::Clone() const
+ {
+ return new FunCmplxExp(*this);
+ }
+
+ //-----------------------------------------------------------------------
+ //
+ // class FunCmplxLn
+ //
+ //-----------------------------------------------------------------------
+
+ FunCmplxLn::FunCmplxLn()
+ :ICallback(cmFUNC, _T("ln"), 1)
+ {}
+
+ //-----------------------------------------------------------------------
+ void FunCmplxLn::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int)
+ {
+ cmplx_type v(a_pArg[0]->GetFloat(), a_pArg[0]->GetImag());
+ *ret = log(v);
+ }
+
+ //-----------------------------------------------------------------------
+ const char_type* FunCmplxLn::GetDesc() const
+ {
+ return _T("ln(x) - Returns the natural (base-e) logarithm of the complex number x.");
+ }
+
+ //-----------------------------------------------------------------------
+ IToken* FunCmplxLn::Clone() const
+ {
+ return new FunCmplxLn(*this);
+ }
+
+ //-----------------------------------------------------------------------
+ //
+ // class FunCmplxLog
+ //
+ //-----------------------------------------------------------------------
+
+ FunCmplxLog::FunCmplxLog()
+ :ICallback(cmFUNC, _T("log"), 1)
+ {}
+
+ //-----------------------------------------------------------------------
+ void FunCmplxLog::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int)
+ {
+ cmplx_type v(a_pArg[0]->GetFloat(), a_pArg[0]->GetImag());
+ *ret = log10(v);
+ }
+
+
+ //-----------------------------------------------------------------------
+ const char_type* FunCmplxLog::GetDesc() const
+ {
+ return _T("log(x) - Common logarithm of x, for values of x greater than zero.");
+ }
+
+ //-----------------------------------------------------------------------
+ IToken* FunCmplxLog::Clone() const
+ {
+ return new FunCmplxLog(*this);
+ }
+
+ //-----------------------------------------------------------------------
+ //
+ // class FunCmplxLog10
+ //
+ //-----------------------------------------------------------------------
+
+ FunCmplxLog10::FunCmplxLog10()
+ :ICallback(cmFUNC, _T("log10"), 1)
+ {}
+
+ //-----------------------------------------------------------------------
+ void FunCmplxLog10::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int)
+ {
+ cmplx_type v(a_pArg[0]->GetFloat(), a_pArg[0]->GetImag());
+ *ret = log10(v);
+ }
+
+ //-----------------------------------------------------------------------
+ const char_type* FunCmplxLog10::GetDesc() const
+ {
+ return _T("log10(x) - Common logarithm of x, for values of x greater than zero.");
+ }
+
+ //-----------------------------------------------------------------------
+ IToken* FunCmplxLog10::Clone() const
+ {
+ return new FunCmplxLog10(*this);
+ }
+
+ //-----------------------------------------------------------------------
+ //
+ // class FunCmplxLog2
+ //
+ //-----------------------------------------------------------------------
+
+ FunCmplxLog2::FunCmplxLog2()
+ :ICallback(cmFUNC, _T("log2"), 1)
+ {}
+
+ //-----------------------------------------------------------------------
+ void FunCmplxLog2::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int)
+ {
+ std::complex<float_type> v(a_pArg[0]->GetFloat(), a_pArg[0]->GetImag());
+ *ret = log(v) * (float_type)1.0/log((float_type)2.0);
+ }
+
+ //-----------------------------------------------------------------------
+ const char_type* FunCmplxLog2::GetDesc() const
+ {
+ return _T("log2(x) - Logarithm to base 2 of x, for values of x greater than zero.");
+ }
+
+ //-----------------------------------------------------------------------
+ IToken* FunCmplxLog2::Clone() const
+ {
+ return new FunCmplxLog2(*this);
+ }
+
+ //-----------------------------------------------------------------------
+ //
+ // class FunCmplxAbs
+ //
+ //-----------------------------------------------------------------------
+
+ FunCmplxAbs::FunCmplxAbs()
+ :ICallback(cmFUNC, _T("abs"), 1)
+ {}
+
+ //-----------------------------------------------------------------------
+ void FunCmplxAbs::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int)
+ {
+ float_type v = sqrt(a_pArg[0]->GetFloat()*a_pArg[0]->GetFloat() +
+ a_pArg[0]->GetImag()*a_pArg[0]->GetImag());
+ *ret = v;
+ }
+
+ //-----------------------------------------------------------------------
+ const char_type* FunCmplxAbs::GetDesc() const
+ {
+ return _T("abs(x) - Returns the absolute value of x.");
+ }
+
+ //-----------------------------------------------------------------------
+ IToken* FunCmplxAbs::Clone() const
+ {
+ return new FunCmplxAbs(*this);
+ }
+
+MUP_NAMESPACE_END
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpFuncCmplx.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpFuncCmplx.h Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,239 @@
+/** \file
+ \brief Definition of functions for complex valued operations.
+
+<pre>
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2011 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+</pre>
+*/
+#ifndef MUP_COMPLEX_FUNCTIONS_H
+#define MUP_COMPLEX_FUNCTIONS_H
+
+#include "mpICallback.h"
+
+
+MUP_NAMESPACE_START
+
+ //-----------------------------------------------------------------------
+ /** \brief Parser callback object for returning the real part of a complex number.
+ \ingroup functions
+ */
+ class FunCmplxReal : public ICallback
+ {
+ public:
+ FunCmplxReal(IPackage *pPackage = NULL);
+ virtual ~FunCmplxReal();
+ virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc);
+ virtual const char_type* GetDesc() const;
+ virtual IToken* Clone() const;
+ };
+
+ //-----------------------------------------------------------------------
+ /** \brief Parser callback object for returning the imaginary part of a complex number.
+ \ingroup functions
+ */
+ class FunCmplxImag : public ICallback
+ {
+ public:
+ FunCmplxImag();
+ virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc);
+ virtual const char_type* GetDesc() const;
+ virtual IToken* Clone() const;
+ };
+
+ //-----------------------------------------------------------------------
+ /** \brief Parser callback object for returning the complex conjugate of
+ the complex number.
+ \ingroup functions
+ */
+ class FunCmplxConj : public ICallback
+ {
+ public:
+ FunCmplxConj();
+ virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc);
+ virtual const char_type* GetDesc() const;
+ virtual IToken* Clone() const;
+ };
+
+
+ //-----------------------------------------------------------------------
+ /** \brief Parser callback object for returning the phase angle
+ (or angular component) of a complex number, expressed in radians.
+ \ingroup functions
+ */
+ class FunCmplxArg : public ICallback
+ {
+ public:
+ FunCmplxArg();
+ virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc);
+ virtual const char_type* GetDesc() const;
+ virtual IToken* Clone() const;
+ };
+
+ //-----------------------------------------------------------------------
+ /** \brief Parser callback object for returning the norm value of the
+ complex number phase angle.
+ \ingroup functions
+ */
+ class FunCmplxNorm : public ICallback
+ {
+ public:
+ FunCmplxNorm();
+ virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc);
+ virtual const char_type* GetDesc() const;
+ virtual IToken* Clone() const;
+ };
+
+ //-----------------------------------------------------------------------
+ class FunCmplxCos : public ICallback
+ {
+ public:
+ FunCmplxCos();
+ virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc);
+ virtual const char_type* GetDesc() const;
+ virtual IToken* Clone() const;
+ };
+
+ //-----------------------------------------------------------------------
+ class FunCmplxSin : public ICallback
+ {
+ public:
+ FunCmplxSin();
+ virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc);
+ virtual const char_type* GetDesc() const;
+ virtual IToken* Clone() const;
+ };
+
+ //-----------------------------------------------------------------------
+ class FunCmplxCosH : public ICallback
+ {
+ public:
+ FunCmplxCosH();
+ virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc);
+ virtual const char_type* GetDesc() const;
+ virtual IToken* Clone() const;
+ };
+
+ //-----------------------------------------------------------------------
+ class FunCmplxSinH : public ICallback
+ {
+ public:
+ FunCmplxSinH();
+ virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc);
+ virtual const char_type* GetDesc() const;
+ virtual IToken* Clone() const;
+ };
+
+ //-----------------------------------------------------------------------
+ class FunCmplxTan : public ICallback
+ {
+ public:
+ FunCmplxTan();
+ virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc);
+ virtual const char_type* GetDesc() const;
+ virtual IToken* Clone() const;
+ };
+
+ //-----------------------------------------------------------------------
+ class FunCmplxTanH : public ICallback
+ {
+ public:
+ FunCmplxTanH();
+ virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc);
+ virtual const char_type* GetDesc() const;
+ virtual IToken* Clone() const;
+ };
+
+ //-----------------------------------------------------------------------
+ class FunCmplxSqrt : public ICallback
+ {
+ public:
+ FunCmplxSqrt();
+ virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc);
+ virtual const char_type* GetDesc() const;
+ virtual IToken* Clone() const;
+ };
+
+ //-----------------------------------------------------------------------
+ class FunCmplxExp : public ICallback
+ {
+ public:
+ FunCmplxExp();
+ virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc);
+ virtual const char_type* GetDesc() const;
+ virtual IToken* Clone() const;
+ };
+
+ //-----------------------------------------------------------------------
+ class FunCmplxLn : public ICallback
+ {
+ public:
+ FunCmplxLn();
+ virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc);
+ virtual const char_type* GetDesc() const;
+ virtual IToken* Clone() const;
+ };
+
+ //-----------------------------------------------------------------------
+ class FunCmplxLog : public ICallback
+ {
+ public:
+ FunCmplxLog();
+ virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc);
+ virtual const char_type* GetDesc() const;
+ virtual IToken* Clone() const;
+ };
+
+ //-----------------------------------------------------------------------
+ class FunCmplxLog10 : public ICallback
+ {
+ public:
+ FunCmplxLog10();
+ virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc);
+ virtual const char_type* GetDesc() const;
+ virtual IToken* Clone() const;
+ };
+
+ //-----------------------------------------------------------------------
+ class FunCmplxLog2 : public ICallback
+ {
+ public:
+ FunCmplxLog2();
+ virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc);
+ virtual const char_type* GetDesc() const;
+ virtual IToken* Clone() const;
+ };
+
+ //-----------------------------------------------------------------------
+ class FunCmplxAbs : public ICallback
+ {
+ public:
+
+ FunCmplxAbs();
+ virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc);
+ virtual const char_type* GetDesc() const;
+ virtual IToken* Clone() const;
+ };
+} // namespace mu
+
+#endif
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpFuncCommon.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpFuncCommon.cpp Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,255 @@
+/*
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+*/
+#include "mpFuncCommon.h"
+
+#include <cassert>
+#include <string>
+#include <iostream>
+
+#include "mpValue.h"
+#include "mpParserBase.h"
+
+
+MUP_NAMESPACE_START
+
+ //------------------------------------------------------------------------------
+ //
+ // FunParserID
+ //
+ //------------------------------------------------------------------------------
+
+ FunParserID::FunParserID()
+ :ICallback(cmFUNC, _T("parserid"), 0)
+ {}
+
+ //------------------------------------------------------------------------------
+ /** \brief Returns the number of elements stored in the first parameter. */
+ void FunParserID::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc)
+ {
+ ParserXBase &parser = *GetParent();
+ string_type sVer = _T("muParserX V") + parser.GetVersion();
+ *ret = sVer;
+ }
+
+ //------------------------------------------------------------------------------
+ const char_type* FunParserID::GetDesc() const
+ {
+ return _T("parserid() - muParserX version information");
+ }
+
+ //------------------------------------------------------------------------------
+ IToken* FunParserID::Clone() const
+ {
+ return new FunParserID(*this);
+ }
+
+ //------------------------------------------------------------------------------
+ //
+ // Max Function
+ //
+ //------------------------------------------------------------------------------
+
+ FunMax::FunMax() : ICallback(cmFUNC, _T("max"), -1)
+ {}
+
+ //------------------------------------------------------------------------------
+ void FunMax::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc)
+ {
+ float_type max(-1e30), val;
+ for (int i=0; i<a_iArgc; ++i)
+ {
+ switch(a_pArg[i]->GetType())
+ {
+ case 'f': val = a_pArg[i]->GetFloat(); break;
+ case 'i': val = a_pArg[i]->GetFloat(); break;
+ case 'n': break; // ignore not in list entries (missing parameter)
+ case 'c':
+ default:
+ {
+ ErrorContext err;
+ err.Errc = ecTYPE_CONFLICT_FUN;
+ err.Arg = i+1;
+ err.Type1 = a_pArg[i]->GetType();
+ err.Type2 = 'f';
+ throw ParserError(err);
+ }
+ }
+ max = std::max(max, val);
+ }
+
+ *ret = max;
+ }
+
+ //------------------------------------------------------------------------------
+ const char_type* FunMax::GetDesc() const
+ {
+ return _T("max(x,y,...,z) - Returns the maximum value from all of its function arguments.");
+ }
+
+ //------------------------------------------------------------------------------
+ IToken* FunMax::Clone() const
+ {
+ return new FunMax(*this);
+ }
+
+ //------------------------------------------------------------------------------
+ //
+ // Min Function
+ //
+ //------------------------------------------------------------------------------
+
+ FunMin::FunMin() : ICallback(cmFUNC, _T("min"), -1)
+ {}
+
+ //------------------------------------------------------------------------------
+ /** \brief Returns the minimum value of all values.
+ \param a_pArg Pointer to an array of Values
+ \param a_iArgc Number of values stored in a_pArg
+ */
+ void FunMin::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc)
+ {
+ float_type min(1e30), val(min);
+
+ for (int i=0; i<a_iArgc; ++i)
+ {
+ switch(a_pArg[i]->GetType())
+ {
+ case 'f':
+ case 'i': val = a_pArg[i]->GetFloat(); break;
+ default:
+ {
+ ErrorContext err;
+ err.Errc = ecTYPE_CONFLICT_FUN;
+ err.Arg = i+1;
+ err.Type1 = a_pArg[i]->GetType();
+ err.Type2 = 'f';
+ throw ParserError(err);
+ }
+ }
+ min = std::min(min, val);
+ }
+
+ *ret = min;
+ }
+
+ //------------------------------------------------------------------------------
+ const char_type* FunMin::GetDesc() const
+ {
+ return _T("min(x,y,...,z) - Returns the minimum value from all of its function arguments.");
+ }
+
+ //------------------------------------------------------------------------------
+ IToken* FunMin::Clone() const
+ {
+ return new FunMin(*this);
+ }
+
+ //------------------------------------------------------------------------------
+ //
+ // class FunSum
+ //
+ //------------------------------------------------------------------------------
+
+ FunSum::FunSum()
+ :ICallback(cmFUNC, _T("sum"), -1)
+ {}
+
+ //------------------------------------------------------------------------------
+ /** \brief Returns the minimum value of all values.
+ \param a_pArg Pointer to an array of Values
+ \param a_iArgc Number of values stored in a_pArg
+ */
+ void FunSum::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc)
+ {
+ float_type sum(0);
+
+ for (int i=0; i<a_iArgc; ++i)
+ {
+ switch(a_pArg[i]->GetType())
+ {
+ case 'f':
+ case 'i': sum += a_pArg[i]->GetFloat(); break;
+ default:
+ {
+ ErrorContext err;
+ err.Errc = ecTYPE_CONFLICT_FUN;
+ err.Arg = i+1;
+ err.Type1 = a_pArg[i]->GetType();
+ err.Type2 = 'f';
+ throw ParserError(err);
+ }
+ }
+ }
+
+ *ret = sum;
+ }
+
+ //------------------------------------------------------------------------------
+ const char_type* FunSum::GetDesc() const
+ {
+ return _T("sum(x,y,...,z) - Returns the sum of all arguments.");
+ }
+
+ //------------------------------------------------------------------------------
+ IToken* FunSum::Clone() const
+ {
+ return new FunSum(*this);
+ }
+
+ //------------------------------------------------------------------------------
+ //
+ // SizeOf
+ //
+ //------------------------------------------------------------------------------
+
+ FunSizeOf::FunSizeOf()
+ :ICallback(cmFUNC, _T("sizeof"), 1)
+ {}
+
+ //------------------------------------------------------------------------------
+ FunSizeOf::~FunSizeOf()
+ {}
+
+ //------------------------------------------------------------------------------
+ /** \brief Returns the number of elements stored in the first parameter. */
+ void FunSizeOf::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc)
+ {
+ assert(a_iArgc==1);
+ *ret = (int)(a_pArg[0]->GetArray().GetRows());
+ }
+
+ //------------------------------------------------------------------------------
+ const char_type* FunSizeOf::GetDesc() const
+ {
+ return _T("sizeof(a) - Returns the number of elements in a.");
+ }
+
+ //------------------------------------------------------------------------------
+ IToken* FunSizeOf::Clone() const
+ {
+ return new FunSizeOf(*this);
+ }
+
+MUP_NAMESPACE_END
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpFuncCommon.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpFuncCommon.h Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,101 @@
+/*
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+*/
+#ifndef MUP_FUNC_COMMON_H
+#define MUP_FUNC_COMMON_H
+
+#include "mpICallback.h"
+
+
+MUP_NAMESPACE_START
+
+ //------------------------------------------------------------------------------
+ /** \brief Parser function callback for determining the size of an array.
+ \ingroup functions
+ */
+ class FunParserID : public ICallback
+ {
+ public:
+ FunParserID ();
+ virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc);
+ virtual const char_type* GetDesc() const;
+ virtual IToken* Clone() const;
+ }; // class FunParserID
+
+ //------------------------------------------------------------------------------
+ /** \brief Determine maximal value from the parameter list.
+ \ingroup functions
+ */
+ class FunMax : public ICallback
+ {
+ public:
+ FunMax();
+ virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc);
+ virtual const char_type* GetDesc() const;
+ virtual IToken* Clone() const;
+ }; // class FunMax
+
+ //------------------------------------------------------------------------------
+ /** \brief Determine minimal value from the parameter list.
+ \ingroup functions
+ */
+ class FunMin : public ICallback
+ {
+ public:
+ FunMin();
+ virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc);
+ virtual const char_type* GetDesc() const;
+ virtual IToken* Clone() const;
+ }; // class FunMin
+
+ //------------------------------------------------------------------------------
+ /** \brief Parser callback for summing up all function arguments.
+ \ingroup functions
+ */
+ class FunSum : public ICallback
+ {
+ public:
+ FunSum();
+ virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc);
+ virtual const char_type* GetDesc() const;
+ virtual IToken* Clone() const;
+ }; // class FunSum
+
+ //------------------------------------------------------------------------------
+ /** \brief Parser function callback for determining the size of an array.
+ \ingroup functions
+ */
+ class FunSizeOf : public ICallback
+ {
+ public:
+ FunSizeOf();
+ virtual ~FunSizeOf();
+ virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc);
+ virtual const char_type* GetDesc() const;
+ virtual IToken* Clone() const;
+ }; // class FunSizeOf
+
+MUP_NAMESPACE_END
+
+#endif
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpFuncMatrix.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpFuncMatrix.cpp Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,106 @@
+/** \file
+ \brief Definition of functions for complex valued operations.
+
+<pre>
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+</pre>
+*/
+#include "mpFuncMatrix.h"
+
+//--- Standard includes ----------------------------------------------------
+#include <cmath>
+#include <cassert>
+#include <complex>
+#include <iostream>
+
+//--- Parser framework -----------------------------------------------------
+#include "mpValue.h"
+#include "mpError.h"
+
+
+MUP_NAMESPACE_START
+
+ //-----------------------------------------------------------------------
+ //
+ // class FunMatrixOnes
+ //
+ //-----------------------------------------------------------------------
+
+ FunMatrixOnes::FunMatrixOnes(IPackage *package)
+ :ICallback(cmFUNC, _T("ones"), -1, package)
+ {}
+
+ //-----------------------------------------------------------------------
+ FunMatrixOnes::~FunMatrixOnes()
+ {}
+
+ //-----------------------------------------------------------------------
+ void FunMatrixOnes::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int argc)
+ {
+ switch(argc)
+ {
+ case 1: // Return a vector
+ {
+ int m = a_pArg[0]->GetInteger();
+ if (m==1)
+ *ret = 1.0;
+ else
+ *ret = matrix_type(a_pArg[0]->GetInteger(), 1, 1.0);
+ }
+ break;
+
+ case 2: // Return a matrix
+ {
+ int m = a_pArg[0]->GetInteger(),
+ n = a_pArg[1]->GetInteger();
+
+ if (m==n && m==1)
+ *ret = 1.0;
+ else
+ *ret = matrix_type(a_pArg[0]->GetInteger(), a_pArg[1]->GetInteger(), 1.0);
+ }
+ break;
+
+ default:
+ ErrorContext err;
+ err.Errc = ecINVALID_NUMBER_OF_PARAMETERS;
+ err.Arg = 2;
+ err.Ident = GetIdent();
+ throw ParserError(err);
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ const char_type* FunMatrixOnes::GetDesc() const
+ {
+ return _T("ones(x [, y]) - Returns a matrix whose elements are all 1.");
+ }
+
+ //-----------------------------------------------------------------------
+ IToken* FunMatrixOnes::Clone() const
+ {
+ return new FunMatrixOnes(*this);
+ }
+
+MUP_NAMESPACE_END
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpFuncMatrix.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpFuncMatrix.h Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,53 @@
+/** \file
+ \brief Definition of functions for complex valued operations.
+
+<pre>
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+</pre>
+*/
+#ifndef MUP_FUNC_MATRIX_H
+#define MUP_FUNC_MATRIX_H
+
+#include "mpICallback.h"
+
+
+MUP_NAMESPACE_START
+
+ //-----------------------------------------------------------------------
+ /** \brief Parser callback object for creating matrices consisting
+ entirely of ones.
+ \ingroup functions
+ */
+ class FunMatrixOnes : public ICallback
+ {
+ public:
+ FunMatrixOnes(IPackage *pPackage = NULL);
+ virtual ~FunMatrixOnes();
+ virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc);
+ virtual const char_type* GetDesc() const;
+ virtual IToken* Clone() const;
+ };
+} // namespace mu
+
+#endif
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpFuncNonCmplx.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpFuncNonCmplx.cpp Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,97 @@
+/** \file
+ \brief Implementation of basic functions used by muParserX.
+
+<pre>
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+ </pre>
+*/
+#include "mpFuncNonCmplx.h"
+
+//--- Standard includes ----------------------------------------------------
+#include <cmath>
+#include <cassert>
+#include <iostream>
+
+//--- muParserX framework --------------------------------------------------
+#include "mpValue.h"
+#include "mpError.h"
+
+#undef log
+#undef log2
+
+MUP_NAMESPACE_START
+
+ float_type log2(float_type v) { return log(v) * 1.0/log(2.0); }
+ float_type asinh(float_type v) { return log(v + sqrt(v * v + 1)); }
+ float_type acosh(float_type v) { return log(v + sqrt(v * v - 1)); }
+ float_type atanh(float_type v) { return (0.5 * log((1 + v) / (1 - v))); }
+
+#define MUP_UNARY_FUNC(CLASS, IDENT, FUNC, DESC) \
+ CLASS::CLASS() \
+ :ICallback(cmFUNC, _T(IDENT), 1) \
+ {} \
+ \
+ void CLASS::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int) \
+ { \
+ *ret = FUNC(a_pArg[0]->GetFloat()); \
+ } \
+ \
+ const char_type* CLASS::GetDesc() const \
+ { \
+ return _T(DESC); \
+ } \
+ \
+ IToken* CLASS::Clone() const \
+ { \
+ return new CLASS(*this); \
+ }
+
+ // trigonometric functions
+ MUP_UNARY_FUNC(FunTan, "sin", sin, "sine function")
+ MUP_UNARY_FUNC(FunCos, "cos", cos, "cosine function")
+ MUP_UNARY_FUNC(FunSin, "tan", tan, "tangens function")
+ // arcus functions
+ MUP_UNARY_FUNC(FunASin, "asin", asin, "arcus sine")
+ MUP_UNARY_FUNC(FunACos, "acos", acos, "arcus cosine")
+ MUP_UNARY_FUNC(FunATan, "atan", atan, "arcus tangens")
+ // hyperbolic functions
+ MUP_UNARY_FUNC(FunSinH, "sinh", sinh, "hyperbolic sine")
+ MUP_UNARY_FUNC(FunCosH, "cosh", cosh, "hyperbolic cosine")
+ MUP_UNARY_FUNC(FunTanH, "tanh", tanh, "hyperbolic tangens")
+ // hyperbolic arcus functions
+ MUP_UNARY_FUNC(FunASinH, "asinh", asinh, "hyperbolic arcus sine")
+ MUP_UNARY_FUNC(FunACosH, "acosh", acosh, "hyperbolic arcus cosine")
+ MUP_UNARY_FUNC(FunATanH, "atanh", atanh, "hyperbolic arcus tangens")
+ // logarithm functions
+ MUP_UNARY_FUNC(FunLog, "log", log10, "Logarithm base 10")
+ MUP_UNARY_FUNC(FunLog10, "log10", log10, "Logarithm base 10")
+ MUP_UNARY_FUNC(FunLog2, "log2", log2, "Logarithm base 2")
+ MUP_UNARY_FUNC(FunLn, "ln", log, "Natural logarithm")
+ // square root
+ MUP_UNARY_FUNC(FunSqrt, "sqrt", sqrt, "sqrt(x) - square root of x")
+ MUP_UNARY_FUNC(FunExp, "exp", exp, "exp(x) - e to the power of x")
+ MUP_UNARY_FUNC(FunAbs, "abs", fabs, "abs(x) - absolute value of x")
+#undef MUP_UNARY_FUNC
+
+MUP_NAMESPACE_END
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpFuncNonCmplx.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpFuncNonCmplx.h Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,79 @@
+/** \file
+ \brief Implementation of basic functions used by muParserX.
+
+<pre>
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+ </pre>
+*/
+#ifndef MUP_FUNC_NON_CMPLX_H
+#define MUP_FUNC_NON_CMPLX_H
+
+#include "mpICallback.h"
+
+/** \defgroup functions Function callback objects.
+
+ This group lists the objects representing parser functions.
+*/
+
+
+MUP_NAMESPACE_START
+
+#define MUP_UNARY_FUNC_DEF(CLASS) \
+ class CLASS : public ICallback \
+ { \
+ public: \
+ CLASS(); \
+ virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc); \
+ virtual const char_type* GetDesc() const; \
+ virtual IToken* Clone() const; \
+ };
+
+ MUP_UNARY_FUNC_DEF(FunTan)
+ MUP_UNARY_FUNC_DEF(FunCos)
+ MUP_UNARY_FUNC_DEF(FunSin)
+ // arcus functions
+ MUP_UNARY_FUNC_DEF(FunASin)
+ MUP_UNARY_FUNC_DEF(FunACos)
+ MUP_UNARY_FUNC_DEF(FunATan)
+ // hyperbolic functions
+ MUP_UNARY_FUNC_DEF(FunSinH)
+ MUP_UNARY_FUNC_DEF(FunCosH)
+ MUP_UNARY_FUNC_DEF(FunTanH)
+ // hyperbolic arcus functions
+ MUP_UNARY_FUNC_DEF(FunASinH)
+ MUP_UNARY_FUNC_DEF(FunACosH)
+ MUP_UNARY_FUNC_DEF(FunATanH)
+ // logarithm functions
+ MUP_UNARY_FUNC_DEF(FunLog)
+ MUP_UNARY_FUNC_DEF(FunLog10)
+ MUP_UNARY_FUNC_DEF(FunLog2)
+ MUP_UNARY_FUNC_DEF(FunLn)
+ // square root
+ MUP_UNARY_FUNC_DEF(FunSqrt)
+ MUP_UNARY_FUNC_DEF(FunExp)
+ MUP_UNARY_FUNC_DEF(FunAbs)
+#undef MUP_UNARY_FUNC_DEF
+} // namespace mu
+
+#endif
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpFuncStr.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpFuncStr.cpp Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,140 @@
+/*
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+*/
+#include "mpFuncStr.h"
+
+#include <cmath>
+#include <cassert>
+#include <cstdio>
+#include <cwchar>
+#include <algorithm>
+
+#include "mpValue.h"
+#include "mpError.h"
+
+
+MUP_NAMESPACE_START
+
+ //------------------------------------------------------------------------------
+ //
+ // Strlen function
+ //
+ //------------------------------------------------------------------------------
+
+ FunStrLen::FunStrLen()
+ :ICallback(cmFUNC, _T("strlen"), 1)
+ {}
+
+ //------------------------------------------------------------------------------
+ void FunStrLen::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int)
+ {
+ string_type str = a_pArg[0]->GetString();
+ *ret = (int)str.length();
+ }
+
+ //------------------------------------------------------------------------------
+ const char_type* FunStrLen::GetDesc() const
+ {
+ return _T("strlen(s) - Returns the length of the string s.");
+ }
+
+ //------------------------------------------------------------------------------
+ IToken* FunStrLen::Clone() const
+ {
+ return new FunStrLen(*this);
+ }
+
+ //------------------------------------------------------------------------------
+ //
+ // ToUpper function
+ //
+ //------------------------------------------------------------------------------
+
+ FunStrToUpper::FunStrToUpper()
+ :ICallback(cmFUNC, _T("toupper"), 1)
+ {}
+
+ //------------------------------------------------------------------------------
+ void FunStrToUpper::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int)
+ {
+ using namespace std;
+
+ string_type str = a_pArg[0]->GetString();
+ std::transform(str.begin(), str.end(), str.begin(), ::toupper);
+
+ *ret = str;
+ }
+
+ //------------------------------------------------------------------------------
+ const char_type* FunStrToUpper::GetDesc() const
+ {
+ return _T("toupper(s) - Converts the string s to uppercase characters.");
+ }
+
+ //------------------------------------------------------------------------------
+ IToken* FunStrToUpper::Clone() const
+ {
+ return new FunStrToUpper(*this);
+ }
+
+ //------------------------------------------------------------------------------
+ //
+ // String to double conversion
+ //
+ //------------------------------------------------------------------------------
+
+ FunStrToDbl::FunStrToDbl()
+ :ICallback(cmFUNC, _T("str2dbl"), 1)
+ {}
+
+ //------------------------------------------------------------------------------
+ void FunStrToDbl::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc)
+ {
+ assert(a_iArgc==1);
+ string_type in;
+ float_type out;
+
+ in = a_pArg[0]->GetString();
+
+#ifndef _UNICODE
+ sscanf(in.c_str(), "%lf", &out);
+#else
+ swscanf(in.c_str(), _T("%lf"), &out);
+#endif
+
+ *ret = out;
+ }
+
+ //------------------------------------------------------------------------------
+ const char_type* FunStrToDbl::GetDesc() const
+ {
+ return _T("str2dbl(s) - Converts the string stored in s into a floating foint value.");
+ }
+
+ //------------------------------------------------------------------------------
+ IToken* FunStrToDbl::Clone() const
+ {
+ return new FunStrToDbl(*this);
+ }
+} // namespace mu
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpFuncStr.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpFuncStr.h Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,73 @@
+/*
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2011 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+*/
+#ifndef MUP_FUNC_STR_H
+#define MUP_FUNC_STR_H
+
+#include "mpICallback.h"
+
+
+MUP_NAMESPACE_START
+
+ //------------------------------------------------------------------------------
+ /** \brief Callback object for determining the length of a string.
+ \ingroup functions
+ */
+ class FunStrLen : public ICallback
+ {
+ public:
+ FunStrLen();
+ virtual void Eval(ptr_val_type& ret, const ptr_val_type *a_pArg, int a_iArgc);
+ virtual const char_type* GetDesc() const;
+ virtual IToken* Clone() const;
+ };
+
+ //------------------------------------------------------------------------------
+ /** \brief Convert a string to upper case letters.
+ \ingroup functions
+ */
+ class FunStrToUpper : public ICallback
+ {
+ public:
+ FunStrToUpper();
+ virtual void Eval(ptr_val_type& ret, const ptr_val_type *a_pArg, int a_iArgc);
+ virtual const char_type* GetDesc() const;
+ virtual IToken* Clone() const;
+ };
+
+ //------------------------------------------------------------------------------
+ /** \brief Parse string to a floating point value.
+ \ingroup functions
+ */
+ class FunStrToDbl : public ICallback
+ {
+ public:
+ FunStrToDbl ();
+ virtual void Eval(ptr_val_type& ret, const ptr_val_type *a_pArg, int a_iArgc);
+ virtual const char_type* GetDesc() const;
+ virtual IToken* Clone() const;
+ }; // class FunStrToDbl
+} // namespace mu
+
+#endif
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpFwdDecl.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpFwdDecl.h Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,49 @@
+/*
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+*/
+#ifndef MUP_FWD_DECL_H
+#define MUP_FWD_DECL_H
+
+#include "mpDefines.h"
+
+
+MUP_NAMESPACE_START
+
+ class ParserXBase;
+
+ class ICallback;
+ class IToken;
+ class IValue;
+ class IValueReader;
+ class IPrecedence;
+ class IOprtIndex;
+ class Value;
+ class ValueCache;
+
+ template<typename T>
+ class TokenPtr;
+
+MUP_NAMESPACE_END
+
+#endif
\ No newline at end of file
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpICallback.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpICallback.cpp Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,138 @@
+/** \file
+ \brief Implementation of the interface for parser callback objects.
+
+<pre>
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+</pre>
+*/
+#include "mpICallback.h"
+#include <cassert>
+
+#include "mpParserBase.h"
+
+
+MUP_NAMESPACE_START
+
+ //------------------------------------------------------------------------------
+ ICallback::ICallback(ECmdCode a_iCode,
+ const char_type *a_szName,
+ int a_nArgc,
+ const IPackage *a_pPackage)
+ :IToken(a_iCode, a_szName)
+ ,m_pParent(NULL)
+ ,m_pPackage(a_pPackage)
+ ,m_nArgc(a_nArgc)
+ ,m_nArgsPresent(-1)
+ {}
+
+ //------------------------------------------------------------------------------
+ ICallback::~ICallback()
+ {}
+
+ //---------------------------------------------------------------------------
+ ICallback* ICallback::AsICallback()
+ {
+ return this;
+ }
+
+ //---------------------------------------------------------------------------
+ IValue* ICallback::AsIValue()
+ {
+ return NULL;
+ }
+
+ //------------------------------------------------------------------------------
+ bool ICallback::IsVolatile() const
+ {
+ return false;
+ }
+
+ //------------------------------------------------------------------------------
+ /** \brief Returns a pointer to the parser object owning this callback.
+ \pre [assert] m_pParent must be defined
+ */
+ ParserXBase* ICallback::GetParent()
+ {
+ assert(m_pParent);
+ return m_pParent;
+ }
+
+ //------------------------------------------------------------------------------
+ void ICallback::SetArgc(int argc)
+ {
+ m_nArgc = argc;
+ }
+
+ //------------------------------------------------------------------------------
+ /** \brief Returns the m´number of arguments required by this callback.
+ \return Number of arguments or -1 if the number of arguments is variable.
+ */
+ int ICallback::GetArgc() const
+ {
+ return m_nArgc;
+ }
+
+ //------------------------------------------------------------------------------
+ /** \brief Assign a parser object to the callback.
+ \param a_pParent The parser that belongs to this callback object.
+
+ The parent object can be used in order to access internals of the parser
+ from within a callback object. Thus enabling callbacks to delete
+ variables or functions if this is desired.
+ */
+ void ICallback::SetParent(parent_type *a_pParent)
+ {
+ assert(a_pParent);
+ m_pParent = a_pParent;
+ }
+
+ //------------------------------------------------------------------------------
+ string_type ICallback::AsciiDump() const
+ {
+ stringstream_type ss;
+
+ ss << g_sCmdCode[ GetCode() ];
+ ss << _T(" [addr=0x") << std::hex << this << std::dec;
+ ss << _T("; ident=\"") << GetIdent() << "\"";
+ ss << _T("; argc=") << GetArgc() << " (present: " << m_nArgsPresent << ")";
+ ss << _T("]");
+
+ return ss.str();
+ }
+
+ //------------------------------------------------------------------------------
+ void ICallback::SetNumArgsPresent(int argc)
+ {
+ m_nArgsPresent = argc;
+ }
+
+ //------------------------------------------------------------------------------
+ int ICallback::GetArgsPresent() const
+ {
+ if (m_nArgc!=-1)
+ return m_nArgc;
+ else
+ return m_nArgsPresent;
+ }
+} // namespace mu
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpICallback.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpICallback.h Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,82 @@
+/** \file
+ \brief Definition of the interface for parser callback objects.
+
+<pre>
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+</pre>
+*/
+#ifndef MU_IPARSER_CALLBACK_H
+#define MU_IPARSER_CALLBACK_H
+
+//--- muParserX framework --------------------------------------------
+#include "mpIToken.h"
+#include "mpIPackage.h"
+
+
+MUP_NAMESPACE_START
+
+ /** \brief Interface for callback objects.
+
+ All Parser functions and operators must implement this interface.
+ */
+ class ICallback : public IToken
+ {
+ public:
+ typedef ParserXBase parent_type;
+
+ ICallback(ECmdCode a_iCode,
+ const char_type *a_szName,
+ int a_nArgNum = 1,
+ const IPackage *a_pPackage = NULL);
+ virtual ~ICallback();
+
+ virtual ICallback* AsICallback();
+ virtual IValue* AsIValue();
+
+ virtual void Eval(ptr_val_type& ret, const ptr_val_type *arg, int argc) = 0;
+ virtual const char_type* GetDesc() const = 0;
+ virtual bool IsVolatile() const;
+ virtual string_type AsciiDump() const;
+
+ int GetArgc() const;
+ int GetArgsPresent() const;
+ void SetParent(parent_type *a_pParent);
+ void SetNumArgsPresent(int argc);
+
+ protected:
+ parent_type* GetParent();
+ void SetArgc(int argc);
+
+ private:
+
+ parent_type *m_pParent; ///< Pointer to the parser object using this callback
+ const IPackage *m_pPackage; ///< Pointer to thhe package this callback is belonging to (may be zero)
+ int m_nArgc; ///< Number of this function can take Arguments.
+ int m_nArgsPresent; ///< Number of arguments actually submitted
+ }; // class ICallback
+
+MUP_NAMESPACE_END
+
+#endif
+
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpIOprt.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpIOprt.cpp Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,209 @@
+/*
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+*/
+#include "mpIOprt.h"
+
+#include "mpError.h"
+
+
+MUP_NAMESPACE_START
+
+ //------------------------------------------------------------------------------
+ //
+ // Binary Operators
+ //
+ //------------------------------------------------------------------------------
+
+ IOprtBin::IOprtBin(const char_type *a_szIdent, int nPrec, EOprtAsct eAsc)
+ :ICallback(cmOPRT_BIN, a_szIdent, 2)
+ ,IPrecedence()
+ ,m_nPrec(nPrec)
+ ,m_eAsc(eAsc)
+ {}
+
+ //------------------------------------------------------------------------------
+ IOprtBin::~IOprtBin()
+ {}
+
+ //------------------------------------------------------------------------------
+ string_type IOprtBin::AsciiDump() const
+ {
+ stringstream_type ss;
+
+ ss << g_sCmdCode[ GetCode() ];
+ ss << _T(" [addr=0x") << std::hex << this << std::dec;
+ ss << _T("; ident=\"") << GetIdent() << _T("\"");
+ ss << _T("; prec=") << GetPri();
+ ss << _T("; argc=") << GetArgc();
+ ss << _T("]");
+
+ return ss.str();
+ }
+
+ //------------------------------------------------------------------------------
+ int IOprtBin::GetPri() const
+ {
+ return m_nPrec;
+ }
+
+ //------------------------------------------------------------------------------
+ EOprtAsct IOprtBin::GetAssociativity() const
+ {
+ return m_eAsc;
+ }
+
+ //------------------------------------------------------------------------------
+ /** \brief Verify the operator prototype.
+
+ Binary operators have the additional constraint that return type and the types
+ of both arguments must be the same. So adding to floats can not produce a string
+ and adding a number to a string is impossible.
+ */
+ void IOprtBin::CheckPrototype(const string_type &a_sProt)
+ {
+ if (a_sProt.length()!=4)
+ throw ParserError( ErrorContext(ecAPI_INVALID_PROTOTYPE, -1, GetIdent() ) );
+
+ //if (a_sProt[0]!=a_sProt[2] || a_sProt[0]!=a_sProt[3])
+ // throw ParserError( ErrorContext(ecAPI_INVALID_PROTOTYPE, -1, GetIdent() ) );
+ }
+
+ //---------------------------------------------------------------------------
+ IPrecedence* IOprtBin::AsIPrecedence()
+ {
+ return this;
+ }
+
+ //------------------------------------------------------------------------------
+ //
+ // Unary Postfix Operators
+ //
+ //------------------------------------------------------------------------------
+
+ IOprtPostfix::IOprtPostfix(const char_type *a_szIdent)
+ :ICallback(cmOPRT_POSTFIX, a_szIdent, 1)
+ {}
+
+ //------------------------------------------------------------------------------
+ IOprtPostfix::~IOprtPostfix()
+ {}
+
+ //------------------------------------------------------------------------------
+ string_type IOprtPostfix::AsciiDump() const
+ {
+ stringstream_type ss;
+
+ ss << g_sCmdCode[ GetCode() ];
+ ss << _T(" [addr=0x") << std::hex << this << std::dec;
+ ss << _T("; ident=\"") << GetIdent() << _T("\"");
+ ss << _T("; argc=") << GetArgc();
+ ss << _T("]");
+
+ return ss.str();
+ }
+
+ //------------------------------------------------------------------------------
+ //
+ // Unary Infix Operators
+ //
+ //------------------------------------------------------------------------------
+
+ IOprtInfix::IOprtInfix(const char_type *a_szIdent)
+ :ICallback(cmOPRT_INFIX, a_szIdent, 1)
+ {}
+
+ //------------------------------------------------------------------------------
+ IOprtInfix::~IOprtInfix()
+ {}
+
+ //------------------------------------------------------------------------------
+ string_type IOprtInfix::AsciiDump() const
+ {
+ stringstream_type ss;
+
+ ss << g_sCmdCode[ GetCode() ];
+ ss << _T(" [addr=0x") << std::hex << this << std::dec;
+ ss << _T("; ident=\"") << GetIdent() << _T("\"");
+ ss << _T("; argc=") << GetArgc();
+ ss << _T("]");
+
+ return ss.str();
+ }
+
+ //------------------------------------------------------------------------------
+ //
+ // Index operators
+ //
+ //------------------------------------------------------------------------------
+
+ IOprtIndex::IOprtIndex(int nArgc)
+ :IToken(cmIC, _T("[...]"))
+ ,m_nArgc(nArgc)
+ {}
+
+ //------------------------------------------------------------------------------
+ IOprtIndex::~IOprtIndex()
+ {}
+
+ //------------------------------------------------------------------------------
+ string_type IOprtIndex::AsciiDump() const
+ {
+ stringstream_type ss;
+
+ ss << g_sCmdCode[ GetCode() ];
+ ss << _T(" [addr=0x") << std::hex << this << std::dec;
+ ss << _T("; ident=\"") << GetIdent() << _T("\"");
+ ss << _T("; argc=") << GetArgc();
+ ss << _T("]");
+
+ return ss.str();
+ }
+
+ //-----------------------------------------------------------------------------------------------
+ IOprtIndex* IOprtIndex::AsIOprtIndex()
+ {
+ return this;
+ }
+
+ //-----------------------------------------------------------------------------------------------
+ int IOprtIndex::GetArgc() const
+ {
+ return m_nArgc;
+ }
+
+ //-----------------------------------------------------------------------------------------------
+ void IOprtIndex::SetNumArgsPresent(int argc)
+ {
+ m_nArgsPresent = argc;
+ }
+
+ //-----------------------------------------------------------------------------------------------
+ int IOprtIndex::GetArgsPresent() const
+ {
+ if (m_nArgc!=-1)
+ return m_nArgc;
+ else
+ return m_nArgsPresent;
+ }
+} // namespace mu
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpIOprt.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpIOprt.h Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,120 @@
+/** \file mpIOprt.h
+ \brief Definition of base classes needed for parser operator definitions.
+
+<pre>
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+</pre>
+*/
+#ifndef MUP_IPARSER_OPERATOR_H
+#define MUP_IPARSER_OPERATOR_H
+
+#include "mpICallback.h"
+#include "mpIPrecedence.h"
+
+
+MUP_NAMESPACE_START
+
+ //------------------------------------------------------------------------------
+ /** \brief Interface for binary operators.
+ \ingroup binop
+
+ All classes representing binary operator callbacks must be derived from
+ this base class.
+ */
+ class IOprtBin : public ICallback,
+ public IPrecedence
+ {
+ public:
+
+ IOprtBin(const char_type *a_szIdent, int nPrec, EOprtAsct eAsc);
+ virtual ~IOprtBin();
+ virtual string_type AsciiDump() const;
+
+ virtual int GetPri() const;
+ virtual EOprtAsct GetAssociativity() const;
+
+ //------------------------------------------
+ // IPrecedence implementation
+ //------------------------------------------
+
+ virtual IPrecedence* AsIPrecedence();
+
+ private:
+
+ void CheckPrototype(const string_type &a_szProt);
+ int m_nPrec;
+ EOprtAsct m_eAsc;
+ }; // class IOperator
+
+
+ //------------------------------------------------------------------------------
+ /** \brief Interface for unary postfix operators.
+ \ingroup postfix
+ */
+ class IOprtPostfix : public ICallback
+ {
+ public:
+ IOprtPostfix(const char_type *a_szIdent);
+ virtual ~IOprtPostfix();
+ virtual string_type AsciiDump() const;
+ }; // class IOperator
+
+
+ //------------------------------------------------------------------------------
+ /** \brief Interface for unary infix operators.
+ \ingroup infix
+ */
+ class IOprtInfix : public ICallback
+ {
+ public:
+ IOprtInfix(const char_type *a_szIdent);
+ virtual ~IOprtInfix();
+ virtual string_type AsciiDump() const;
+ }; // class IOperator
+
+ //------------------------------------------------------------------------------
+ /** \brief Interface for index operator tokens.
+ */
+ class IOprtIndex : public IToken
+ {
+ public:
+ IOprtIndex(int nArgc);
+ virtual ~IOprtIndex();
+ virtual string_type AsciiDump() const;
+ virtual void At(ptr_val_type& ret, const ptr_val_type *arg, int argc) = 0;
+ virtual IOprtIndex* AsIOprtIndex();
+
+ int GetArgc() const;
+ int GetArgsPresent() const;
+ void SetNumArgsPresent(int argc);
+
+ private:
+ int m_nArgc; ///< Number of arguments needed for the index operator (dimension of the index)
+ int m_nArgsPresent; ///< Number of arguments actually submitted
+
+ }; // class IOperator
+} // namespace mu
+
+#endif
+
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpIPackage.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpIPackage.cpp Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,17 @@
+#include "mpIPackage.h"
+
+#include "mpDefines.h"
+#include "mpParserBase.h"
+
+
+MUP_NAMESPACE_START
+
+//------------------------------------------------------------------------------
+IPackage::IPackage()
+{}
+
+//------------------------------------------------------------------------------
+IPackage::~IPackage()
+{}
+
+MUP_NAMESPACE_END
\ No newline at end of file
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpIPackage.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpIPackage.h Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,27 @@
+#ifndef MU_IPACKAGE_H
+#define MU_IPACKAGE_H
+
+#include <vector>
+#include "mpFwdDecl.h"
+#include "mpTypes.h"
+
+
+MUP_NAMESPACE_START
+
+class IPackage
+{
+public:
+
+ virtual void AddToParser(ParserXBase *pParser) = 0;
+ virtual string_type GetDesc() const = 0;
+ virtual string_type GetPrefix() const = 0;
+
+protected:
+
+ IPackage();
+ virtual ~IPackage();
+};
+
+MUP_NAMESPACE_END
+
+#endif
\ No newline at end of file
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpIPrecedence.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpIPrecedence.h Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,50 @@
+/** \file mpIPrecedence.h
+ \brief Definition of base classes needed for parser operator definitions.
+
+<pre>
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+</pre>
+*/
+#ifndef MUP_IPRECEDENCE_H
+#define MUP_IPRECEDENCE_H
+
+#include "mpTypes.h"
+
+
+MUP_NAMESPACE_START
+
+ //------------------------------------------------------------------------------
+ /** \brief Interface for binary and ternary operators
+ \ingroup binop
+ */
+ class IPrecedence
+ {
+ public:
+ virtual int GetPri() const = 0;
+ virtual EOprtAsct GetAssociativity() const = 0;
+ };
+} // namespace mu
+
+#endif
+
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpIToken.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpIToken.cpp Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,321 @@
+/*
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+*/
+#include "mpIToken.h"
+#include <iostream>
+#include <algorithm>
+#include <vector>
+#include <list>
+#include <cassert>
+
+#include "mpIPrecedence.h"
+
+MUP_NAMESPACE_START
+
+#ifdef MUP_LEAKAGE_REPORT
+ std::list<IToken*> IToken::s_Tokens;
+#endif
+
+#ifndef _UNICODE
+
+ //---------------------------------------------------------------------------
+ /** \brief Overloaded streaming operator for outputting the value type
+ into an std::ostream.
+ \param a_Stream The stream object
+ \param a_Val The value object to be streamed
+
+ This function is only present if _UNICODE is not defined.
+ */
+ std::ostream& operator<<(std::ostream &a_Stream, const IToken &tok)
+ {
+ return a_Stream << tok.ToString();
+ }
+
+#else
+
+ //---------------------------------------------------------------------------
+ /** \brief Overloaded streaming operator for outputting the value type
+ into an std::ostream.
+ \param a_Stream The stream object
+ \param a_Val The value object to be streamed
+
+ This function is only present if _UNICODE is defined.
+ */
+ std::wostream& operator<<(std::wostream &a_Stream, const IToken &tok)
+ {
+ return a_Stream << tok.ToString();
+ }
+#endif
+
+#ifdef MUP_LEAKAGE_REPORT
+
+ void IToken::LeakageReport()
+ {
+ using namespace std;
+
+ console() << "\n";
+ console() << "Memory leakage report:\n\n";
+ if (IToken::s_Tokens.size())
+ {
+ list<IToken*>::const_iterator item = IToken::s_Tokens.begin();
+ std::vector<int> stat(cmCOUNT, 0);
+ for (; item!=IToken::s_Tokens.end(); ++item)
+ {
+ console() << "Addr: 0x" << hex << *item << " Ident: \"" << (*item)->GetIdent() << "\"";
+ console() << "\tCode: " << g_sCmdCode[(*item)->GetCode()] << "\n";
+ stat[(*item)->GetCode()]++;
+ }
+ console() << "Leaked tokens: " << dec << (int)IToken::s_Tokens.size() << std::endl;
+
+ for (int i=0; i<cmCOUNT; ++i)
+ console() << g_sCmdCode[i] << ":" << stat[i] << "\n";
+
+ console() << endl;
+ }
+ else
+ {
+ console() << "No tokens leaked!\n";
+ }
+ }
+
+#endif
+
+ //------------------------------------------------------------------------------
+ IToken::IToken(ECmdCode a_iCode)
+ :m_eCode(a_iCode)
+ ,m_sIdent()
+ ,m_nPosExpr(-1)
+ ,m_nRefCount(0)
+ ,m_flags(0)
+ {
+#ifdef MUP_LEAKAGE_REPORT
+ IToken::s_Tokens.push_back(this);
+#endif
+ }
+
+ //------------------------------------------------------------------------------
+ IToken::IToken(ECmdCode a_iCode, string_type a_sIdent)
+ :m_eCode(a_iCode)
+ ,m_sIdent(a_sIdent)
+ ,m_nPosExpr(-1)
+ ,m_nRefCount(0)
+ ,m_flags(0)
+ {
+#ifdef MUP_LEAKAGE_REPORT
+ IToken::s_Tokens.push_back(this);
+#endif
+ }
+
+ /** \brief Destructor (trivial). */
+ IToken::~IToken()
+ {
+#ifdef MUP_LEAKAGE_REPORT
+ std::list<IToken*>::iterator it = std::find(IToken::s_Tokens.begin(), IToken::s_Tokens.end(), this);
+ IToken::s_Tokens.remove(this);
+#endif
+ }
+
+ //------------------------------------------------------------------------------
+ /** \brief Copy constructor.
+ \param ref The token to copy basic state information from.
+
+ The copy constructor must be implemented in order not to screw up
+ the reference count of the created object. CC's are used in the
+ Clone function and they would start with a reference count != 0
+ introducing memory leaks if the default CC where used.
+ */
+ IToken::IToken(const IToken &ref)
+ {
+ m_eCode = ref.m_eCode;
+ m_sIdent = ref.m_sIdent;
+ m_flags = ref.m_flags;
+ m_nPosExpr = ref.m_nPosExpr;
+
+ // The following items must be initialised
+ // (rather than just beeing copied)
+ m_nRefCount = 0;
+ }
+
+ //------------------------------------------------------------------------------
+ void IToken::ResetRef()
+ {
+ m_nRefCount = 0;
+ }
+
+ //------------------------------------------------------------------------------
+ void IToken::Release()
+ {
+ delete this;
+ }
+
+ //------------------------------------------------------------------------------
+ string_type IToken::ToString() const
+ {
+ return AsciiDump();
+ }
+
+ //------------------------------------------------------------------------------
+ int IToken::GetExprPos() const
+ {
+ return m_nPosExpr;
+ }
+
+ //------------------------------------------------------------------------------
+ void IToken::SetExprPos(int nPos)
+ {
+ m_nPosExpr = nPos;
+ }
+
+ //------------------------------------------------------------------------------
+ /** \brief return the token code.
+
+ \sa ECmdCode
+ */
+ ECmdCode IToken::GetCode() const
+ {
+ return m_eCode;
+ }
+
+ //------------------------------------------------------------------------------
+ /** \brief Return the token identifier string. */
+ const string_type& IToken::GetIdent() const
+ {
+ return m_sIdent;
+ }
+
+ //------------------------------------------------------------------------------
+ void IToken::SetIdent(const string_type &a_sIdent)
+ {
+ m_sIdent = a_sIdent;
+ }
+
+ //------------------------------------------------------------------------------
+ string_type IToken::AsciiDump() const
+ {
+ stringstream_type ss;
+ ss << g_sCmdCode[m_eCode];
+ return ss.str().c_str();
+ }
+
+ //------------------------------------------------------------------------------
+ void IToken::IncRef() const
+ {
+ ++m_nRefCount;
+ }
+
+ //------------------------------------------------------------------------------
+ long IToken::DecRef() const
+ {
+ return --m_nRefCount;
+ }
+
+ //------------------------------------------------------------------------------
+ long IToken::GetRef() const
+ {
+ return m_nRefCount;
+ }
+
+ //---------------------------------------------------------------------------
+ void IToken::AddFlags(int flags)
+ {
+ m_flags |= flags;
+ }
+
+ //---------------------------------------------------------------------------
+ bool IToken::IsFlagSet(int flags) const
+ {
+ return (m_flags & flags)==flags;
+ }
+
+ //---------------------------------------------------------------------------
+ ICallback* IToken::AsICallback()
+ {
+ return NULL;
+ }
+
+ //---------------------------------------------------------------------------
+ IValue* IToken::AsIValue()
+ {
+ return NULL;
+ }
+
+ //---------------------------------------------------------------------------
+ IPrecedence* IToken::AsIPrecedence()
+ {
+ return NULL;
+ }
+
+ //------------------------------------------------------------------------------
+ IOprtIndex* IToken::AsIOprtIndex()
+ {
+ return NULL;
+ }
+
+ //------------------------------------------------------------------------------
+ void IToken::Compile(const string_type &sArg)
+ {
+ }
+
+ //---------------------------------------------------------------------------
+ //
+ // Generic token implementation
+ //
+ //---------------------------------------------------------------------------
+
+ GenericToken::GenericToken(ECmdCode a_iCode, string_type a_sIdent)
+ :IToken(a_iCode, a_sIdent)
+ {}
+
+ //---------------------------------------------------------------------------
+ GenericToken::GenericToken(ECmdCode a_iCode)
+ :IToken(a_iCode, _T(""))
+ {}
+
+ //---------------------------------------------------------------------------
+ GenericToken::~GenericToken()
+ {}
+
+ //---------------------------------------------------------------------------
+ GenericToken::GenericToken(const GenericToken &a_Tok)
+ :IToken(a_Tok)
+ {}
+
+ //---------------------------------------------------------------------------
+ IToken* GenericToken::Clone() const
+ {
+ return new GenericToken(*this);
+ }
+
+ //------------------------------------------------------------------------------
+ string_type GenericToken::AsciiDump() const
+ {
+ stringstream_type ss;
+
+ ss << g_sCmdCode[ GetCode() ];
+ ss << _T(" [addr=0x") << std::hex << this << _T("]");
+
+ return ss.str();
+ }
+
+MUP_NAMESPACE_END
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpIToken.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpIToken.h Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,223 @@
+/*
+<pre>
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+</pre>
+*/
+#ifndef MUP_ITOKEN_H
+#define MUP_ITOKEN_H
+
+#include <list>
+#include "mpTypes.h"
+#include "mpFwdDecl.h"
+
+MUP_NAMESPACE_START
+
+ //------------------------------------------------------------------------------
+ /** \brief Generic token interface for expression tokens.
+ \author (C) 2010 Ingo Berg
+
+ Tokens can either be Functions, operators, values, variables or necessary
+ base tokens like brackets. ´The IToken baseclass implements reference
+ counting. Only TokenPtr<...> templates may be used as pointers to tokens.
+ */
+ class IToken
+ {
+ friend std::ostream& operator<<(std::ostream &a_Stream, const IToken &a_Val);
+ friend std::wostream& operator<<(std::wostream &a_Stream, const IToken &a_Val);
+
+ friend class TokenPtr<IToken>;
+ friend class TokenPtr<IValue>;
+ friend class TokenPtr<IOprtBin>;
+ friend class TokenPtr<IFunction>;
+ friend class TokenPtr<Value>;
+ friend class TokenPtr<Variable>;
+
+ public:
+
+ enum EFlags
+ {
+ flNONE = 0,
+ flVOLATILE = 1
+ };
+
+ virtual IToken* Clone() const = 0;
+ virtual string_type ToString() const;
+ virtual string_type AsciiDump() const;
+
+ virtual ICallback* AsICallback();
+ virtual IValue* AsIValue();
+ virtual IPrecedence* AsIPrecedence();
+ virtual IOprtIndex* AsIOprtIndex();
+
+ virtual void Compile(const string_type &sArg);
+
+ ECmdCode GetCode() const;
+ int GetExprPos() const;
+
+ const string_type& GetIdent() const;
+ long GetRef() const;
+ void SetIdent(const string_type &a_sIdent);
+ void SetExprPos(int nPos);
+
+ void AddFlags(int flags);
+ bool IsFlagSet(int flags) const;
+
+ protected:
+
+ explicit IToken(ECmdCode a_iCode);
+ virtual ~IToken();
+ IToken(ECmdCode a_iCode, string_type a_sIdent);
+ IToken(const IToken &ref);
+
+ void ResetRef();
+
+ private:
+
+ /** \brief Release the token.
+
+ This Function either deletes the token or releases it to
+ the value cache for reuse without deletion.
+ */
+ virtual void Release();
+
+ void IncRef() const;
+ long DecRef() const;
+
+ ECmdCode m_eCode;
+ string_type m_sIdent;
+ int m_nPosExpr; ///< Original position of the token in the expression
+ mutable long m_nRefCount; ///< Reference counter.
+ int m_flags;
+
+#ifdef MUP_LEAKAGE_REPORT
+ static std::list<IToken*> s_Tokens;
+
+ public:
+ static void LeakageReport();
+#endif
+ };
+
+
+ //---------------------------------------------------------------------------
+ /** \brief Default token implentation.
+ */
+ class GenericToken : public IToken
+ {
+ public:
+ GenericToken(ECmdCode a_iCode, string_type a_sIdent);
+ explicit GenericToken(ECmdCode a_iCode);
+ GenericToken(const GenericToken &a_Tok);
+ virtual ~GenericToken();
+ virtual IToken* Clone() const;
+ virtual string_type AsciiDump() const;
+ };
+
+ //------------------------------------------------------------------------------
+ template<typename T>
+ class TokenPtr
+ {
+ public:
+
+ typedef T* token_type;
+
+ //---------------------------------------------------------------------------
+ explicit TokenPtr(token_type p = 0)
+ :m_pTok(p)
+ {
+ if (m_pTok)
+ m_pTok->IncRef();
+ }
+
+ //---------------------------------------------------------------------------
+ TokenPtr(const TokenPtr &p)
+ :m_pTok(p.m_pTok)
+ {
+ if (m_pTok)
+ m_pTok->IncRef();
+ }
+
+ //---------------------------------------------------------------------------
+ ~TokenPtr()
+ {
+ if (m_pTok && m_pTok->DecRef()==0)
+ m_pTok->Release();
+ }
+
+ //---------------------------------------------------------------------------
+ token_type operator->() const
+ {
+ return static_cast<token_type>(m_pTok);
+ }
+
+ //---------------------------------------------------------------------------
+ T& operator*() const
+ {
+ assert(m_pTok);
+ return *(static_cast<token_type>(m_pTok));
+ }
+
+ //---------------------------------------------------------------------------
+ token_type Get() const
+ {
+ return static_cast<token_type>(m_pTok);
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Release the managed pointer and assign a new pointer. */
+ void Reset(token_type tok)
+ {
+ if (m_pTok && m_pTok->DecRef()==0)
+ {
+ m_pTok->Release();
+ //delete m_pTok;
+ }
+
+ tok->IncRef();
+ m_pTok = tok;
+ }
+
+ //---------------------------------------------------------------------------
+ TokenPtr& operator=(const TokenPtr &p)
+ {
+ if (p.m_pTok)
+ p.m_pTok->IncRef();
+
+ if (m_pTok && m_pTok->DecRef()==0)
+ {
+ m_pTok->Release();
+ //delete m_pTok;
+ }
+
+ m_pTok = p.m_pTok;
+
+ return *this;
+ }
+
+ private:
+ IToken *m_pTok;
+ };
+
+MUP_NAMESPACE_END
+
+#endif // include guard
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpIValReader.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpIValReader.cpp Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,62 @@
+/*
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+*/
+#include "mpIValReader.h"
+#include "mpTokenReader.h"
+
+#include <cassert>
+
+
+MUP_NAMESPACE_START
+
+//--------------------------------------------------------------------------------------------
+ IValueReader::IValueReader()
+ :m_pTokenReader(NULL)
+ {}
+
+ //--------------------------------------------------------------------------------------------
+ IValueReader::~IValueReader()
+ {}
+
+ //--------------------------------------------------------------------------------------------
+ IValueReader::IValueReader(const IValueReader &ref)
+ {
+ m_pTokenReader = ref.m_pTokenReader;
+ }
+
+ //--------------------------------------------------------------------------------------------
+ void IValueReader::SetParent(TokenReader *pTokenReader)
+ {
+ assert(pTokenReader);
+ m_pTokenReader = pTokenReader;
+ }
+
+ //--------------------------------------------------------------------------------------------
+ const IToken* IValueReader::TokenHistory(std::size_t pos) const
+ {
+ const TokenReader::token_buf_type &buf = m_pTokenReader->GetTokens();
+ std::size_t size = buf.size();
+ return (pos>=size) ? NULL : buf[size-1-pos].Get();
+ }
+}
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpIValReader.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpIValReader.h Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,91 @@
+/*
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+*/
+#ifndef MU_IPARSER_VALUE_READER_H
+#define MU_IPARSER_VALUE_READER_H
+
+#include "mpValue.h"
+#include "mpIToken.h"
+#include "mpTokenReader.h"
+
+/** \defgroup valreader Value reader classes
+
+ This group lists all classes that detect and parse values in an expression string.
+*/
+
+
+MUP_NAMESPACE_START
+
+ class TokenReader;
+
+ /** \brief Interface for custom value reader objects.
+ \ingroup valreader
+
+ Value readers are objects used for identifying values
+ in an expression.
+ */
+ class IValueReader
+ {
+ public:
+
+ IValueReader();
+ IValueReader(const IValueReader &ref);
+
+ virtual ~IValueReader();
+
+ /** \brief Check a certain position in an expression for the presence of a value.
+ \param a_iPos [in/out] Reference to an integer value representing the current
+ position of the parser in the expression.
+ \param a_Val If a value is found it is stored in a_Val
+ \return true if a value was found
+ */
+ virtual bool IsValue(const char_type *a_szExpr,
+ int &a_iPos,
+ Value &a_Val ) = 0;
+
+ /** \brief Clone this ValueReader object.
+ \return Pointer to the cloned value reader object.
+ */
+ virtual IValueReader* Clone(TokenReader *pParent) const = 0;
+
+ /** \brief Assign this value reader object to a token
+ reader object.
+
+ The token reader does the tokenization of the expression.
+ It uses this value reader to detect values.
+ */
+ virtual void SetParent(TokenReader *pTokenReader);
+
+ protected:
+
+ const IToken* TokenHistory(std::size_t pos) const;
+
+ private:
+
+ TokenReader *m_pTokenReader; ///< Pointer to the TokenReader class used for token recognition
+ }; // class IValueReader
+
+MUP_NAMESPACE_END
+
+#endif
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpIValue.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpIValue.cpp Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,435 @@
+/** \file
+ \brief Implementation of the virtual base class used for all parser values.
+
+<pre>
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+</pre>
+*/
+#include "mpIValue.h"
+
+//--- Standard includes ------------------------------------------------------
+#include <cassert>
+
+//--- muParserX framework -----------------------------------------------------
+#include "mpValue.h"
+#include "mpError.h"
+#include "mpValue.h"
+
+
+MUP_NAMESPACE_START
+
+#ifndef _UNICODE
+
+ //---------------------------------------------------------------------------
+ /** \brief Overloaded streaming operator for outputting the value type
+ into an std::ostream.
+ \param a_Stream The stream object
+ \param a_Val The value object to be streamed
+
+ This function is only present if _UNICODE is not defined.
+ */
+ std::ostream& operator<<(std::ostream &a_Stream, const IValue &a_Val)
+ {
+ return a_Stream << a_Val.ToString();
+ }
+
+#else
+
+ //---------------------------------------------------------------------------
+ /** \brief Overloaded streaming operator for outputting the value type
+ into an std::ostream.
+ \param a_Stream The stream object
+ \param a_Val The value object to be streamed
+
+ This function is only present if _UNICODE is defined.
+ */
+ std::wostream& operator<<(std::wostream &a_Stream, const IValue &a_Val)
+ {
+ return a_Stream << a_Val.ToString();
+ }
+#endif
+
+ //---------------------------------------------------------------------------------------------
+ Value operator*(const IValue& lhs, const IValue& rhs)
+ {
+ return Value(lhs) *= rhs;
+ }
+
+ //---------------------------------------------------------------------------
+ IValue::IValue(ECmdCode a_iCode)
+ :IToken(a_iCode)
+ {
+ assert(a_iCode==cmVAL || a_iCode==cmVAR);
+ }
+
+ //---------------------------------------------------------------------------
+ IValue::IValue(ECmdCode a_iCode, const string_type &a_sIdent)
+ :IToken(a_iCode, a_sIdent)
+ {
+ assert(a_iCode==cmVAL || a_iCode==cmVAR);
+ }
+
+ //---------------------------------------------------------------------------
+ IValue::~IValue()
+ {}
+
+ //---------------------------------------------------------------------------
+ ICallback* IValue::AsICallback()
+ {
+ return NULL;
+ }
+
+ //---------------------------------------------------------------------------
+ IValue* IValue::AsIValue()
+ {
+ return this;
+ }
+
+ //---------------------------------------------------------------------------
+ string_type IValue::ToString() const
+ {
+ stringstream_type ss;
+ switch (GetType())
+ {
+ case 'm':
+ {
+ const matrix_type &arr(GetArray());
+
+ if (arr.GetRows()>1)
+ ss << _T("{");
+
+ for (int i=0; i<arr.GetRows(); ++i)
+ {
+ if (arr.GetCols()>1)
+ ss << _T("{");
+
+ for (int j=0; j<arr.GetCols();++j)
+ {
+ ss << arr.At(i, j).ToString();
+ if (j!=arr.GetCols()-1)
+ ss << _T(", ");
+ }
+
+ if (arr.GetCols()>1)
+ ss << _T("}");
+
+ if (i!=arr.GetRows()-1)
+ ss << _T("; ");
+ }
+
+ if (arr.GetRows()>1)
+ ss << _T("} ");
+ }
+ break;
+
+ case 'c':
+ {
+ float_type re = GetFloat(),
+ im = GetImag();
+
+ // realteil nicht ausgeben, wenn es eine rein imaginäre Zahl ist
+ if (im==0 || re!=0 || (im==0 && re==0))
+ ss << re;
+
+ if (im!=0)
+ {
+ if (im>0 && re!=0)
+ ss << _T("+");
+
+ if (im!=1)
+ ss << im;
+
+ ss << _T("i");
+ }
+ }
+ break;
+
+ case 'i':
+ case 'f': ss << GetFloat(); break;
+ case 's': ss << _T("\"") << GetString() << _T("\""); break;
+ case 'b': ss << ((GetBool()==true) ? _T("true"):_T("false")); break;
+ case 'v': ss << _T("void"); break;
+ default: ss << _T("internal error: unknown value type."); break;
+ }
+
+ return ss.str();
+ }
+
+ //---------------------------------------------------------------------------
+ bool IValue::operator==(const IValue &a_Val) const
+ {
+ char_type type1 = GetType(),
+ type2 = a_Val.GetType();
+
+ if (type1==type2 || IsScalar() && a_Val.IsScalar())
+ {
+ switch(GetType())
+ {
+ case 'i':
+ case 'f': return GetFloat() == a_Val.GetFloat();
+ case 'c': return GetComplex() == a_Val.GetComplex();
+ case 's': return GetString() == a_Val.GetString();
+ case 'b': return GetBool() == a_Val.GetBool();
+ case 'v': return false;
+ case 'm': if (GetRows()!=a_Val.GetRows() || GetCols()!=a_Val.GetCols())
+ {
+ return false;
+ }
+ else
+ {
+ for (int i=0; i<GetRows(); ++i)
+ {
+ if (const_cast<IValue*>(this)->At(i)!=const_cast<IValue&>(a_Val).At(i))
+ return false;
+ }
+
+ return true;
+ }
+ default:
+ ErrorContext err;
+ err.Errc = ecINTERNAL_ERROR;
+ err.Pos = -1;
+ err.Type1 = GetType();
+ err.Type2 = a_Val.GetType();
+ throw ParserError(err);
+ } // switch this type
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ //---------------------------------------------------------------------------
+ bool IValue::operator!=(const IValue &a_Val) const
+ {
+ char_type type1 = GetType(),
+ type2 = a_Val.GetType();
+
+ if (type1==type2 || IsScalar() && a_Val.IsScalar())
+ {
+ switch(GetType())
+ {
+ case 's': return GetString() != a_Val.GetString();
+ case 'i':
+ case 'f': return GetFloat() != a_Val.GetFloat();
+ case 'c': return (GetFloat() != a_Val.GetFloat()) || (GetImag() != a_Val.GetImag());
+ case 'b': return GetBool() != a_Val.GetBool();
+ case 'v': return true;
+ case 'm': if (GetRows()!=a_Val.GetRows() || GetCols()!=a_Val.GetCols())
+ {
+ return true;
+ }
+ else
+ {
+ for (int i=0; i<GetRows(); ++i)
+ {
+ if (const_cast<IValue*>(this)->At(i)!=const_cast<IValue&>(a_Val).At(i))
+ return true;
+ }
+
+ return false;
+ }
+ default:
+ ErrorContext err;
+ err.Errc = ecINTERNAL_ERROR;
+ err.Pos = -1;
+ err.Type2 = GetType();
+ err.Type1 = a_Val.GetType();
+ throw ParserError(err);
+ } // switch this type
+ }
+ else
+ {
+ return true;
+ }
+ }
+
+ //---------------------------------------------------------------------------
+ bool IValue::operator<(const IValue &a_Val) const
+ {
+ char_type type1 = GetType(),
+ type2 = a_Val.GetType();
+
+ if (type1==type2 || IsScalar() && a_Val.IsScalar())
+ {
+ switch(GetType())
+ {
+ case 's': return GetString() < a_Val.GetString();
+ case 'i':
+ case 'f':
+ case 'c': return GetFloat() < a_Val.GetFloat();
+ case 'b': return GetBool() < a_Val.GetBool();
+
+ default:
+ ErrorContext err;
+ err.Errc = ecINTERNAL_ERROR;
+ err.Pos = -1;
+ err.Type1 = GetType();
+ err.Type2 = a_Val.GetType();
+ throw ParserError(err);
+ } // switch this type
+ }
+ else
+ {
+ ErrorContext err;
+ err.Errc = ecTYPE_CONFLICT_FUN;
+ err.Arg = (type1!='f' && type1!='i') ? 1 : 2;
+ err.Type1 = type2;
+ err.Type2 = type1;
+ throw ParserError(err);
+ }
+ }
+
+ //---------------------------------------------------------------------------
+ bool IValue::operator> (const IValue &a_Val) const
+ {
+ char_type type1 = GetType(),
+ type2 = a_Val.GetType();
+
+ if (type1==type2 || IsScalar() && a_Val.IsScalar())
+ {
+ switch(GetType())
+ {
+ case 's': return GetString() > a_Val.GetString();
+ case 'i':
+ case 'f':
+ case 'c': return GetFloat() > a_Val.GetFloat();
+ case 'b': return GetBool() > a_Val.GetBool();
+ default:
+ ErrorContext err;
+ err.Errc = ecINTERNAL_ERROR;
+ err.Pos = -1;
+ err.Type1 = GetType();
+ err.Type2 = a_Val.GetType();
+ throw ParserError(err);
+
+ } // switch this type
+ }
+ else
+ {
+ ErrorContext err;
+ err.Errc = ecTYPE_CONFLICT_FUN;
+ err.Arg = (type1!='f' && type1!='i') ? 1 : 2;
+ err.Type1 = type2;
+ err.Type2 = type1;
+ throw ParserError(err);
+ }
+ }
+
+ //---------------------------------------------------------------------------
+ bool IValue::operator>=(const IValue &a_Val) const
+ {
+ char_type type1 = GetType(),
+ type2 = a_Val.GetType();
+
+ if (type1==type2 || IsScalar() && a_Val.IsScalar())
+ {
+ switch(GetType())
+ {
+ case 's': return GetString() >= a_Val.GetString();
+ case 'i':
+ case 'f':
+ case 'c': return GetFloat() >= a_Val.GetFloat();
+ case 'b': return GetBool() >= a_Val.GetBool();
+ default:
+ ErrorContext err;
+ err.Errc = ecINTERNAL_ERROR;
+ err.Pos = -1;
+ err.Type1 = GetType();
+ err.Type2 = a_Val.GetType();
+ throw ParserError(err);
+
+ } // switch this type
+ }
+ else
+ {
+ ErrorContext err;
+ err.Errc = ecTYPE_CONFLICT_FUN;
+ err.Arg = (type1!='f' && type1!='i') ? 1 : 2;
+ err.Type1 = type2;
+ err.Type2 = type1;
+ throw ParserError(err);
+ }
+ }
+
+ //---------------------------------------------------------------------------
+ bool IValue::operator<=(const IValue &a_Val) const
+ {
+ char_type type1 = GetType(),
+ type2 = a_Val.GetType();
+
+ if (type1==type2 || IsScalar() && a_Val.IsScalar())
+ {
+ switch(GetType())
+ {
+ case 's': return GetString() <= a_Val.GetString();
+ case 'i':
+ case 'f':
+ case 'c': return GetFloat() <= a_Val.GetFloat();
+ case 'b': return GetBool() <= a_Val.GetBool();
+ default:
+ ErrorContext err;
+ err.Errc = ecINTERNAL_ERROR;
+ err.Pos = -1;
+ err.Type1 = GetType();
+ err.Type2 = a_Val.GetType();
+ throw ParserError(err);
+
+ } // switch this type
+ }
+ else
+ {
+ ErrorContext err;
+ err.Errc = ecTYPE_CONFLICT_FUN;
+ err.Arg = (type1!='f' && type1!='i') ? 1 : 2;
+ err.Type1 = type2;
+ err.Type2 = type1;
+ throw ParserError(err);
+ }
+ }
+
+ //---------------------------------------------------------------------------
+ IValue& IValue::operator=(const IValue &ref)
+ {
+ if (this==&ref)
+ return *this;
+
+ switch(ref.GetType())
+ {
+ case 'i':
+ case 'f':
+ case 'c': return *this = cmplx_type(ref.GetFloat(), ref.GetImag());
+ case 's': return *this = ref.GetString();
+ case 'm': return *this = ref.GetArray();
+ case 'b': return *this = ref.GetBool();
+ case 'v':
+ throw ParserError(_T("Assignment from void type is not possible"));
+
+ default:
+ throw ParserError(_T("Internal error: unexpected data type identifier in IValue& operator=(const IValue &ref)"));
+ }
+ }
+
+MUP_NAMESPACE_END
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpIValue.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpIValue.h Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,189 @@
+/** \file
+ \brief Definition of the virtual base class used for all parser values.
+
+<pre>
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+</pre>
+*/
+#ifndef MUP_IVALUE_H
+#define MUP_IVALUE_H
+
+#include "mpIToken.h"
+#include "mpFwdDecl.h"
+
+MUP_NAMESPACE_START
+
+ //------------------------------------------------------------------------------
+ /** \brief Interface to be implemented by all classes representing values.
+
+ IValue is the common base class of both the Value and Variable classes.
+ */
+ class IValue : public IToken
+ {
+ friend std::ostream& operator<<(std::ostream &a_Stream, const IValue &a_Val);
+ friend std::wostream& operator<<(std::wostream &a_Stream, const IValue &a_Val);
+
+ public:
+
+ explicit IValue(ECmdCode a_iCode);
+ IValue(ECmdCode a_iCode, const string_type &a_sIdent);
+
+ bool operator==(const IValue &a_Val) const;
+ bool operator!=(const IValue &a_Val) const;
+ bool operator< (const IValue &a_Val) const;
+ bool operator> (const IValue &a_Val) const;
+ bool operator<=(const IValue &a_Val) const;
+ bool operator>=(const IValue &a_Val) const;
+
+ virtual ICallback* AsICallback();
+ virtual IValue* AsIValue();
+ virtual Value* AsValue() = 0;
+
+ virtual IValue& operator=(int_type val) = 0;
+ virtual IValue& operator=(float_type val) = 0;
+ virtual IValue& operator=(string_type val) = 0;
+ virtual IValue& operator=(bool_type val) = 0;
+ virtual IValue& operator=(const cmplx_type &val) = 0;
+ virtual IValue& operator=(const matrix_type &val) = 0;
+ IValue& operator=(const IValue &ref);
+
+ virtual IValue& operator+=(const IValue &ref) = 0;
+ virtual IValue& operator-=(const IValue &ref) = 0;
+ virtual IValue& operator*=(const IValue &ref) = 0;
+
+ virtual IValue& At(int nRow, int nCol = 0) = 0;
+ virtual IValue& At(const IValue &nRows, const IValue &nCols) = 0;
+
+ virtual int_type GetInteger() const = 0;
+ virtual float_type GetFloat() const = 0;
+ virtual float_type GetImag() const = 0;
+ virtual bool GetBool() const = 0;
+ virtual const cmplx_type& GetComplex() const = 0;
+ virtual const string_type& GetString() const = 0;
+ virtual const matrix_type& GetArray() const = 0;
+ virtual char_type GetType() const = 0;
+ virtual int GetRows() const = 0;
+ virtual int GetCols() const = 0;
+
+ virtual bool IsVolatile() const = 0;
+ virtual string_type ToString() const;
+
+ //---------------------------------------------------------------------------
+ /** \brief Returns the dimension of the value represented by a value object.
+
+ The value represents the dimension of the object. Possible value are:
+ <ul>
+ <li>0 - scalar</li>
+ <li>1 - vector</li>
+ <li>2 - matrix</li>
+ </ul>
+ */
+ inline int GetDim() const
+ {
+ return (IsMatrix()) ? GetArray().GetDim() : 0;
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Returns true if the type is either floating point or interger.
+ \throw nothrow
+ */
+ inline bool IsNonComplexScalar() const
+ {
+ char_type t = GetType();
+ return t=='f' || t=='i';
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Returns true if the type is not a vector and not a string.
+ \throw nothrow
+ */
+ inline bool IsScalar() const
+ {
+ char_type t = GetType();
+ return t=='f' || t=='i' || t=='c';
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Returns true if this value is a noncomplex integer.
+ \throw nothrow
+ */
+ inline bool IsInteger() const
+ {
+ // checking the type is is insufficient. The integer could be disguised
+ // as a float or a complex value
+ return IsScalar() && GetImag()==0 && GetFloat()==(int_type)GetFloat();
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Returns true if this value is an array.
+ \throw nothrow
+ */
+ inline bool IsMatrix() const
+ {
+ return GetType() == 'm';
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Returns true if this value is a complex value.
+ \throw nothrow
+ */
+ inline bool IsComplex() const
+ {
+ return GetType() == 'c' && GetImag()!=0;
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Returns true if this value is a string value.
+ \throw nothrow
+ */
+ inline bool IsString() const
+ {
+ return GetType() == 's';
+ }
+
+ protected:
+ virtual ~IValue();
+ }; // class IValue
+
+ //---------------------------------------------------------------------------------------------
+ Value operator*(const IValue& lhs, const IValue& rhs);
+
+/*
+ //---------------------------------------------------------------------------------------------
+ IValue operator+(const IValue& lhs, const IValue& rhs)
+ {
+ return Value(lhs) += rhs;
+ }
+
+ //---------------------------------------------------------------------------------------------
+ IValue operator-(const IValue& lhs, const IValue& rhs)
+ {
+ return Value(lhs) -= rhs;
+ }
+*/
+} // namespace mu
+
+#endif
+
+
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpIfThenElse.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpIfThenElse.cpp Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,65 @@
+#include "mpIfThenElse.h"
+
+MUP_NAMESPACE_START
+
+ //---------------------------------------------------------------------------
+ //
+ // If part of if-then-else clauses
+ //
+ //---------------------------------------------------------------------------
+
+ TokenIfThenElse::TokenIfThenElse(ECmdCode eCode)
+ :IToken(eCode, g_sCmdCode[ eCode ])
+ ,IPrecedence()
+ ,m_nOffset()
+ {}
+
+ //---------------------------------------------------------------------------
+ IToken* TokenIfThenElse::Clone() const
+ {
+ return new TokenIfThenElse(*this);
+ }
+
+ //---------------------------------------------------------------------------
+ void TokenIfThenElse::SetOffset(int nOffset)
+ {
+ m_nOffset = nOffset;
+ }
+
+ //---------------------------------------------------------------------------
+ int TokenIfThenElse::GetOffset() const
+ {
+ return m_nOffset;
+ }
+
+ //---------------------------------------------------------------------------
+ string_type TokenIfThenElse::AsciiDump() const
+ {
+ stringstream_type ss;
+
+ ss << GetIdent();
+ ss << _T(" [addr=0x") << std::hex << this << std::dec;
+ ss << _T("; offset=") << m_nOffset;
+ ss << _T("]");
+ return ss.str();
+ }
+
+ //---------------------------------------------------------------------------
+ int TokenIfThenElse::GetPri() const
+ {
+ return (int)prIF_THEN_ELSE;
+ }
+
+ //---------------------------------------------------------------------------
+ EOprtAsct TokenIfThenElse::GetAssociativity() const
+ {
+ return oaNONE;
+ }
+
+ //---------------------------------------------------------------------------
+ IPrecedence* TokenIfThenElse::AsIPrecedence()
+ {
+ return this;
+ }
+
+MUP_NAMESPACE_END
\ No newline at end of file
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpIfThenElse.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpIfThenElse.h Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,70 @@
+/** \file
+ \brief Definition of basic types used by muParserX
+
+<pre>
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+ </pre>
+*/
+#ifndef MUP_IF_THEN_ELSE_H
+#define MUP_IF_THEN_ELSE_H
+
+#include "mpIToken.h"
+#include "mpIPrecedence.h"
+
+
+MUP_NAMESPACE_START
+
+ //---------------------------------------------------------------------------
+ /** \brief A class for encapsulation if-then-else tokens. */
+ class TokenIfThenElse : public IToken,
+ public IPrecedence
+ {
+ public:
+
+ TokenIfThenElse(ECmdCode eCmd);
+ void SetOffset(int nOffset);
+ int GetOffset() const;
+
+ //---------------------------------------------
+ // IToken interface
+ //---------------------------------------------
+
+ virtual IToken* Clone() const;
+ virtual string_type AsciiDump() const;
+ virtual IPrecedence* AsIPrecedence();
+
+ //---------------------------------------------
+ // IPrecedence interface
+ //---------------------------------------------
+
+ virtual int GetPri() const;
+ virtual EOprtAsct GetAssociativity() const;
+
+ private:
+ int m_nOffset;
+ };
+
+MUP_NAMESPACE_END
+
+#endif
\ No newline at end of file
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpMatrix.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpMatrix.h Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,417 @@
+#ifndef MU_MATRIX_H
+#define MU_MATRIX_H
+
+#include <vector>
+#include <cassert>
+#include <iostream>
+#include <stdexcept>
+#include <sstream>
+#include "mpMatrixError.h"
+
+
+MUP_NAMESPACE_START
+
+ //-----------------------------------------------------------------------------------------------
+ template<class T>
+ class Matrix
+ {
+ template<class T2>
+ friend Matrix operator+(const Matrix& lhs, const Matrix& rhs);
+
+ template<class T2>
+ friend Matrix operator-(const Matrix& lhs, const Matrix& rhs);
+
+ public:
+
+ //---------------------------------------------------------------------------------------------
+ enum EMatrixStorageScheme
+ {
+ mssROWS_FIRST,
+ mssCOLS_FIRST
+ };
+
+ //---------------------------------------------------------------------------------------------
+ Matrix()
+ :m_nRows(1)
+ ,m_nCols(1)
+ ,m_eStorageScheme(mssROWS_FIRST)
+ ,m_vData(1)
+ {}
+
+ //---------------------------------------------------------------------------------------------
+ Matrix(int nRows, const T &value = T())
+ :m_nRows(nRows)
+ ,m_nCols(1)
+ ,m_eStorageScheme(mssROWS_FIRST)
+ ,m_vData(m_nRows, value)
+ {}
+
+ //---------------------------------------------------------------------------------------------
+ /* \brief Constructs a Matrix object representing a scalar value
+ */
+ Matrix(const T &v)
+ :m_nRows(1)
+ ,m_nCols(1)
+ ,m_eStorageScheme(mssROWS_FIRST)
+ ,m_vData(1, v)
+ {}
+
+ //---------------------------------------------------------------------------------------------
+ /* \brief Constructs a Matrix object representing a vector
+ */
+ Matrix(const std::vector<T> &v)
+ :m_nRows(v.size())
+ ,m_nCols(1)
+ ,m_eStorageScheme(mssROWS_FIRST)
+ ,m_vData(v)
+ {}
+
+ //---------------------------------------------------------------------------------------------
+ /* Constructs a Matrix object representing a vector
+ */
+ template<size_t TSize>
+ Matrix(T (&v)[TSize])
+ :m_nRows(TSize)
+ ,m_nCols(1)
+ ,m_eStorageScheme(mssROWS_FIRST)
+ ,m_vData(v, v + TSize)
+ {}
+
+ //---------------------------------------------------------------------------------------------
+ template<size_t TRows, size_t TCols>
+ Matrix(T (&v)[TRows][TCols])
+ :m_nRows(TRows)
+ ,m_nCols(TCols)
+ ,m_eStorageScheme(mssROWS_FIRST)
+ ,m_vData(TRows*TCols, 0)
+ {
+ for (int m=0; m<TRows; ++m)
+ {
+ for (int n=0; n<TCols; ++n)
+ {
+ At(m,n) = v[m][n];
+ }
+ }
+ }
+
+ //---------------------------------------------------------------------------------------------
+ Matrix(int nRows, int nCols, const T &value = T())
+ :m_nRows(nRows)
+ ,m_nCols(nCols)
+ ,m_eStorageScheme(mssROWS_FIRST)
+ ,m_vData(m_nRows*m_nCols, value)
+ {}
+
+ //---------------------------------------------------------------------------------------------
+ Matrix(const Matrix &ref)
+ {
+ Assign(ref);
+ }
+
+ //---------------------------------------------------------------------------------------------
+ Matrix& operator=(const Matrix &ref)
+ {
+ if (this!=&ref)
+ Assign(ref);
+
+ return *this;
+ }
+
+ //---------------------------------------------------------------------------------------------
+ Matrix& operator=(const T &v)
+ {
+ m_nCols = 1;
+ m_nRows = 1;
+ m_eStorageScheme = mssROWS_FIRST;
+ m_vData.assign(1, v);
+ return *this;
+ }
+
+ //---------------------------------------------------------------------------------------------
+ Matrix& operator+=(const Matrix &lhs)
+ {
+ if (m_nRows!=lhs.m_nRows || m_nCols!=lhs.m_nCols)
+ throw MatrixError("Matrix dimension mismatch");
+
+ for (int i=0; i<m_nRows; ++i)
+ {
+ for (int j=0; j<m_nCols; ++j)
+ {
+ At(i,j) += lhs.At(i,j);
+ }
+ }
+
+ return *this;
+ }
+
+ //---------------------------------------------------------------------------------------------
+ Matrix& operator-=(const Matrix &lhs)
+ {
+ if (m_nRows!=lhs.m_nRows || m_nCols!=lhs.m_nCols)
+ throw MatrixError("Matrix dimension mismatch");
+
+ for (int i=0; i<m_nRows; ++i)
+ {
+ for (int j=0; j<m_nCols; ++j)
+ {
+ At(i,j) -= lhs.At(i,j);
+ }
+ }
+
+ return *this;
+ }
+
+ //---------------------------------------------------------------------------------------------
+ Matrix& operator*=(const T &rhs)
+ {
+ // Matrix x Matrix multiplication
+ for (int m=0; m<m_nRows; ++m)
+ {
+ for (int n=0; n<m_nCols; ++n)
+ {
+ At(m, n) *= rhs;
+ }
+ }
+
+ return *this;
+ }
+
+ //---------------------------------------------------------------------------------------------
+ Matrix& operator*=(const Matrix &rhs)
+ {
+ // Matrix x Matrix multiplication
+ if (rhs.GetRows()==0)
+ {
+ T v = rhs.At(0,0);
+ for (int m=0; m<m_nRows; ++m)
+ {
+ for (int n=0; n<m_nCols; ++n)
+ {
+ At(m, n) *= v;
+ }
+ }
+ }
+ else if (GetRows()==0)
+ {
+ T v = At(0,0);
+ Assign(rhs);
+ for (int m=0; m<m_nRows; ++m)
+ {
+ for (int n=0; n<m_nCols; ++n)
+ {
+ At(m, n) *= v;
+ }
+ }
+ }
+ else if (m_nCols==rhs.m_nRows)
+ {
+ Matrix<T> out(m_nRows, rhs.m_nCols);
+
+ // For each cell in the output matrix
+ for (int m=0; m<m_nRows; ++m)
+ {
+ for (int n=0; n<rhs.m_nCols; ++n)
+ {
+ T buf = 0;
+ for (int i=0; i<m_nCols; ++i)
+ {
+ buf += At(m, i) * rhs.At(i, n);
+ }
+ out.At(m,n) = buf;
+ } // for all rows
+ } // for all columns
+
+ Assign(out);
+ }
+ else
+ throw MatrixError("Matrix dimensions don't allow multiplication");
+
+ return *this;
+ }
+
+ //---------------------------------------------------------------------------------------------
+ void AsciiDump(const char *szTitle) const
+ {
+ using namespace std;
+
+ cout << szTitle << _T("\n");
+ cout << _T("------------------\n");
+ cout << _T("Cols: ") << GetCols() << _T("\n");
+ cout << _T("Rows: ") << GetRows() << _T("\n");
+ cout << _T("Dim: ") << GetDim() << _T("\n");
+
+ for (int i=0; i<m_nRows; ++i)
+ {
+ for (int j=0; j<m_nCols; ++j)
+ {
+ cout << At(i, j) << _T(" ");
+ }
+ cout << _T("\n");
+ }
+
+ cout << _T("\n\n");
+ }
+
+ //---------------------------------------------------------------------------------------------
+ std::string ToString() const
+ {
+ std::stringstream ss;
+ for (int i=0; i<m_nRows; ++i)
+ {
+ for (int j=0; j<m_nCols; ++j)
+ {
+ ss << At(i, j) << " ";
+ }
+ ss << "\n";
+ }
+
+ return ss.str();
+ }
+
+ //---------------------------------------------------------------------------------------------
+ ~Matrix()
+ {
+ m_vData.clear();
+ }
+
+ //---------------------------------------------------------------------------------------------
+ int GetRows() const
+ {
+ return m_nRows;
+ }
+
+ //---------------------------------------------------------------------------------------------
+ int GetCols() const
+ {
+ return m_nCols;
+ }
+
+ //---------------------------------------------------------------------------------------------
+ int GetDim() const
+ {
+ if (m_nCols==1)
+ {
+ return (m_nRows==1) ? 0 : 1;
+ }
+ else
+ return 2;
+ }
+
+ //---------------------------------------------------------------------------------------------
+ T& At(int nRow, int nCol = 0)
+ {
+ int i;
+ if (m_eStorageScheme==mssROWS_FIRST)
+ {
+ i = nRow * m_nCols + nCol;
+ }
+ else
+ {
+ i = nCol * m_nRows + nRow;
+ }
+
+ assert(i<(int)m_vData.size());
+ return m_vData[i];
+ }
+
+ //---------------------------------------------------------------------------------------------
+ const T& At(int nRow, int nCol = 0) const
+ {
+ int i;
+ if (m_eStorageScheme==mssROWS_FIRST)
+ {
+ i = nRow * m_nCols + nCol;
+ }
+ else
+ {
+ i = nCol * m_nRows + nRow;
+ }
+
+ assert(i<(int)m_vData.size());
+ return m_vData[i];
+ }
+
+ //---------------------------------------------------------------------------------------------
+ const T* GetData() const
+ {
+ assert(m_vData.size());
+ return &m_vData[0];
+ }
+
+ //---------------------------------------------------------------------------------------------
+ void SetStorageScheme(EMatrixStorageScheme eScheme)
+ {
+ m_eStorageScheme = eScheme;
+ }
+
+ //---------------------------------------------------------------------------------------------
+ EMatrixStorageScheme GetStorageScheme() const
+ {
+ return m_eStorageScheme;
+ }
+
+ //---------------------------------------------------------------------------------------------
+ Matrix<T>& Transpose()
+ {
+ if (GetDim()==0)
+ return *this;
+
+ m_eStorageScheme = (m_eStorageScheme==mssROWS_FIRST) ? mssCOLS_FIRST : mssROWS_FIRST;
+ m_nRows ^= m_nCols ^= m_nRows ^= m_nCols;
+
+ return *this;
+ }
+
+ //---------------------------------------------------------------------------------------------
+ void Fill(const T &v)
+ {
+ m_vData.assign(m_vData.size(), v);
+ }
+
+ private:
+ int m_nCols;
+ int m_nRows;
+ std::vector<T> m_vData;
+ EMatrixStorageScheme m_eStorageScheme;
+
+ //---------------------------------------------------------------------------------------------
+ void Assign(const Matrix &ref)
+ {
+ m_nCols = ref.m_nCols;
+ m_nRows = ref.m_nRows;
+ m_eStorageScheme = ref.m_eStorageScheme;
+ m_vData = ref.m_vData;
+ }
+ };
+
+ //---------------------------------------------------------------------------------------------
+ template<class T>
+ Matrix<T> operator*(const Matrix<T>& lhs, const T& rhs)
+ {
+ return Matrix<T>(lhs) *= rhs;
+ }
+
+ //---------------------------------------------------------------------------------------------
+ template<class T>
+ Matrix<T> operator*(const Matrix<T>& lhs, const Matrix<T>& rhs)
+ {
+ return Matrix<T>(lhs) *= rhs;
+ }
+
+ //---------------------------------------------------------------------------------------------
+ template<class T>
+ Matrix<T> operator+(const Matrix<T>& lhs, const Matrix<T>& rhs)
+ {
+ return Matrix<T>(lhs) += rhs;
+ }
+
+ //---------------------------------------------------------------------------------------------
+ template<class T>
+ Matrix<T> operator-(const Matrix<T>& lhs, const Matrix<T>& rhs)
+ {
+ return Matrix<T>(lhs) -= rhs;
+ }
+
+MUP_NAMESPACE_END
+
+#endif
\ No newline at end of file
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpMatrixError.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpMatrixError.h Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,19 @@
+#ifndef MU_MATRIX_ERROR_H
+#define MU_MATRIX_ERROR_H
+
+#include <stdexcept>
+#include <string>
+
+MUP_NAMESPACE_START
+
+ class MatrixError : public std::runtime_error
+ {
+ public:
+ explicit MatrixError(const std::string &sMsg)
+ :std::runtime_error(sMsg)
+ {}
+ };
+
+MUP_NAMESPACE_END
+
+#endif
\ No newline at end of file
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpOprtBinAssign.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpOprtBinAssign.cpp Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,243 @@
+/** \file
+ \brief This file contains the implementation of binary assignment
+ operators used in muParser.
+
+<pre>
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+</pre>
+*/
+#include "mpOprtBinAssign.h"
+
+
+MUP_NAMESPACE_START
+
+ //---------------------------------------------------------------------
+ //
+ // class OprtAssign
+ //
+ //---------------------------------------------------------------------
+
+ OprtAssign::OprtAssign()
+ :IOprtBin(_T("="), (int)prASSIGN, oaLEFT)
+ {}
+
+ //---------------------------------------------------------------------
+ const char_type* OprtAssign::GetDesc() const
+ {
+ return _T("'=' assignement operator");
+ }
+
+ //---------------------------------------------------------------------
+ IToken* OprtAssign::Clone() const
+ {
+ return new OprtAssign(*this);
+ }
+
+ //---------------------------------------------------------------------
+ void OprtAssign::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int)
+ {
+ Variable *pVar = dynamic_cast<Variable*>(a_pArg[0].Get());
+
+ // assigment to non variable type
+ if (!pVar)
+ {
+ ErrorContext err;
+ err.Arg = 1;
+ err.Ident = _T("=");
+ err.Errc = ecASSIGNEMENT_TO_VALUE;
+ throw ParserError(err);
+ }
+
+ *pVar = *a_pArg[1]; //pVar->SetFloat(a_pArg[1]->GetFloat());
+ *ret = *pVar;
+ }
+
+ //---------------------------------------------------------------------
+ //
+ // class OprtAssignAdd
+ //
+ //---------------------------------------------------------------------
+
+ OprtAssignAdd::OprtAssignAdd()
+ :IOprtBin(_T("+="), (int)prASSIGN, oaLEFT)
+ {}
+
+ //---------------------------------------------------------------------
+ void OprtAssignAdd::Eval(ptr_val_type& ret, const ptr_val_type *a_pArg, int)
+ {
+ Variable *pVar = dynamic_cast<Variable*>(a_pArg[0].Get());
+
+ // assigment to non variable type
+ if (!pVar)
+ {
+ ErrorContext err;
+ err.Arg = 1;
+ err.Ident = _T("+=");
+ err.Errc = ecASSIGNEMENT_TO_VALUE;
+ throw ParserError(err);
+ }
+
+ *pVar = cmplx_type(a_pArg[0]->GetFloat() + a_pArg[1]->GetFloat(),
+ a_pArg[0]->GetImag() + a_pArg[1]->GetImag());
+ *ret = *pVar;
+ }
+
+ //---------------------------------------------------------------------
+ const char_type* OprtAssignAdd::GetDesc() const
+ {
+ return _T("assignement operator");
+ }
+
+ //---------------------------------------------------------------------
+ IToken* OprtAssignAdd::Clone() const
+ {
+ return new OprtAssignAdd(*this);
+ }
+
+ //---------------------------------------------------------------------
+ //
+ // class OprtAssignAdd
+ //
+ //---------------------------------------------------------------------
+
+ OprtAssignSub::OprtAssignSub()
+ :IOprtBin(_T("-="), (int)prASSIGN, oaLEFT)
+ {}
+
+ //---------------------------------------------------------------------
+ void OprtAssignSub::Eval(ptr_val_type& ret, const ptr_val_type *a_pArg, int)
+ {
+ Variable *pVar = dynamic_cast<Variable*>(a_pArg[0].Get());
+ if (!pVar)
+ {
+ ErrorContext err;
+ err.Arg = 1;
+ err.Ident = _T("-=");
+ err.Errc = ecASSIGNEMENT_TO_VALUE;
+ throw ParserError(err);
+ }
+
+ *pVar = cmplx_type(a_pArg[0]->GetFloat() - a_pArg[1]->GetFloat(),
+ a_pArg[0]->GetImag() - a_pArg[1]->GetImag());
+ *ret = *pVar;
+ }
+
+ //---------------------------------------------------------------------
+ const char_type* OprtAssignSub::GetDesc() const
+ {
+ return _T("assignement operator");
+ }
+
+ //---------------------------------------------------------------------
+ IToken* OprtAssignSub::Clone() const
+ {
+ return new OprtAssignSub(*this);
+ }
+
+ //---------------------------------------------------------------------
+ //
+ // class OprtAssignAdd
+ //
+ //---------------------------------------------------------------------
+
+ OprtAssignMul::OprtAssignMul()
+ :IOprtBin(_T("*="), (int)prASSIGN, oaLEFT)
+ {}
+
+ //---------------------------------------------------------------------
+ void OprtAssignMul::Eval(ptr_val_type& ret, const ptr_val_type *a_pArg, int)
+ {
+ Variable *pVar = dynamic_cast<Variable*>(a_pArg[0].Get());
+ if (!pVar)
+ {
+ ErrorContext err;
+ err.Arg = 1;
+ err.Ident = _T("*=");
+ err.Errc = ecASSIGNEMENT_TO_VALUE;
+ throw ParserError(err);
+ }
+
+ float_type a = a_pArg[0]->GetFloat(),
+ b = a_pArg[0]->GetImag(),
+ c = a_pArg[1]->GetFloat(),
+ d = a_pArg[1]->GetImag();
+ *pVar = cmplx_type(a*c-b*d, a*d-b*c);
+ *ret = *pVar;
+ }
+
+ //---------------------------------------------------------------------
+ const char_type* OprtAssignMul::GetDesc() const
+ {
+ return _T("multiply and assign operator");
+ }
+
+ //---------------------------------------------------------------------
+ IToken* OprtAssignMul::Clone() const
+ {
+ return new OprtAssignMul(*this);
+ }
+
+ //---------------------------------------------------------------------
+ //
+ // class OprtAssignDiv
+ //
+ //---------------------------------------------------------------------
+
+ OprtAssignDiv::OprtAssignDiv() : IOprtBin(_T("/="), (int)prASSIGN, oaLEFT)
+ {}
+
+ //------------------------------------------------------------------------------
+ void OprtAssignDiv::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int)
+ {
+ Variable *pVar = dynamic_cast<Variable*>(a_pArg[0].Get());
+ if (!pVar)
+ {
+ ErrorContext err;
+ err.Arg = 1;
+ err.Ident = _T("/=");
+ err.Errc = ecASSIGNEMENT_TO_VALUE;
+ throw ParserError(err);
+ }
+
+ float_type a = a_pArg[0]->GetFloat(),
+ b = a_pArg[0]->GetImag(),
+ c = a_pArg[1]->GetFloat(),
+ d = a_pArg[1]->GetImag(),
+ n = c*c + d*d;
+ *pVar = cmplx_type((a*c+b*d)/n, (b*c-a*d)/n);
+ *ret = *pVar;
+ }
+
+ //------------------------------------------------------------------------------
+ const char_type* OprtAssignDiv::GetDesc() const
+ {
+ return _T("multiply and divide operator");
+ }
+
+ //------------------------------------------------------------------------------
+ IToken* OprtAssignDiv::Clone() const
+ {
+ return new OprtAssignDiv(*this);
+ }
+MUP_NAMESPACE_END
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpOprtBinAssign.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpOprtBinAssign.h Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,120 @@
+/** \file
+ \brief This file contains the definition of binary assignment
+ operators used in muParser.
+
+<pre>
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+</pre>
+*/
+#ifndef MUP_OPRT_BIN_ASSIGN_H
+#define MUP_OPRT_BIN_ASSIGN_H
+
+//--- Standard includes ----------------------------------------------------------
+#include <cmath>
+
+//--- muParserX framework --------------------------------------------------------
+#include "mpIOprt.h"
+#include "mpValue.h"
+#include "mpVariable.h"
+#include "mpError.h"
+
+
+MUP_NAMESPACE_START
+
+ //------------------------------------------------------------------------------
+ /** \brief Assignement operator.
+
+ This operator can only be applied to variable items.
+ */
+ class OprtAssign : public IOprtBin
+ {
+ public:
+
+ OprtAssign();
+
+ virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int);
+ virtual const char_type* GetDesc() const;
+ virtual IToken* Clone() const;
+ };
+
+ //------------------------------------------------------------------------------
+ /** \brief Assignement operator.
+
+ This operator can only be applied to variable items.
+ */
+ class OprtAssignAdd : public IOprtBin
+ {
+ public:
+ OprtAssignAdd();
+ virtual void Eval(ptr_val_type& ret, const ptr_val_type *a_pArg, int);
+ virtual const char_type* GetDesc() const;
+ virtual IToken* Clone() const;
+ };
+
+ //------------------------------------------------------------------------------
+ /** \brief Assignement operator.
+
+ This operator can only be applied to variable items.
+ */
+ class OprtAssignSub : public IOprtBin
+ {
+ public:
+ OprtAssignSub();
+ virtual void Eval(ptr_val_type& ret, const ptr_val_type *a_pArg, int);
+ virtual const char_type* GetDesc() const;
+ virtual IToken* Clone() const;
+ };
+
+ //------------------------------------------------------------------------------
+ /** \brief Assignement operator.
+
+ This operator can only be applied to variable items.
+ */
+ class OprtAssignMul : public IOprtBin
+ {
+ public:
+ OprtAssignMul();
+ virtual void Eval(ptr_val_type& ret, const ptr_val_type *a_pArg, int);
+ virtual const char_type* GetDesc() const;
+ virtual IToken* Clone() const;
+ };
+
+ //------------------------------------------------------------------------------
+ /** \brief Assignement operator.
+
+ This operator can only be applied to variable items.
+ */
+ class OprtAssignDiv : public IOprtBin
+ {
+ public:
+
+ OprtAssignDiv();
+ virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int);
+ virtual const char_type* GetDesc() const;
+ virtual IToken* Clone() const;
+ };
+
+MUP_NAMESPACE_END
+
+#endif
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpOprtBinCommon.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpOprtBinCommon.cpp Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,356 @@
+/*
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+*/
+#include "mpOprtBinCommon.h"
+
+MUP_NAMESPACE_START
+
+ //-----------------------------------------------------------
+ //
+ // class OprtAnd
+ //
+ //-----------------------------------------------------------
+
+ OprtAnd::OprtAnd()
+ :IOprtBin(_T("&"), (int)prBIT_AND, oaLEFT)
+ {}
+
+ //-----------------------------------------------------------
+ void OprtAnd::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int num)
+ {
+ assert(num==2);
+
+ if (!a_pArg[0]->IsScalar())
+ throw ParserError(ErrorContext(ecTYPE_CONFLICT_FUN, -1, GetIdent(), a_pArg[0]->GetType(), 'i', 1));
+
+ if (!a_pArg[1]->IsScalar())
+ throw ParserError(ErrorContext(ecTYPE_CONFLICT_FUN, -1, GetIdent(), a_pArg[1]->GetType(), 'i', 2));
+
+ float_type a = a_pArg[0]->GetFloat(),
+ b = a_pArg[1]->GetFloat();
+
+ if (a!=(int_type)a)
+ throw ParserError( ErrorContext(ecTYPE_CONFLICT_FUN, -1, a_pArg[0]->GetIdent(), a_pArg[0]->GetType(), 'i', 1) );
+
+ if (b!=(int_type)b)
+ throw ParserError( ErrorContext(ecTYPE_CONFLICT_FUN, -1, a_pArg[1]->GetIdent(), a_pArg[1]->GetType(), 'i', 2) );
+
+ *ret = (int_type)a & (int_type)(b);
+ }
+
+ //-----------------------------------------------------------
+ const char_type* OprtAnd::GetDesc() const
+ {
+ return _T("bitwise and");
+ }
+
+ //-----------------------------------------------------------
+ IToken* OprtAnd::Clone() const
+ {
+ return new OprtAnd(*this);
+ }
+
+ //-----------------------------------------------------------
+ //
+ // class OprtOr
+ //
+ //-----------------------------------------------------------
+
+ OprtOr::OprtOr()
+ :IOprtBin(_T("|"), (int)prBIT_OR, oaLEFT)
+ {}
+
+ //-----------------------------------------------------------
+ void OprtOr::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int num)
+ {
+ assert(num==2);
+
+ if (!a_pArg[0]->IsScalar())
+ throw ParserError(ErrorContext(ecTYPE_CONFLICT_FUN, -1, GetIdent(), a_pArg[0]->GetType(), 'i', 1));
+
+ if (!a_pArg[1]->IsScalar())
+ throw ParserError(ErrorContext(ecTYPE_CONFLICT_FUN, -1, GetIdent(), a_pArg[1]->GetType(), 'i', 2));
+
+ float_type a = a_pArg[0]->GetFloat(),
+ b = a_pArg[1]->GetFloat();
+
+ if (a!=(int_type)a)
+ throw ParserError( ErrorContext(ecTYPE_CONFLICT_FUN, -1, a_pArg[0]->GetIdent(), a_pArg[0]->GetType(), 'i', 1) );
+
+ if (b!=(int_type)b)
+ throw ParserError( ErrorContext(ecTYPE_CONFLICT_FUN, -1, a_pArg[1]->GetIdent(), a_pArg[1]->GetType(), 'i', 2) );
+
+ *ret = (int_type)a | (int_type)(b);
+ }
+
+ //-----------------------------------------------------------
+ const char_type* OprtOr::GetDesc() const
+ {
+ return _T("bitwise or");
+ }
+
+ //-----------------------------------------------------------
+ IToken* OprtOr::Clone() const
+ {
+ return new OprtOr(*this);
+ }
+
+ //-----------------------------------------------------------
+ //
+ // class OprtLOr
+ //
+ //-----------------------------------------------------------
+
+ OprtLOr::OprtLOr()
+ :IOprtBin(_T("||"), (int)prLOGIC_OR, oaLEFT)
+ {}
+
+ //-----------------------------------------------------------
+ void OprtLOr::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int num)
+ {
+ assert(num==2);
+ *ret = a_pArg[0]->GetBool() || a_pArg[1]->GetBool();
+ }
+
+ //-----------------------------------------------------------
+ const char_type* OprtLOr::GetDesc() const
+ {
+ return _T("logical or");
+ }
+
+ //-----------------------------------------------------------
+ IToken* OprtLOr::Clone() const
+ {
+ return new OprtLOr(*this);
+ }
+
+ //-----------------------------------------------------------
+ //
+ // class OprtLAnd
+ //
+ //-----------------------------------------------------------
+
+ OprtLAnd::OprtLAnd()
+ :IOprtBin(_T("&&"), (int)prLOGIC_AND, oaLEFT)
+ {}
+
+ //-----------------------------------------------------------
+ void OprtLAnd::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int num)
+ {
+ assert(num==2);
+ *ret = a_pArg[0]->GetBool() && a_pArg[1]->GetBool();
+ }
+
+ //-----------------------------------------------------------
+ const char_type* OprtLAnd::GetDesc() const
+ {
+ return _T("logical and");
+ }
+
+ //-----------------------------------------------------------
+ IToken* OprtLAnd::Clone() const
+ {
+ return new OprtLAnd(*this);
+ }
+
+ //-----------------------------------------------------------
+ //
+ // class OprtShl
+ //
+ //-----------------------------------------------------------
+
+ OprtShl::OprtShl()
+ :IOprtBin(_T("<<"), (int)prSHIFT, oaLEFT)
+ {}
+
+ //-----------------------------------------------------------
+ void OprtShl::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int num)
+ {
+ assert(num==2);
+
+ if (!a_pArg[0]->IsScalar())
+ throw ParserError(ErrorContext(ecTYPE_CONFLICT_FUN, -1, GetIdent(), a_pArg[0]->GetType(), 'i', 1));
+
+ if (!a_pArg[1]->IsScalar())
+ throw ParserError(ErrorContext(ecTYPE_CONFLICT_FUN, -1, GetIdent(), a_pArg[1]->GetType(), 'i', 2));
+
+ float_type a = a_pArg[0]->GetFloat(),
+ b = a_pArg[1]->GetFloat();
+
+ if (a!=(int_type)a)
+ throw ParserError( ErrorContext(ecTYPE_CONFLICT_FUN, -1, a_pArg[0]->GetIdent(), a_pArg[0]->GetType(), 'i', 1) );
+
+ if (b!=(int_type)b)
+ throw ParserError( ErrorContext(ecTYPE_CONFLICT_FUN, -1, a_pArg[1]->GetIdent(), a_pArg[1]->GetType(), 'i', 2) );
+
+
+ *ret = (int_type)a << (int_type)(b);
+ }
+
+ //-----------------------------------------------------------
+ const char_type* OprtShl::GetDesc() const
+ {
+ return _T("shift left");
+ }
+
+ //-----------------------------------------------------------
+ IToken* OprtShl::Clone() const
+ {
+ return new OprtShl(*this);
+ }
+
+ //-----------------------------------------------------------
+ //
+ // class OprtShr
+ //
+ //-----------------------------------------------------------
+
+ OprtShr::OprtShr()
+ :IOprtBin(_T(">>"), (int)prSHIFT, oaLEFT)
+ {}
+
+ //-----------------------------------------------------------
+ void OprtShr::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int num)
+ {
+ assert(num==2);
+
+ if (!a_pArg[0]->IsScalar())
+ throw ParserError(ErrorContext(ecTYPE_CONFLICT_FUN, -1, GetIdent(), a_pArg[0]->GetType(), 'i', 1));
+
+ if (!a_pArg[1]->IsScalar())
+ throw ParserError(ErrorContext(ecTYPE_CONFLICT_FUN, -1, GetIdent(), a_pArg[1]->GetType(), 'i', 2));
+
+ float_type a = a_pArg[0]->GetFloat(),
+ b = a_pArg[1]->GetFloat();
+
+ if (a!=(int_type)a)
+ throw ParserError( ErrorContext(ecTYPE_CONFLICT_FUN, -1, a_pArg[0]->GetIdent(), a_pArg[0]->GetType(), 'i', 1) );
+
+ if (b!=(int_type)b)
+ throw ParserError( ErrorContext(ecTYPE_CONFLICT_FUN, -1, a_pArg[1]->GetIdent(), a_pArg[1]->GetType(), 'i', 2) );
+
+ *ret = (int_type)a >> (int_type)b;
+ }
+
+ //-----------------------------------------------------------
+ const char_type* OprtShr::GetDesc() const
+ {
+ return _T("shift left");
+ }
+
+ //-----------------------------------------------------------
+ IToken* OprtShr::Clone() const
+ {
+ return new OprtShr(*this);
+ }
+
+ //------------------------------------------------------------------------------
+ //
+ // Cast To Float
+ //
+ //------------------------------------------------------------------------------
+
+ OprtCastToFloat::OprtCastToFloat()
+ :IOprtInfix( _T("(float)"))
+ {}
+
+ //------------------------------------------------------------------------------
+ void OprtCastToFloat::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int /*a_iArgc*/)
+ {
+ switch(a_pArg[0]->GetType())
+ {
+ case 'i':
+ case 'f':
+ case 'b':
+ *ret = a_pArg[0]->GetFloat();
+ break;
+
+ default:
+ {
+ ErrorContext err;
+ err.Errc = ecINVALID_TYPECAST;
+ err.Type1 = a_pArg[0]->GetType();
+ err.Type2 = 'f';
+ throw ParserError(err);
+ }
+ } // switch value type
+ }
+
+ //------------------------------------------------------------------------------
+ const char_type* OprtCastToFloat::GetDesc() const
+ {
+ return _T("cast a value into a floating point number");
+ }
+
+ //------------------------------------------------------------------------------
+ IToken* OprtCastToFloat::Clone() const
+ {
+ return new OprtCastToFloat(*this);
+ }
+
+
+ //------------------------------------------------------------------------------
+ //
+ // Cast To Int
+ //
+ //------------------------------------------------------------------------------
+
+ OprtCastToInt::OprtCastToInt()
+ :IOprtInfix( _T("(int)"))
+ {}
+
+ //------------------------------------------------------------------------------
+ void OprtCastToInt::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int /*a_iArgc*/)
+ {
+ switch(a_pArg[0]->GetType())
+ {
+ case 'f':
+ case 'i':
+ case 'b':
+ *ret = (int_type)a_pArg[0]->GetFloat();
+ break;
+
+ default:
+ {
+ ErrorContext err;
+ err.Errc = ecINVALID_TYPECAST;
+ err.Type1 = a_pArg[0]->GetType();
+ err.Type2 = 'i';
+ throw ParserError(err);
+ }
+ } // switch value type
+ }
+
+ //------------------------------------------------------------------------------
+ const char_type* OprtCastToInt::GetDesc() const
+ {
+ return _T("cast a value into a floating point number");
+ }
+
+ //------------------------------------------------------------------------------
+ IToken* OprtCastToInt::Clone() const
+ {
+ return new OprtCastToInt(*this);
+ }
+}
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpOprtBinCommon.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpOprtBinCommon.h Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,300 @@
+/*
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+*/
+#ifndef MP_OPRT_BIN_H
+#define MP_OPRT_BIN_H
+
+/** \file
+ \brief Definitions of classes used as callbacks for standard binary operators.
+*/
+
+/** \defgroup binop Binary operator callbacks
+
+ This group lists the objects representing the binary operators of muParserX.
+*/
+
+#include <cmath>
+#include "mpIOprt.h"
+#include "mpValue.h"
+#include "mpError.h"
+
+
+MUP_NAMESPACE_START
+
+#define MUP_NAME_PROXY_get_float_type GetFloat
+#define MUP_NAME_PROXY_get_string_type GetString
+#define MUP_NAME_PROXY_get_bool_type GetBool
+#define MUP_NAME_PROXY_get_value_type
+
+/** \brief MUP_BINARY_OPERATOR(CLASS, IDENT, PROT, TYPE, DESC, PRI, OP)
+ \param CLASS Name of the class to be defined
+ \param IDENT The string to be used as the operator identifier
+ \param PROT A string representing the operators prototype
+ \param TYPE The datatype used for the operation
+ \param DESC A string containing the operator description
+ \param PRI The operator precedence
+ \param OP The operation to perform
+
+ A macro for simplifying the process of creating binary operator
+ callback classes.
+*/
+#define MUP_BINARY_OPERATOR(CLASS, IDENT, TYPE, DESC, PRI, ASC, OP) \
+ class CLASS : public IOprtBin \
+ { \
+ public: \
+ CLASS() : IOprtBin((IDENT), (PRI), (ASC)) {} \
+ \
+ virtual void Eval(ptr_val_type& ret, const ptr_val_type *arg, int argc)\
+ { \
+ assert(argc==2); \
+ TYPE a = arg[0]->MUP_NAME_PROXY_get_##TYPE(); \
+ TYPE b = arg[1]->MUP_NAME_PROXY_get_##TYPE(); \
+ *ret = OP; \
+ } \
+ \
+ virtual const char_type* GetDesc() const { return (DESC); } \
+ virtual IToken* Clone() const { return new CLASS(); } \
+ };
+
+ // for string values
+ MUP_BINARY_OPERATOR(OprtStrAdd, _T("//"), string_type, _T(""), 2, oaLEFT, a+b)
+ // logical operators
+ MUP_BINARY_OPERATOR(OprtBAnd, _T("and"), bool_type, _T("less than"), 1, oaLEFT, a&&b)
+ MUP_BINARY_OPERATOR(OprtBOr, _T("or"), bool_type, _T("less than"), 1, oaLEFT, a||b)
+ MUP_BINARY_OPERATOR(OprtBXor, _T("xor"), bool_type, _T("less than"), 1, oaLEFT, (bool_type)(a^b))
+
+//#undef MUP_NAME_PROXY_get_float_type
+//#undef MUP_NAME_PROXY_get_string_type
+//#undef MUP_NAME_PROXY_get_bool_type
+//#undef MUP_BINARY_OPERATOR
+
+ //------------------------------------------------------------------------------
+ /** \brief Callback object for testing if two values are equal.
+ \ingroup binop
+ */
+ class OprtEQ : public IOprtBin
+ {
+ public:
+ OprtEQ() : IOprtBin(_T("=="), 2, oaLEFT) {}
+ virtual void Eval(ptr_val_type& ret, const ptr_val_type *a_pArg, int)
+ {
+ *ret = *a_pArg[0] == *a_pArg[1];
+ }
+ virtual const char_type* GetDesc() const { return _T("equals operator"); }
+ virtual IToken* Clone() const { return new OprtEQ; }
+ };
+
+
+ //------------------------------------------------------------------------------
+ /** \brief Callback object for testing if two values are not equal.
+ \ingroup binop
+ */
+ class OprtNEQ : public IOprtBin
+ {
+ public:
+ OprtNEQ() : IOprtBin(_T("!="), 2, oaLEFT) {}
+ virtual void Eval(ptr_val_type& ret, const ptr_val_type *a_pArg, int)
+ {
+ *ret = *a_pArg[0] != *a_pArg[1];
+ }
+
+ virtual const char_type* GetDesc() const { return _T("neq operator"); }
+ virtual IToken* Clone() const { return new OprtNEQ; }
+ };
+
+ //------------------------------------------------------------------------------
+ /** \brief Callback object class for the "Less than" operator.
+ \ingroup binop
+ */
+ class OprtLT : public IOprtBin
+ {
+ public:
+ OprtLT() : IOprtBin(_T("<"), 2, oaLEFT) {}
+ virtual void Eval(ptr_val_type& ret, const ptr_val_type *a_pArg, int)
+ {
+ *ret = *a_pArg[0] < *a_pArg[1];
+ }
+
+ virtual const char_type* GetDesc() const { return _T("less operator"); }
+ virtual IToken* Clone() const { return new OprtLT; }
+ };
+
+ //------------------------------------------------------------------------------
+ /** \brief Callback object class for the "Greater than" operator.
+ \ingroup binop
+ */
+ class OprtGT : public IOprtBin
+ {
+ public:
+ OprtGT() : IOprtBin(_T(">"), 2, oaLEFT) {}
+ virtual void Eval(ptr_val_type& ret, const ptr_val_type *a_pArg, int)
+ {
+ *ret = *a_pArg[0] > *a_pArg[1];
+ }
+
+ virtual const char_type* GetDesc() const { return _T("greater than"); }
+ virtual IToken* Clone() const { return new OprtGT; }
+ };
+
+ //------------------------------------------------------------------------------
+ /** \brief Callback object class for the "Less or equal" operator.
+ \ingroup binop
+ */
+ class OprtLE : public IOprtBin
+ {
+ public:
+ OprtLE() : IOprtBin(_T("<="), 2, oaLEFT) {}
+ virtual void Eval(ptr_val_type& ret, const ptr_val_type *a_pArg, int)
+ {
+ *ret = *a_pArg[0] <= *a_pArg[1];
+ }
+
+ virtual const char_type* GetDesc() const { return _T("less or equal operator"); }
+ virtual IToken* Clone() const { return new OprtLE; }
+ };
+
+ //------------------------------------------------------------------------------
+ /** \brief Callback object class for the "Greater or or equal" operator.
+ \ingroup binop
+ */
+ class OprtGE : public IOprtBin
+ {
+ public:
+ OprtGE() : IOprtBin(_T(">="), 2, oaLEFT) {}
+ virtual void Eval(ptr_val_type& ret, const ptr_val_type *a_pArg, int)
+ {
+ *ret = *a_pArg[0] >= *a_pArg[1];
+ }
+
+ virtual const char_type* GetDesc() const { return _T("greater or equal operator"); }
+ virtual IToken* Clone() const { return new OprtGE; }
+ };
+
+ //------------------------------------------------------------------------------
+ /** \brief Callback class for a logic and operator.
+ \ingroup binop
+ */
+ class OprtAnd : public IOprtBin
+ {
+ public:
+ OprtAnd();
+ virtual void Eval(ptr_val_type& ret, const ptr_val_type *a_pArg, int);
+ virtual const char_type* GetDesc() const;
+ virtual IToken* Clone() const;
+ };
+
+ //------------------------------------------------------------------------------
+ /** \brief Callback class for a logic or operator.
+ \ingroup binop
+ */
+ class OprtOr : public IOprtBin
+ {
+ public:
+ OprtOr();
+ virtual void Eval(ptr_val_type& ret, const ptr_val_type *a_pArg, int);
+ virtual const char_type* GetDesc() const;
+ virtual IToken* Clone() const;
+ };
+
+ //------------------------------------------------------------------------------
+ /** \brief Callback class for a logical or operator.
+ \ingroup binop
+ */
+ class OprtLOr : public IOprtBin
+ {
+ public:
+ OprtLOr();
+ virtual void Eval(ptr_val_type& ret, const ptr_val_type *a_pArg, int);
+ virtual const char_type* GetDesc() const;
+ virtual IToken* Clone() const;
+ };
+
+ //------------------------------------------------------------------------------
+ /** \brief Callback class for a logical and operator.
+ \ingroup binop
+ */
+ class OprtLAnd : public IOprtBin
+ {
+ public:
+ OprtLAnd();
+ virtual void Eval(ptr_val_type& ret, const ptr_val_type *a_pArg, int);
+ virtual const char_type* GetDesc() const;
+ virtual IToken* Clone() const;
+ };
+
+ //------------------------------------------------------------------------------
+ /** \brief Callback class for the shift left operator.
+ \ingroup binop
+ */
+ class OprtShl : public IOprtBin
+ {
+ public:
+ OprtShl();
+ virtual void Eval(ptr_val_type& ret, const ptr_val_type *a_pArg, int);
+ virtual const char_type* GetDesc() const;
+ virtual IToken* Clone() const;
+ };
+
+ //------------------------------------------------------------------------------
+ /** \brief Callback class for the shift right operator.
+ \ingroup binop
+ */
+ class OprtShr : public IOprtBin
+ {
+ public:
+ OprtShr();
+ virtual void Eval(ptr_val_type& ret, const ptr_val_type *a_pArg, int);
+ virtual const char_type* GetDesc() const;
+ virtual IToken* Clone() const;
+ };
+
+ //---------------------------------------------------------------------------
+ /** \brief Callback for an operator allowing to cast values to floating
+ point values.
+ \ingroup infix
+ */
+ class OprtCastToFloat : public IOprtInfix
+ {
+ public:
+ OprtCastToFloat();
+ virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc);
+ virtual const char_type* GetDesc() const;
+ virtual IToken* Clone() const;
+ }; // class OprtCastToFloat
+
+ //---------------------------------------------------------------------------
+ /** \brief Callback for an operator allowing to cast values to integer values.
+ \ingroup infix
+ */
+ class OprtCastToInt : public IOprtInfix
+ {
+ public:
+ OprtCastToInt();
+ virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc);
+ virtual const char_type* GetDesc() const;
+ virtual IToken* Clone() const;
+ }; // class OprtCastToInt
+} // namespace mu
+
+#endif
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpOprtCmplx.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpOprtCmplx.cpp Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,302 @@
+/*
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+*/
+#include "mpOprtCmplx.h"
+#include <iomanip>
+
+
+MUP_NAMESPACE_START
+
+//------------------------------------------------------------------------------
+//
+// class OprtSignCmplx
+//
+//------------------------------------------------------------------------------
+
+ OprtSignCmplx::OprtSignCmplx()
+ :IOprtInfix( _T("-"))
+ {}
+
+ //------------------------------------------------------------------------------
+ void OprtSignCmplx::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc)
+ {
+ MUP_ASSERT(a_iArgc==1);
+
+ if (a_pArg[0]->IsScalar())
+ {
+ float_type re = a_pArg[0]->GetFloat();
+ float_type im = a_pArg[0]->GetImag();
+
+ // Do not omit the test for zero! Multiplying 0 with -1
+ // will yield -0 on IEEE754 compliant implementations!
+ // This would change the result of complex calculations:
+ //
+ // i.e. sqrt(-1 + (-0)i) != sqrt(-1 + 0i)
+ // -i != i
+ cmplx_type v((re==0) ? 0 : -re, (im==0) ? 0 : -im);
+ *ret = v;
+ }
+ else if (a_pArg[0]->GetType()=='m')
+ {
+ Value v(a_pArg[0]->GetRows(), 0);
+ for (int i=0; i<a_pArg[0]->GetRows(); ++i)
+ {
+ v.At(i) = a_pArg[0]->At(i).GetComplex() * -1.0;
+ }
+ *ret = v;
+ }
+ else
+ {
+ ErrorContext err;
+ err.Errc = ecINVALID_TYPE;
+ err.Type1 = a_pArg[0]->GetType();
+ err.Type2 = 's';
+ throw ParserError(err);
+ }
+ }
+
+ //------------------------------------------------------------------------------
+ const char_type* OprtSignCmplx::GetDesc() const
+ {
+ return _T("unit multiplicator 1e-9");
+ }
+
+ //------------------------------------------------------------------------------
+ IToken* OprtSignCmplx::Clone() const
+ {
+ return new OprtSignCmplx(*this);
+ }
+
+//-----------------------------------------------------------
+//
+// class OprtAddCmplx
+//
+//-----------------------------------------------------------
+
+ OprtAddCmplx::OprtAddCmplx()
+ :IOprtBin(_T("+"), (int)prADD_SUB, oaLEFT)
+ {}
+
+ //-----------------------------------------------------------
+ void OprtAddCmplx::Eval(ptr_val_type& ret, const ptr_val_type *a_pArg, int num)
+ {
+ assert(num==2);
+
+ const IValue *arg1 = a_pArg[0].Get();
+ const IValue *arg2 = a_pArg[1].Get();
+
+ if (arg1->IsNonComplexScalar() && arg2->IsNonComplexScalar())
+ {
+ *ret = arg1->GetFloat() + arg2->GetFloat();
+ }
+ else if (arg1->GetType()=='m' && arg2->GetType()=='m')
+ {
+ // Matrix + Matrix
+ *ret = arg1->GetArray() + arg2->GetArray();
+ }
+ else
+ {
+ if (!arg1->IsScalar())
+ throw ParserError( ErrorContext(ecTYPE_CONFLICT_FUN, GetExprPos(), GetIdent(), arg1->GetType(), 'c', 1));
+
+ if (!arg2->IsScalar())
+ throw ParserError( ErrorContext(ecTYPE_CONFLICT_FUN, GetExprPos(), GetIdent(), arg2->GetType(), 'c', 2));
+
+ *ret = cmplx_type(arg1->GetFloat() + arg2->GetFloat(),
+ arg1->GetImag() + arg2->GetImag());
+ }
+ }
+
+ //-----------------------------------------------------------
+ const char_type* OprtAddCmplx::GetDesc() const
+ {
+ return _T("addition");
+ }
+
+ //-----------------------------------------------------------
+ IToken* OprtAddCmplx::Clone() const
+ {
+ return new OprtAddCmplx(*this);
+ }
+
+//-----------------------------------------------------------
+//
+// class OprtSubCmplx
+//
+//-----------------------------------------------------------
+
+ OprtSubCmplx::OprtSubCmplx()
+ :IOprtBin(_T("-"), (int)prADD_SUB, oaLEFT)
+ {}
+
+ //-----------------------------------------------------------
+ void OprtSubCmplx::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int num)
+ {
+ assert(num==2);
+
+ const IValue *arg1 = a_pArg[0].Get();
+ const IValue *arg2 = a_pArg[1].Get();
+ if ( a_pArg[0]->IsNonComplexScalar() && a_pArg[1]->IsNonComplexScalar())
+ {
+ *ret = arg1->GetFloat() - arg2->GetFloat();
+ }
+ else if (a_pArg[0]->GetType()=='m' && a_pArg[1]->GetType()=='m')
+ {
+ // Matrix + Matrix
+ *ret = arg1->GetArray() - arg2->GetArray();
+ }
+ else
+ {
+ if (!a_pArg[0]->IsScalar())
+ throw ParserError( ErrorContext(ecTYPE_CONFLICT_FUN, GetExprPos(), GetIdent(), a_pArg[0]->GetType(), 'c', 1));
+
+ if (!a_pArg[1]->IsScalar())
+ throw ParserError( ErrorContext(ecTYPE_CONFLICT_FUN, GetExprPos(), GetIdent(), a_pArg[1]->GetType(), 'c', 2));
+
+ *ret = cmplx_type(a_pArg[0]->GetFloat() - a_pArg[1]->GetFloat(),
+ a_pArg[0]->GetImag() - a_pArg[1]->GetImag());
+ }
+ }
+
+ //-----------------------------------------------------------
+ const char_type* OprtSubCmplx::GetDesc() const
+ {
+ return _T("subtraction");
+ }
+
+ //-----------------------------------------------------------
+ IToken* OprtSubCmplx::Clone() const
+ {
+ return new OprtSubCmplx(*this);
+ }
+
+//-----------------------------------------------------------
+//
+// class OprtMulCmplx
+//
+//-----------------------------------------------------------
+
+ OprtMulCmplx::OprtMulCmplx()
+ :IOprtBin(_T("*"), (int)prMUL_DIV, oaLEFT)
+ {}
+
+ //-----------------------------------------------------------
+ void OprtMulCmplx::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int num)
+ {
+ assert(num==2);
+ IValue *arg1 = a_pArg[0].Get();
+ IValue *arg2 = a_pArg[1].Get();
+ *ret = (*arg1) * (*arg2);
+ }
+
+ //-----------------------------------------------------------
+ const char_type* OprtMulCmplx::GetDesc() const
+ {
+ return _T("foo*bar - multiplication");
+ }
+
+ //-----------------------------------------------------------
+ IToken* OprtMulCmplx::Clone() const
+ {
+ return new OprtMulCmplx(*this);
+ }
+
+//-----------------------------------------------------------
+//
+// class OprtDivCmplx
+//
+//-----------------------------------------------------------
+
+
+ OprtDivCmplx::OprtDivCmplx()
+ :IOprtBin(_T("/"), (int)prMUL_DIV, oaLEFT)
+ {}
+
+ //-----------------------------------------------------------
+ /** \brief Implements the Division operator.
+ \throw ParserError in case one of the arguments if
+ nonnumeric or an array.
+
+ */
+ void OprtDivCmplx::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int num)
+ {
+ assert(num==2);
+
+ if ( a_pArg[0]->IsNonComplexScalar() && a_pArg[1]->IsNonComplexScalar())
+ {
+ *ret = a_pArg[0]->GetFloat() / a_pArg[1]->GetFloat();
+ }
+ else
+ {
+ // multiplication of two imaginary numbers
+ float_type a = a_pArg[0]->GetFloat(),
+ b = a_pArg[0]->GetImag(),
+ c = a_pArg[1]->GetFloat(),
+ d = a_pArg[1]->GetImag(),
+ n = c*c + d*d;
+ *ret = cmplx_type((a*c+b*d)/n, (b*c-a*d)/n);
+ }
+ }
+
+ //-----------------------------------------------------------
+ const char_type* OprtDivCmplx::GetDesc() const
+ {
+ return _T("division");
+ }
+
+ //-----------------------------------------------------------
+ IToken* OprtDivCmplx::Clone() const
+ {
+ return new OprtDivCmplx(*this);
+ }
+
+//-----------------------------------------------------------
+//
+// class OprtPowCmplx
+//
+//-----------------------------------------------------------
+
+ OprtPowCmplx::OprtPowCmplx()
+ :IOprtBin(_T("^"), (int)prPOW, oaRIGHT)
+ {}
+
+ //-----------------------------------------------------------
+ void OprtPowCmplx::Eval(ptr_val_type& ret, const ptr_val_type *arg, int argc)
+ {
+ assert(argc==2);
+ *ret = exp(arg[1]->GetComplex() * log(arg[0]->GetComplex()));
+ }
+
+ //-----------------------------------------------------------
+ const char_type* OprtPowCmplx::GetDesc() const
+ {
+ return _T("raise x to the power of y");
+ }
+
+ //-----------------------------------------------------------
+ IToken* OprtPowCmplx::Clone() const
+ {
+ return new OprtPowCmplx(*this);
+ }
+}
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpOprtCmplx.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpOprtCmplx.h Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,124 @@
+/*
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+*/
+#ifndef MP_OPRT_CMPLX_H
+#define MP_OPRT_CMPLX_H
+
+/** \file
+ \brief Definitions of classes used as callbacks for standard binary operators.
+*/
+
+/** \defgroup binop Binary operator callbacks
+
+ This group lists the objects representing the binary operators of muParserX.
+*/
+
+#include <cmath>
+#include "mpIOprt.h"
+#include "mpValue.h"
+#include "mpError.h"
+
+
+MUP_NAMESPACE_START
+
+ //---------------------------------------------------------------------------
+ /** \brief Callback for the negative sign operator.
+ \ingroup infix
+ */
+ class OprtSignCmplx : public IOprtInfix
+ {
+ public:
+ OprtSignCmplx();
+ virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc);
+ virtual const char_type* GetDesc() const;
+ virtual IToken* Clone() const;
+ }; // class OprtSignCmplx
+
+ //------------------------------------------------------------------------------
+ /** \brief Parser callback for implementing an addition of two complex values.
+ \ingroup binop
+ */
+ class OprtAddCmplx : public IOprtBin
+ {
+ public:
+ OprtAddCmplx();
+ virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int);
+ virtual const char_type* GetDesc() const;
+ virtual IToken* Clone() const;
+ };
+
+ //------------------------------------------------------------------------------
+ /** \brief Parser callback for implementing the subtraction of two complex values.
+ \ingroup binop
+ */
+ class OprtSubCmplx : public IOprtBin
+ {
+ public:
+ OprtSubCmplx();
+ virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int);
+ virtual const char_type* GetDesc() const;
+ virtual IToken* Clone() const;
+ };
+
+ //------------------------------------------------------------------------------
+ /** \brief Callback object for implementing the multiplications of complex values.
+ \ingroup binop
+ */
+ class OprtMulCmplx : public IOprtBin
+ {
+ public:
+ OprtMulCmplx();
+ virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int);
+ virtual const char_type* GetDesc() const;
+ virtual IToken* Clone() const;
+ };
+
+ //------------------------------------------------------------------------------
+ /** \brief Callback object for implementing the division of complex values.
+ \ingroup binop
+ */
+ class OprtDivCmplx : public IOprtBin
+ {
+ public:
+ OprtDivCmplx();
+ virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int);
+ virtual const char_type* GetDesc() const;
+ virtual IToken* Clone() const;
+ };
+
+ //------------------------------------------------------------------------------
+ /** \brief Raise x to the power of y.
+ \ingroup binop
+ */
+ class OprtPowCmplx : public IOprtBin
+ {
+ public:
+ OprtPowCmplx();
+ virtual void Eval(ptr_val_type& ret, const ptr_val_type *arg, int argc);
+ virtual const char_type* GetDesc() const;
+ virtual IToken* Clone() const;
+ };
+} // namespace mu
+
+#endif
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpOprtIndex.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpOprtIndex.cpp Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,92 @@
+/*
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+*/
+#include "mpOprtIndex.h"
+#include "mpVariable.h"
+
+MUP_NAMESPACE_START
+
+ //-----------------------------------------------------------------------------------------------
+ //
+ // class OprtIndex
+ //
+ //-----------------------------------------------------------------------------------------------
+
+ OprtIndex::OprtIndex(IPackage* pPackage)
+ :IOprtIndex(-1)
+ {}
+
+ //-----------------------------------------------------------------------------------------------
+ /** \brief Index operator implementation
+ \param ret A reference to the return value
+ \param a_pArg Pointer to an array with the indices as ptr_val_type
+ \param a_iArgc Number of indices (=dimension) actully used in the expression found. This must
+ be 1 or 2 since three dimensional data structures are not supported by muParserX.
+ */
+ void OprtIndex::At(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc)
+ {
+ try
+ {
+ // The index is -1, thats the actual variable reference
+ if (a_iArgc!=a_pArg[-1]->GetDim())
+ {
+ throw ParserError(ErrorContext(ecINDEX_DIMENSION, -1, GetIdent()));
+ }
+
+ switch(a_iArgc)
+ {
+ case 1:
+ ret.Reset(new Variable( &(ret->At(*a_pArg[0], Value(0))) ) );
+ break;
+
+ case 2:
+ ret.Reset(new Variable( &(ret->At(*a_pArg[0], *a_pArg[1])) ) );
+ break;
+
+ default:
+ throw ParserError(ErrorContext(ecINDEX_DIMENSION, -1, GetIdent()));
+ }
+ }
+ catch(ParserError &exc)
+ {
+ exc.GetContext().Pos = GetExprPos();
+ throw exc;
+ }
+ }
+
+ //-----------------------------------------------------------------------------------------------
+ const char_type* OprtIndex::GetDesc() const
+ {
+ return _T("[,] - The index operator.");
+ }
+
+ //-----------------------------------------------------------------------------------------------
+ IToken* OprtIndex::Clone() const
+ {
+ return new OprtIndex(*this);
+ }
+
+
+
+MUP_NAMESPACE_END
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpOprtIndex.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpOprtIndex.h Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,59 @@
+/*
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+*/
+#ifndef MP_OPRT_INDEX_H
+#define MP_OPRT_INDEX_H
+
+/** \file
+ \brief Definitions of index operator classes.
+*/
+
+/** \defgroup binop Binary operator callbacks
+
+ This group lists the objects representing the binary operators of muParserX.
+*/
+
+#include <cmath>
+#include "mpIOprt.h"
+#include "mpValue.h"
+#include "mpError.h"
+
+
+MUP_NAMESPACE_START
+
+ //-----------------------------------------------------------------------------------------------
+ /** \brief Default implementation of a multidimensional index operator.
+ */
+ class OprtIndex : public IOprtIndex
+ {
+ public:
+ OprtIndex(IPackage* pPackage=NULL);
+ virtual void At(ptr_val_type& ret, const ptr_val_type *arg, int argc);
+ virtual const char_type* GetDesc() const;
+ virtual IToken* Clone() const;
+ };
+
+MUP_NAMESPACE_END
+
+#endif
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpOprtMatrix.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpOprtMatrix.cpp Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,111 @@
+/*
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+*/
+#include "mpOprtMatrix.h"
+
+
+MUP_NAMESPACE_START
+
+//-------------------------------------------------------------------------------------------------
+//
+// class OprtTranspose
+//
+//-------------------------------------------------------------------------------------------------
+
+ OprtTranspose::OprtTranspose(IPackage* pPackage)
+ :IOprtPostfix(_T("'"))
+ {}
+
+ //-------------------------------------------------------------------------------------------------
+ void OprtTranspose::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc)
+ {
+ if (a_pArg[0]->IsMatrix())
+ {
+ matrix_type matrix = a_pArg[0]->GetArray();
+ matrix.Transpose();
+ *ret = matrix;
+ }
+ else
+ *ret = *a_pArg[0];
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ const char_type* OprtTranspose::GetDesc() const
+ {
+ return _T("foo' - An operator for transposing a matrix.");
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ IToken* OprtTranspose::Clone() const
+ {
+ return new OprtTranspose(*this);
+ }
+
+//-----------------------------------------------------------
+//
+// class OprtAdd
+//
+//-----------------------------------------------------------
+
+ OprtColon::OprtColon()
+ :IOprtBin(_T("~"), (int)prCOLON, oaLEFT)
+ {}
+
+ //-----------------------------------------------------------
+ void OprtColon::Eval(ptr_val_type& ret, const ptr_val_type *a_pArg, int num)
+ {
+ assert(num==2);
+
+ const IValue *argMin = a_pArg[0].Get();
+ const IValue *argMax = a_pArg[1].Get();
+
+ if (!argMin->IsNonComplexScalar())
+ throw ParserError( ErrorContext(ecTYPE_CONFLICT_FUN, -1, GetIdent(), argMin->GetType(), 'i', 1));
+
+ if (!argMax->IsNonComplexScalar())
+ throw ParserError( ErrorContext(ecTYPE_CONFLICT_FUN, -1, GetIdent(), argMax->GetType(), 'i', 1));
+
+ if (*argMax < *argMin)
+ throw ParserError(_T("Colon operator: Maximum value smaller than Minimum!"));
+
+ int n = (argMax->GetFloat() - argMin->GetFloat()) + 1;
+ matrix_type arr(n);
+ for (int i=0; i<n; ++i)
+ arr.At(i) = argMin->GetFloat() + i;
+
+ *ret = arr;
+ }
+
+ //-----------------------------------------------------------
+ const char_type* OprtColon::GetDesc() const
+ {
+ return _T(": - Colon operator");
+ }
+
+ //-----------------------------------------------------------
+ IToken* OprtColon::Clone() const
+ {
+ return new OprtColon(*this);
+ }
+MUP_NAMESPACE_END
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpOprtMatrix.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpOprtMatrix.h Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,62 @@
+/*
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+*/
+#ifndef MP_OPRT_MATRIX_H
+#define MP_OPRT_MATRIX_H
+
+/** \file
+ \brief Definitions of classes used as callbacks for matrix operators.
+*/
+
+
+#include <cmath>
+#include "mpIOprt.h"
+#include "mpValue.h"
+#include "mpError.h"
+
+
+MUP_NAMESPACE_START
+
+ //-----------------------------------------------------------------------------------------------
+ class OprtTranspose : public IOprtPostfix
+ {
+ public:
+ OprtTranspose(IPackage* pPackage=NULL);
+ virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc);
+ virtual const char_type* GetDesc() const;
+ virtual IToken* Clone() const;
+ };
+
+ //-----------------------------------------------------------------------------------------------
+ class OprtColon : public IOprtBin
+ {
+ public:
+ OprtColon();
+ virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc);
+ virtual const char_type* GetDesc() const;
+ virtual IToken* Clone() const;
+ };
+MUP_NAMESPACE_END
+
+#endif
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpOprtNonCmplx.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpOprtNonCmplx.cpp Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,363 @@
+/*
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+*/
+#include "mpOprtNonCmplx.h"
+
+MUP_NAMESPACE_START
+
+ //------------------------------------------------------------------------------
+ //
+ // Sign operator
+ //
+ //------------------------------------------------------------------------------
+
+ OprtSign::OprtSign()
+ :IOprtInfix( _T("-"))
+ {}
+
+ //------------------------------------------------------------------------------
+ void OprtSign::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc)
+ {
+ MUP_ASSERT(a_iArgc==1);
+
+ if (a_pArg[0]->IsScalar())
+ {
+ *ret = -a_pArg[0]->GetFloat();
+ }
+ else if (a_pArg[0]->GetType()=='m')
+ {
+ Value v(a_pArg[0]->GetRows(), 0);
+ for (int i=0; i<a_pArg[0]->GetRows(); ++i)
+ {
+ v.At(i) = -a_pArg[0]->At(i).GetFloat();
+ }
+ *ret = v;
+ }
+ else
+ {
+ ErrorContext err;
+ err.Errc = ecINVALID_TYPE;
+ err.Type1 = a_pArg[0]->GetType();
+ err.Type2 = 's';
+ throw ParserError(err);
+ }
+ }
+
+ //------------------------------------------------------------------------------
+ const char_type* OprtSign::GetDesc() const
+ {
+ return _T("unit multiplicator 1e-9");
+ }
+
+ //------------------------------------------------------------------------------
+ IToken* OprtSign::Clone() const
+ {
+ return new OprtSign(*this);
+ }
+
+//-----------------------------------------------------------
+//
+// class OprtAdd
+//
+//-----------------------------------------------------------
+
+ OprtAdd::OprtAdd()
+ :IOprtBin(_T("+"), (int)prADD_SUB, oaLEFT)
+ {}
+
+ //-----------------------------------------------------------
+ void OprtAdd::Eval(ptr_val_type& ret, const ptr_val_type *a_pArg, int num)
+ {
+ assert(num==2);
+
+ const IValue *arg1 = a_pArg[0].Get();
+ const IValue *arg2 = a_pArg[1].Get();
+ if (arg1->GetType()=='m' && arg2->GetType()=='m')
+ {
+ // Vector + Vector
+ const matrix_type &a1 = arg1->GetArray(),
+ &a2 = arg2->GetArray();
+ if (a1.GetRows()!=a2.GetRows())
+ throw ParserError(ErrorContext(ecARRAY_SIZE_MISMATCH, -1, GetIdent(), 'm', 'm', 2));
+
+ matrix_type rv(a1.GetRows());
+ for (int i=0; i<a1.GetRows(); ++i)
+ {
+ if (!a1.At(i).IsNonComplexScalar())
+ throw ParserError( ErrorContext(ecTYPE_CONFLICT_FUN, -1, GetIdent(), a1.At(i).GetType(), 'f', 1));
+
+ if (!a2.At(i).IsNonComplexScalar())
+ throw ParserError( ErrorContext(ecTYPE_CONFLICT_FUN, -1, GetIdent(), a2.At(i).GetType(), 'f', 1));
+
+ rv.At(i) = a1.At(i).GetFloat() + a2.At(i).GetFloat();
+ }
+
+ *ret = rv;
+ }
+ else
+ {
+ if (!arg1->IsNonComplexScalar())
+ throw ParserError( ErrorContext(ecTYPE_CONFLICT_FUN, -1, GetIdent(), arg1->GetType(), 'f', 1));
+
+ if (!arg2->IsNonComplexScalar())
+ throw ParserError( ErrorContext(ecTYPE_CONFLICT_FUN, -1, GetIdent(), arg2->GetType(), 'f', 2));
+
+ *ret = arg1->GetFloat() + arg2->GetFloat();
+ }
+ }
+
+ //-----------------------------------------------------------
+ const char_type* OprtAdd::GetDesc() const
+ {
+ return _T("x+y - Addition for noncomplex values");
+ }
+
+ //-----------------------------------------------------------
+ IToken* OprtAdd::Clone() const
+ {
+ return new OprtAdd(*this);
+ }
+
+//-----------------------------------------------------------
+//
+// class OprtSub
+//
+//-----------------------------------------------------------
+
+ OprtSub::OprtSub()
+ :IOprtBin(_T("-"), (int)prADD_SUB, oaLEFT)
+ {}
+
+ //-----------------------------------------------------------
+ void OprtSub::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int num)
+ {
+ assert(num==2);
+
+ if (a_pArg[0]->GetType()=='m' && a_pArg[1]->GetType()=='m')
+ {
+ const matrix_type &a1 = a_pArg[0]->GetArray(),
+ &a2 = a_pArg[1]->GetArray();
+ if (a1.GetRows()!=a2.GetRows())
+ throw ParserError(ErrorContext(ecARRAY_SIZE_MISMATCH, -1, GetIdent(), 'm', 'm', 2));
+
+ matrix_type rv(a1.GetRows());
+ for (int i=0; i<a1.GetRows(); ++i)
+ {
+ if (!a1.At(i).IsNonComplexScalar())
+ throw ParserError( ErrorContext(ecTYPE_CONFLICT_FUN, -1, GetIdent(), a1.At(i).GetType(), 'f', 1));
+
+ if (!a2.At(i).IsNonComplexScalar())
+ throw ParserError( ErrorContext(ecTYPE_CONFLICT_FUN, -1, GetIdent(), a2.At(i).GetType(), 'f', 1));
+
+ rv.At(i) = cmplx_type(a1.At(i).GetFloat() - a2.At(i).GetFloat(),
+ a1.At(i).GetImag() - a2.At(i).GetImag());
+ }
+
+ *ret = rv;
+ }
+ else
+ {
+ if (!a_pArg[0]->IsNonComplexScalar())
+ throw ParserError( ErrorContext(ecTYPE_CONFLICT_FUN, -1, GetIdent(), a_pArg[0]->GetType(), 'f', 1));
+
+ if (!a_pArg[1]->IsNonComplexScalar())
+ throw ParserError( ErrorContext(ecTYPE_CONFLICT_FUN, -1, GetIdent(), a_pArg[1]->GetType(), 'f', 2));
+
+ *ret = a_pArg[0]->GetFloat() - a_pArg[1]->GetFloat();
+ }
+ }
+
+ //-----------------------------------------------------------
+ const char_type* OprtSub::GetDesc() const
+ {
+ return _T("subtraction");
+ }
+
+ //-----------------------------------------------------------
+ IToken* OprtSub::Clone() const
+ {
+ return new OprtSub(*this);
+ }
+
+//-----------------------------------------------------------
+//
+// class OprtMul
+//
+//-----------------------------------------------------------
+
+ OprtMul::OprtMul()
+ :IOprtBin(_T("*"), (int)prMUL_DIV, oaLEFT)
+ {}
+
+ //-----------------------------------------------------------
+ void OprtMul::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int num)
+ {
+ assert(num==2);
+ IValue *arg1 = a_pArg[0].Get();
+ IValue *arg2 = a_pArg[1].Get();
+ if (arg1->GetType()=='m' && arg2->GetType()=='m')
+ {
+ // Scalar multiplication
+ matrix_type a1 = arg1->GetArray();
+ matrix_type a2 = arg2->GetArray();
+
+ if (a1.GetRows()!=a2.GetRows())
+ throw ParserError(ErrorContext(ecARRAY_SIZE_MISMATCH, -1, GetIdent(), 'm', 'm', 2));
+
+ float_type val(0);
+ for (int i=0; i<a1.GetRows(); ++i)
+ val += a1.At(i).GetFloat()*a2.At(i).GetFloat();
+
+ *ret = val;
+ }
+ else if (arg1->GetType()=='m' && arg2->IsNonComplexScalar())
+ {
+ // Skalar * Vector
+ matrix_type out(a_pArg[0]->GetArray());
+ for (int i=0; i<out.GetRows(); ++i)
+ out.At(i) = out.At(i).GetFloat() * arg2->GetFloat();
+
+ *ret = out;
+ }
+ else if (arg2->GetType()=='m' && arg1->IsNonComplexScalar())
+ {
+ // Vector * Skalar
+ matrix_type out(arg2->GetArray());
+ for (int i=0; i<out.GetRows(); ++i)
+ out.At(i) = out.At(i).GetFloat() * arg1->GetFloat();
+
+ *ret = out;
+ }
+ else
+ {
+ if (!arg1->IsNonComplexScalar())
+ throw ParserError( ErrorContext(ecTYPE_CONFLICT_FUN, -1, GetIdent(), arg1->GetType(), 'f', 1));
+
+ if (!arg2->IsNonComplexScalar())
+ throw ParserError( ErrorContext(ecTYPE_CONFLICT_FUN, -1, GetIdent(), arg2->GetType(), 'f', 2));
+
+ *ret = arg1->GetFloat() * arg2->GetFloat();
+ }
+ }
+
+ //-----------------------------------------------------------
+ const char_type* OprtMul::GetDesc() const
+ {
+ return _T("multiplication");
+ }
+
+ //-----------------------------------------------------------
+ IToken* OprtMul::Clone() const
+ {
+ return new OprtMul(*this);
+ }
+
+//-----------------------------------------------------------
+//
+// class OprtDiv
+//
+//-----------------------------------------------------------
+
+
+ OprtDiv::OprtDiv()
+ :IOprtBin(_T("/"), (int)prMUL_DIV, oaLEFT)
+ {}
+
+ //-----------------------------------------------------------
+ /** \brief Implements the Division operator.
+ \throw ParserError in case one of the arguments if
+ nonnumeric or an array.
+
+ */
+ void OprtDiv::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int num)
+ {
+ assert(num==2);
+
+ if (!a_pArg[0]->IsNonComplexScalar())
+ throw ParserError( ErrorContext(ecTYPE_CONFLICT_FUN, -1, GetIdent(), a_pArg[0]->GetType(), 'f', 1));
+
+ if (!a_pArg[1]->IsNonComplexScalar())
+ throw ParserError( ErrorContext(ecTYPE_CONFLICT_FUN, -1, GetIdent(), a_pArg[1]->GetType(), 'f', 2));
+
+ *ret = a_pArg[0]->GetFloat() / a_pArg[1]->GetFloat();
+ }
+
+ //-----------------------------------------------------------
+ const char_type* OprtDiv::GetDesc() const
+ {
+ return _T("division");
+ }
+
+ //-----------------------------------------------------------
+ IToken* OprtDiv::Clone() const
+ {
+ return new OprtDiv(*this);
+ }
+
+//-----------------------------------------------------------
+//
+// class OprtPow
+//
+//-----------------------------------------------------------
+
+ OprtPow::OprtPow()
+ :IOprtBin(_T("^"), (int)prPOW, oaRIGHT)
+ {}
+
+ //-----------------------------------------------------------
+ void OprtPow::Eval(ptr_val_type& ret, const ptr_val_type *arg, int argc)
+ {
+ assert(argc==2);
+ float_type a = arg[0]->GetFloat();
+ float_type b = arg[1]->GetFloat();
+
+ int ib = (int)b;
+ if (b-ib==0)
+ {
+ switch (ib)
+ {
+ case 1: *ret = a; return;
+ case 2: *ret = a*a; return;
+ case 3: *ret = a*a*a; return;
+ case 4: *ret = a*a*a*a; return;
+ case 5: *ret = a*a*a*a*a; return;
+ default: *ret = pow(a, ib); return;
+ }
+ }
+ else
+ *ret = pow(a, b);
+ }
+
+ //-----------------------------------------------------------
+ const char_type* OprtPow::GetDesc() const
+ {
+ return _T("x^y - Raises x to the power of y");
+ }
+
+ //-----------------------------------------------------------
+ IToken* OprtPow::Clone() const
+ {
+ return new OprtPow(*this);
+ }
+}
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpOprtNonCmplx.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpOprtNonCmplx.h Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,126 @@
+/*
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+*/
+#ifndef MP_OPRT_NON_CMPLX_H
+#define MP_OPRT_NON_CMPLX_H
+
+/** \file
+ \brief Definitions of classes used as callbacks for standard binary operators.
+*/
+
+/** \defgroup binop Binary operator callbacks
+
+ This group lists the objects representing the binary operators of muParserX.
+*/
+
+#include <cmath>
+#include "mpIOprt.h"
+#include "mpValue.h"
+#include "mpError.h"
+
+
+MUP_NAMESPACE_START
+
+ //---------------------------------------------------------------------------
+ /** \brief Callback for the negative sign operator for noncomplex values.
+ \ingroup infix
+ */
+ class OprtSign : public IOprtInfix
+ {
+ public:
+ OprtSign();
+ virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc);
+ virtual const char_type* GetDesc() const;
+ virtual IToken* Clone() const;
+ }; // class OprtSign
+
+ //------------------------------------------------------------------------------
+ /** \brief Parser callback for implementing an addition of two noncomplex values.
+ \ingroup binop
+ */
+ class OprtAdd : public IOprtBin
+ {
+ public:
+ OprtAdd();
+ virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int);
+ virtual const char_type* GetDesc() const;
+ virtual IToken* Clone() const;
+ };
+
+ //------------------------------------------------------------------------------
+ /** \brief Parser callback for implementing the subtraction of two noncomplex values.
+ \ingroup binop
+ */
+ class OprtSub : public IOprtBin
+ {
+ public:
+ OprtSub();
+ virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int);
+ virtual const char_type* GetDesc() const;
+ virtual IToken* Clone() const;
+ };
+
+ //------------------------------------------------------------------------------
+ /** \brief Callback object for implementing the multiplications of noncomplex values.
+ \ingroup binop
+ */
+ class OprtMul : public IOprtBin
+ {
+ public:
+ OprtMul();
+ virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int);
+ virtual const char_type* GetDesc() const;
+ virtual IToken* Clone() const;
+ };
+
+ //------------------------------------------------------------------------------
+ /** \brief Callback object for implementing the division of noncomplex values.
+ \ingroup binop
+ */
+ class OprtDiv : public IOprtBin
+ {
+ public:
+ OprtDiv();
+ virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int);
+ virtual const char_type* GetDesc() const;
+ virtual IToken* Clone() const;
+ };
+
+ //------------------------------------------------------------------------------
+ /** \brief Raise x to the power of y.
+ \ingroup binop
+ */
+ class OprtPow : public IOprtBin
+ {
+ public:
+
+ OprtPow();
+
+ virtual void Eval(ptr_val_type& ret, const ptr_val_type *arg, int argc);
+ virtual const char_type* GetDesc() const;
+ virtual IToken* Clone() const;
+ };
+} // namespace mu
+
+#endif
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpPackageCmplx.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpPackageCmplx.cpp Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,71 @@
+#include "mpPackageCmplx.h"
+
+#include "mpParserBase.h"
+#include "mpFuncCmplx.h"
+#include "mpOprtCmplx.h"
+#include "mpOprtBinCommon.h"
+
+MUP_NAMESPACE_START
+
+//------------------------------------------------------------------------------
+std::auto_ptr<PackageCmplx> PackageCmplx::s_pInstance;
+
+//------------------------------------------------------------------------------
+IPackage* PackageCmplx::Instance()
+{
+ if (s_pInstance.get()==NULL)
+ {
+ s_pInstance.reset(new PackageCmplx);
+ }
+
+ return s_pInstance.get();
+}
+
+//------------------------------------------------------------------------------
+void PackageCmplx::AddToParser(ParserXBase *pParser)
+{
+ // Constants
+ pParser->DefineConst( _T("i"), cmplx_type(0.0, 1.0) );
+
+ // Complex valued functions
+ pParser->DefineFun(new FunCmplxReal());
+ pParser->DefineFun(new FunCmplxImag());
+ pParser->DefineFun(new FunCmplxConj());
+ pParser->DefineFun(new FunCmplxArg());
+ pParser->DefineFun(new FunCmplxNorm());
+ pParser->DefineFun(new FunCmplxSin());
+ pParser->DefineFun(new FunCmplxCos());
+ pParser->DefineFun(new FunCmplxTan());
+ pParser->DefineFun(new FunCmplxSinH());
+ pParser->DefineFun(new FunCmplxCosH());
+ pParser->DefineFun(new FunCmplxTanH());
+ pParser->DefineFun(new FunCmplxSqrt());
+ pParser->DefineFun(new FunCmplxExp());
+ pParser->DefineFun(new FunCmplxLn());
+ pParser->DefineFun(new FunCmplxLog());
+ pParser->DefineFun(new FunCmplxLog2());
+ pParser->DefineFun(new FunCmplxLog10());
+ pParser->DefineFun(new FunCmplxAbs());
+
+ // Complex valued operators
+ pParser->DefineOprt(new OprtAddCmplx());
+ pParser->DefineOprt(new OprtSubCmplx());
+ pParser->DefineOprt(new OprtMulCmplx());
+ pParser->DefineOprt(new OprtDivCmplx());
+ pParser->DefineOprt(new OprtPowCmplx());
+ pParser->DefineInfixOprt(new OprtSignCmplx());
+}
+
+//------------------------------------------------------------------------------
+string_type PackageCmplx::GetDesc() const
+{
+ return _T("");
+}
+
+//------------------------------------------------------------------------------
+string_type PackageCmplx::GetPrefix() const
+{
+ return _T("");
+}
+
+MUP_NAMESPACE_END
\ No newline at end of file
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpPackageCmplx.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpPackageCmplx.h Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,31 @@
+#ifndef MU_PACKAGE_CMPLX_H
+#define MU_PACKAGE_CMPLX_H
+
+#include <memory>
+#include "mpIPackage.h"
+#include "mpIOprt.h"
+
+
+MUP_NAMESPACE_START
+
+//------------------------------------------------------------------------------
+/** \brief Package for installing complex functions and operators. */
+class PackageCmplx: public IPackage
+{
+friend class std::auto_ptr<PackageCmplx>;
+
+public:
+
+ static IPackage* Instance();
+ virtual void AddToParser(ParserXBase *pParser);
+ virtual string_type GetDesc() const;
+ virtual string_type GetPrefix() const;
+
+private:
+
+ static std::auto_ptr<PackageCmplx> s_pInstance;
+};
+
+MUP_NAMESPACE_END
+
+#endif
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpPackageCommon.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpPackageCommon.cpp Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,102 @@
+#include "mpPackageCommon.h"
+
+#include "mpParserBase.h"
+#include "mpFuncNonCmplx.h"
+#include "mpFuncCommon.h"
+#include "mpOprtBinCommon.h"
+#include "mpOprtBinAssign.h"
+#include "mpValReader.h"
+
+/** \brief Pi (what else?). */
+#define MUP_CONST_PI 3.141592653589793238462643
+
+/** \brief The eulerian number. */
+#define MUP_CONST_E 2.718281828459045235360287
+
+
+MUP_NAMESPACE_START
+
+//------------------------------------------------------------------------------
+std::auto_ptr<PackageCommon> PackageCommon::s_pInstance;
+
+//------------------------------------------------------------------------------
+IPackage* PackageCommon::Instance()
+{
+ if (s_pInstance.get()==NULL)
+ {
+ s_pInstance.reset(new PackageCommon);
+ }
+
+ return s_pInstance.get();
+}
+
+//------------------------------------------------------------------------------
+void PackageCommon::AddToParser(ParserXBase *pParser)
+{
+ // Readers that need fancy decorations on their values must
+ // be added first (i.e. hex -> "0x...") Otherwise the
+ // zero in 0x will be read as a value of zero!
+ pParser->AddValueReader(new HexValReader());
+ pParser->AddValueReader(new DblValReader());
+ pParser->AddValueReader(new BoolValReader());
+ pParser->AddValueReader(new BinValReader());
+
+ // Constants
+ pParser->DefineConst( _T("pi"), (float_type)MUP_CONST_PI );
+ pParser->DefineConst( _T("e"), (float_type)MUP_CONST_E );
+
+ // Vector
+ pParser->DefineFun(new FunSizeOf());
+
+ // Generic functions
+ pParser->DefineFun(new FunMax());
+ pParser->DefineFun(new FunMin());
+ pParser->DefineFun(new FunSum());
+
+ // misc
+ pParser->DefineFun(new FunParserID());
+
+ // integer package
+ pParser->DefineOprt(new OprtLAnd);
+ pParser->DefineOprt(new OprtLOr);
+ pParser->DefineOprt(new OprtAnd);
+ pParser->DefineOprt(new OprtOr);
+ pParser->DefineOprt(new OprtShr);
+ pParser->DefineOprt(new OprtShl);
+
+ // booloean package
+ pParser->DefineOprt(new OprtLE);
+ pParser->DefineOprt(new OprtGE);
+ pParser->DefineOprt(new OprtLT);
+ pParser->DefineOprt(new OprtGT);
+ pParser->DefineOprt(new OprtEQ);
+ pParser->DefineOprt(new OprtNEQ);
+ pParser->DefineOprt(new OprtBAnd);
+ pParser->DefineOprt(new OprtBOr);
+ pParser->DefineOprt(new OprtBXor);
+
+ // assignement operators
+ pParser->DefineOprt(new OprtAssign);
+ pParser->DefineOprt(new OprtAssignAdd);
+ pParser->DefineOprt(new OprtAssignSub);
+ pParser->DefineOprt(new OprtAssignMul);
+ pParser->DefineOprt(new OprtAssignDiv);
+
+ // infix operators
+ pParser->DefineInfixOprt(new OprtCastToFloat);
+ pParser->DefineInfixOprt(new OprtCastToInt);
+}
+
+//------------------------------------------------------------------------------
+string_type PackageCommon::GetDesc() const
+{
+ return _T("");
+}
+
+//------------------------------------------------------------------------------
+string_type PackageCommon::GetPrefix() const
+{
+ return _T("");
+}
+
+MUP_NAMESPACE_END
\ No newline at end of file
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpPackageCommon.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpPackageCommon.h Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,33 @@
+#ifndef MU_PACKAGE_COMMON_H
+#define MU_PACKAGE_COMMON_H
+
+#include <memory>
+#include "mpIPackage.h"
+#include "mpIOprt.h"
+
+
+MUP_NAMESPACE_START
+
+//------------------------------------------------------------------------------
+/** \brief Package for installing operators and functions which
+ are always present.
+*/
+class PackageCommon: public IPackage
+{
+friend class std::auto_ptr<PackageCommon>;
+
+public:
+
+ static IPackage* Instance();
+ virtual void AddToParser(ParserXBase *pParser);
+ virtual string_type GetDesc() const;
+ virtual string_type GetPrefix() const;
+
+private:
+
+ static std::auto_ptr<PackageCommon> s_pInstance;
+};
+
+MUP_NAMESPACE_END
+
+#endif
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpPackageMatrix.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpPackageMatrix.cpp Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,48 @@
+#include "mpPackageMatrix.h"
+
+#include "mpParserBase.h"
+#include "mpFuncMatrix.h"
+#include "mpOprtMatrix.h"
+
+MUP_NAMESPACE_START
+
+//------------------------------------------------------------------------------
+std::auto_ptr<PackageMatrix> PackageMatrix::s_pInstance;
+
+//------------------------------------------------------------------------------
+IPackage* PackageMatrix::Instance()
+{
+ if (s_pInstance.get()==NULL)
+ {
+ s_pInstance.reset(new PackageMatrix);
+ }
+
+ return s_pInstance.get();
+}
+
+//------------------------------------------------------------------------------
+void PackageMatrix::AddToParser(ParserXBase *pParser)
+{
+ // Matrix functions
+ pParser->DefineFun(new FunMatrixOnes());
+
+ // Matrix Operators
+ pParser->DefinePostfixOprt(new OprtTranspose(this));
+
+ // Colon operator
+ pParser->DefineOprt(new OprtColon());
+}
+
+//------------------------------------------------------------------------------
+string_type PackageMatrix::GetDesc() const
+{
+ return _T("Operators and functions for matrix operations");
+}
+
+//------------------------------------------------------------------------------
+string_type PackageMatrix::GetPrefix() const
+{
+ return _T("");
+}
+
+MUP_NAMESPACE_END
\ No newline at end of file
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpPackageMatrix.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpPackageMatrix.h Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,31 @@
+#ifndef MU_PACKAGE_MATRIX_H
+#define MU_PACKAGE_MATRIX_H
+
+#include <memory>
+#include "mpIPackage.h"
+#include "mpIOprt.h"
+
+
+MUP_NAMESPACE_START
+
+//------------------------------------------------------------------------------
+/** \brief Package for installing complex functions and operators. */
+class PackageMatrix : public IPackage
+{
+friend class std::auto_ptr<PackageMatrix>;
+
+public:
+
+ static IPackage* Instance();
+ virtual void AddToParser(ParserXBase *pParser);
+ virtual string_type GetDesc() const;
+ virtual string_type GetPrefix() const;
+
+private:
+
+ static std::auto_ptr<PackageMatrix> s_pInstance;
+};
+
+MUP_NAMESPACE_END
+
+#endif
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpPackageNonCmplx.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpPackageNonCmplx.cpp Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,69 @@
+#include "mpPackageNonCmplx.h"
+
+#include "mpParserBase.h"
+#include "mpFuncNonCmplx.h"
+#include "mpOprtNonCmplx.h"
+#include "mpOprtBinCommon.h"
+
+
+MUP_NAMESPACE_START
+
+//------------------------------------------------------------------------------
+std::auto_ptr<PackageNonCmplx> PackageNonCmplx::s_pInstance;
+
+//------------------------------------------------------------------------------
+IPackage* PackageNonCmplx::Instance()
+{
+ if (s_pInstance.get()==NULL)
+ {
+ s_pInstance.reset(new PackageNonCmplx);
+ }
+
+ return s_pInstance.get();
+}
+
+//------------------------------------------------------------------------------
+void PackageNonCmplx::AddToParser(ParserXBase *pParser)
+{
+ pParser->DefineFun(new FunSin());
+ pParser->DefineFun(new FunCos());
+ pParser->DefineFun(new FunTan());
+ pParser->DefineFun(new FunSinH());
+ pParser->DefineFun(new FunCosH());
+ pParser->DefineFun(new FunTanH());
+ pParser->DefineFun(new FunASin());
+ pParser->DefineFun(new FunACos());
+ pParser->DefineFun(new FunATan());
+ pParser->DefineFun(new FunASinH());
+ pParser->DefineFun(new FunACosH());
+ pParser->DefineFun(new FunATanH());
+ pParser->DefineFun(new FunLog());
+ pParser->DefineFun(new FunLog10());
+ pParser->DefineFun(new FunLog2());
+ pParser->DefineFun(new FunLn());
+ pParser->DefineFun(new FunExp());
+ pParser->DefineFun(new FunSqrt());
+ pParser->DefineFun(new FunAbs());
+
+ // Operator callbacks
+ pParser->DefineInfixOprt(new OprtSign());
+ pParser->DefineOprt(new OprtAdd());
+ pParser->DefineOprt(new OprtSub());
+ pParser->DefineOprt(new OprtMul());
+ pParser->DefineOprt(new OprtDiv());
+ pParser->DefineOprt(new OprtPow);
+}
+
+//------------------------------------------------------------------------------
+string_type PackageNonCmplx::GetDesc() const
+{
+ return _T("");
+}
+
+//------------------------------------------------------------------------------
+string_type PackageNonCmplx::GetPrefix() const
+{
+ return _T("");
+}
+
+MUP_NAMESPACE_END
\ No newline at end of file
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpPackageNonCmplx.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpPackageNonCmplx.h Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,32 @@
+#ifndef MU_PACKAGE_NON_CMPLX_H
+#define MU_PACKAGE_NON_CMPLX_H
+
+#include <memory>
+#include "mpIPackage.h"
+#include "mpIOprt.h"
+
+
+MUP_NAMESPACE_START
+
+//------------------------------------------------------------------------------
+/** \brief Package for installing complex functions and operators. */
+class PackageNonCmplx: public IPackage
+{
+friend class std::auto_ptr<PackageNonCmplx>;
+
+public:
+
+ static IPackage* Instance();
+
+ virtual void AddToParser(ParserXBase *pParser);
+ virtual string_type GetDesc() const;
+ virtual string_type GetPrefix() const;
+
+private:
+
+ static std::auto_ptr<PackageNonCmplx> s_pInstance;
+};
+
+MUP_NAMESPACE_END
+
+#endif
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpPackageStr.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpPackageStr.cpp Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,50 @@
+#include "mpPackageStr.h"
+
+#include "mpParserBase.h"
+#include "mpFuncStr.h"
+#include "mpOprtBinCommon.h"
+#include "mpValReader.h"
+
+MUP_NAMESPACE_START
+
+//------------------------------------------------------------------------------
+std::auto_ptr<PackageStr> PackageStr::s_pInstance;
+
+//------------------------------------------------------------------------------
+IPackage* PackageStr::Instance()
+{
+ if (s_pInstance.get()==NULL)
+ {
+ s_pInstance.reset(new PackageStr);
+ }
+
+ return s_pInstance.get();
+}
+
+//------------------------------------------------------------------------------
+void PackageStr::AddToParser(ParserXBase *pParser)
+{
+ pParser->AddValueReader(new StrValReader());
+
+ // Functions
+ pParser->DefineFun(new FunStrLen());
+ pParser->DefineFun(new FunStrToDbl());
+ pParser->DefineFun(new FunStrToUpper());
+
+ // Operators
+ pParser->DefineOprt(new OprtStrAdd);
+}
+
+//------------------------------------------------------------------------------
+string_type PackageStr::GetDesc() const
+{
+ return _T("A package for string operations.");
+}
+
+//------------------------------------------------------------------------------
+string_type PackageStr::GetPrefix() const
+{
+ return _T("");
+}
+
+MUP_NAMESPACE_END
\ No newline at end of file
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpPackageStr.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpPackageStr.h Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,32 @@
+#ifndef MU_PACKAGE_STR_H
+#define MU_PACKAGE_STR_H
+
+#include <memory>
+
+#include "mpIPackage.h"
+#include "mpIOprt.h"
+
+
+MUP_NAMESPACE_START
+
+//------------------------------------------------------------------------------
+/** \brief Package for installing unit postfix operators into muParserX. */
+class PackageStr : public IPackage
+{
+friend class std::auto_ptr<PackageStr>;
+
+public:
+
+ static IPackage* Instance();
+ virtual void AddToParser(ParserXBase *pParser);
+ virtual string_type GetDesc() const;
+ virtual string_type GetPrefix() const;
+
+private:
+
+ static std::auto_ptr<PackageStr> s_pInstance;
+};
+
+MUP_NAMESPACE_END
+
+#endif
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpPackageUnit.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpPackageUnit.cpp Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,89 @@
+#include "mpPackageUnit.h"
+
+#include "mpParserBase.h"
+
+
+MUP_NAMESPACE_START
+
+/** \brief This is a macro for defining scaling postfix operators.
+
+ These operators can be used for unit conversions.
+*/
+#define MUP_POSTFIX_IMLP(CLASS, IDENT, MUL, DESC) \
+ CLASS::CLASS(IPackage *pPackage) \
+ :IOprtPostfix(_T(IDENT)) \
+ {} \
+ \
+ void CLASS::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int) \
+ { \
+ if (!a_pArg[0]->IsScalar()) \
+ { \
+ ErrorContext err(ecTYPE_CONFLICT, \
+ GetExprPos(), \
+ a_pArg[0]->ToString(), \
+ a_pArg[0]->GetType(), \
+ 'c', \
+ 1); \
+ throw ParserError(err); \
+ } \
+ \
+ *ret = a_pArg[0]->GetComplex() * MUL; \
+ } \
+ \
+ const char_type* CLASS::GetDesc() const \
+ { \
+ return _T(DESC); \
+ } \
+ \
+ IToken* CLASS::Clone() const \
+ { \
+ return new CLASS(*this); \
+ }
+
+ MUP_POSTFIX_IMLP(OprtNano, "{n}", (float_type)1e-9, "{n} - unit multiplicator 1e-9")
+ MUP_POSTFIX_IMLP(OprtMicro, "{mu}", (float_type)1e-6, "{µ} - unit multiplicator 1e-6")
+ MUP_POSTFIX_IMLP(OprtMilli, "{m}", (float_type)1e-3, "{m} - unit multiplicator 1e-3")
+ MUP_POSTFIX_IMLP(OprtKilo, "{k}", (float_type)1e3, "{k} - unit multiplicator 1e3")
+ MUP_POSTFIX_IMLP(OprtMega, "{M}", (float_type)1e6, "{M} - unit multiplicator 1e6")
+ MUP_POSTFIX_IMLP(OprtGiga, "{G}", (float_type)1e9, "{G} - unit multiplicator 1e9")
+
+#undef MUP_POSTFIX_IMLP
+
+//------------------------------------------------------------------------------
+std::auto_ptr<PackageUnit> PackageUnit::s_pInstance;
+
+//------------------------------------------------------------------------------
+IPackage* PackageUnit::Instance()
+{
+ if (s_pInstance.get()==NULL)
+ {
+ s_pInstance.reset(new PackageUnit);
+ }
+
+ return s_pInstance.get();
+}
+
+//------------------------------------------------------------------------------
+void PackageUnit::AddToParser(ParserXBase *pParser)
+{
+ pParser->DefinePostfixOprt(new OprtNano(this));
+ pParser->DefinePostfixOprt(new OprtMicro(this));
+ pParser->DefinePostfixOprt(new OprtMilli(this));
+ pParser->DefinePostfixOprt(new OprtKilo(this));
+ pParser->DefinePostfixOprt(new OprtMega(this));
+ pParser->DefinePostfixOprt(new OprtGiga(this));
+}
+
+//------------------------------------------------------------------------------
+string_type PackageUnit::GetDesc() const
+{
+ return _T("Postfix operators for basic unit conversions.");
+}
+
+//------------------------------------------------------------------------------
+string_type PackageUnit::GetPrefix() const
+{
+ return _T("");
+}
+
+MUP_NAMESPACE_END
\ No newline at end of file
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpPackageUnit.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpPackageUnit.h Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,49 @@
+#ifndef MU_PACKAGE_UNIT_H
+#define MU_PACKAGE_UNIT_H
+
+#include <memory>
+#include "mpIPackage.h"
+#include "mpIOprt.h"
+
+MUP_NAMESPACE_START
+
+#define MUP_POSTFIX_DEF(CLASS) \
+ class CLASS : public IOprtPostfix \
+ { \
+ public: \
+ CLASS(IPackage* pPackage=NULL); \
+ virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc); \
+ virtual const char_type* GetDesc() const; \
+ virtual IToken* Clone() const; \
+ };
+
+MUP_POSTFIX_DEF(OprtNano)
+MUP_POSTFIX_DEF(OprtMicro)
+MUP_POSTFIX_DEF(OprtMilli)
+MUP_POSTFIX_DEF(OprtKilo)
+MUP_POSTFIX_DEF(OprtMega)
+MUP_POSTFIX_DEF(OprtGiga)
+
+#undef MUP_POSTFIX_DEF
+
+//------------------------------------------------------------------------------
+/** \brief Package for installing unit postfix operators into muParserX. */
+class PackageUnit : public IPackage
+{
+friend class std::auto_ptr<PackageUnit>;
+
+public:
+
+ static IPackage* Instance();
+ virtual void AddToParser(ParserXBase *pParser);
+ virtual string_type GetDesc() const;
+ virtual string_type GetPrefix() const;
+
+private:
+
+ static std::auto_ptr<PackageUnit> s_pInstance;
+};
+
+MUP_NAMESPACE_END
+
+#endif
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpParser.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpParser.cpp Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,77 @@
+/*
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+*/
+#include "mpParser.h"
+
+//--- Standard includes ----------------------------------------------------
+#include <cmath>
+#include <algorithm>
+#include <numeric>
+
+//--- Parser framework -----------------------------------------------------
+#include "mpPackageUnit.h"
+#include "mpPackageStr.h"
+#include "mpPackageCmplx.h"
+#include "mpPackageNonCmplx.h"
+#include "mpPackageCommon.h"
+#include "mpPackageMatrix.h"
+
+using namespace std;
+
+
+/** \brief Namespace for mathematical applications. */
+MUP_NAMESPACE_START
+
+ //---------------------------------------------------------------------------
+ /** \brief Default constructor.
+
+ Call ParserXBase class constructor and initiate function, operator
+ and constant initialization.
+ */
+ ParserX::ParserX(EPackages ePackages)
+ :ParserXBase()
+ {
+ DefineNameChars(_T("0123456789_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"));
+ DefineOprtChars(_T("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+-*^/?<>=#!$%&|~'_µ{}"));
+ DefineInfixOprtChars(_T("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ()/+-*^?<>=#!$%&|~'_"));
+
+ if (ePackages & pckUNIT)
+ AddPackage(PackageUnit::Instance());
+
+ if (ePackages & pckSTRING)
+ AddPackage(PackageStr::Instance());
+
+ if (ePackages & pckCOMPLEX)
+ AddPackage(PackageCmplx::Instance());
+
+ if (ePackages & pckNON_COMPLEX)
+ AddPackage(PackageNonCmplx::Instance());
+
+ if (ePackages & pckCOMMON)
+ AddPackage(PackageCommon::Instance());
+
+ if (ePackages & pckMATRIX)
+ AddPackage(PackageMatrix::Instance());
+ }
+} // namespace mu
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpParser.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpParser.h Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,53 @@
+/** \file
+ \brief Definition of the parser class
+
+<pre>
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+</pre>
+*/
+#ifndef MUP_PARSERX_H
+#define MUP_PARSERX_H
+
+//--- Parser framework -----------------------------------------------------
+#include "mpDefines.h"
+#include "mpParserBase.h"
+
+
+MUP_NAMESPACE_START
+
+/** \brief The parser implementation.
+ \sa ParserXBase
+
+ This is the class that implements the parser. It installs all functions
+ and operatore and defines the constants.
+ */
+ class ParserX : public ParserXBase
+ {
+ public:
+ ParserX(EPackages ePackages = pckALL_COMPLEX);
+ };
+} // namespace mu
+
+#endif
+
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpParserBase.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpParserBase.cpp Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,1331 @@
+/** \file
+ \brief Implementation of the muParserX engine.
+
+<pre>
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+</pre>
+*/
+#include "mpParserBase.h"
+
+#include <cassert>
+#include <cmath>
+#include <memory>
+#include <vector>
+#include <sstream>
+
+#include "utGeneric.h"
+#include "mpDefines.h"
+#include "mpIfThenElse.h"
+#include "mpScriptTokens.h"
+
+using namespace std;
+
+
+MUP_NAMESPACE_START
+
+ //------------------------------------------------------------------------------
+ const char_type *g_sCmdCode[] = { _T("BRCK. OPEN "),
+ _T("BRCK. CLOSE "),
+ _T("IDX OPEN "),
+ _T("IDX CLOSE "),
+ _T("ARG_SEP "),
+ _T("IF "),
+ _T("ELSE "),
+ _T("ENDIF "),
+ _T("JMP "),
+ _T("VAR "),
+ _T("VAL "),
+ _T("FUNC "),
+ _T("OPRT_BIN "),
+ _T("OPRT_IFX "),
+ _T("OPRT_PFX "),
+ _T("END "),
+ _T("SCRIPT_GOTO "),
+ _T("SCRIPT_LABEL "),
+ _T("SCRIPT_FOR "),
+ _T("SCRIPT_IF "),
+ _T("SCRIPT_ELSE "),
+ _T("SCRIPT_ELSEIF "),
+ _T("SCRIPT_ENDIF "),
+ _T("SCRIPT_NEWLINE "),
+ _T("SCRIPT_FUNCTION"),
+ _T("UNKNOWN ") };
+
+ //------------------------------------------------------------------------------
+ bool ParserXBase::s_bDumpStack = false;
+ bool ParserXBase::s_bDumpRPN = false;
+
+ //------------------------------------------------------------------------------
+ /** \brief Identifiers for built in binary operators.
+
+ When defining custom binary operators with AddOprt(...) make sure not to choose
+ names conflicting with these definitions.
+ */
+ const char_type* ParserXBase::c_DefaultOprt[] = { _T("("),
+ _T(")"),
+ _T("["),
+ _T("]"),
+ _T(","),
+ _T("?"),
+ _T(":"),
+ 0 };
+
+ //------------------------------------------------------------------------------
+ /** \brief Default constructor. */
+ ParserXBase::ParserXBase()
+ :m_pParserEngine(&ParserXBase::ParseFromString)
+ ,m_pTokenReader()
+ ,m_FunDef()
+ ,m_PostOprtDef()
+ ,m_InfixOprtDef()
+ ,m_OprtDef()
+ ,m_valConst()
+ ,m_valDynVarShadow()
+ ,m_VarDef()
+ ,m_sNameChars()
+ ,m_sOprtChars()
+ ,m_sInfixOprtChars()
+ ,m_nFinalResultIdx(0)
+ ,m_bIsQueryingExprVar(false)
+ ,m_bAutoCreateVar(false)
+ ,m_rpn()
+ ,m_vStackBuffer()
+ {
+ InitTokenReader();
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Copy constructor.
+ \param a_Parser Reference to the other parser object
+
+ Implemented by calling Assign(a_Parser)
+ */
+ ParserXBase::ParserXBase(const ParserXBase &a_Parser)
+ :m_pParserEngine(&ParserXBase::ParseFromString)
+ ,m_pTokenReader()
+ ,m_FunDef()
+ ,m_PostOprtDef()
+ ,m_InfixOprtDef()
+ ,m_OprtDef()
+ ,m_valConst()
+ ,m_valDynVarShadow()
+ ,m_VarDef()
+ ,m_sNameChars()
+ ,m_sOprtChars()
+ ,m_sInfixOprtChars()
+ ,m_nFinalResultIdx(0)
+ ,m_bAutoCreateVar()
+ ,m_rpn()
+ ,m_vStackBuffer()
+ {
+ m_pTokenReader.reset(new TokenReader(this));
+ Assign(a_Parser);
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Destructor.
+ \throw nothrow
+ */
+ ParserXBase::~ParserXBase()
+ {
+ // It is important to release the stack buffer before
+ // releasing the value cache. Since it may contain
+ // Values referencing the cache.
+ m_vStackBuffer.clear();
+ m_cache.ReleaseAll();
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Assignement operator.
+ \param a_Parser Object to copy to this.
+ \return *this
+ \throw nothrow
+
+ Implemented by calling Assign(a_Parser). Self assignement is suppressed.
+ */
+ ParserXBase& ParserXBase::operator=(const ParserXBase &a_Parser)
+ {
+ Assign(a_Parser);
+ return *this;
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Copy state of a parser object to this.
+ \param a_Parser the source object.
+
+ Clears Variables and Functions of this parser.
+ Copies the states of all internal variables.
+ Resets parse function to string parse mode.
+ */
+ void ParserXBase::Assign(const ParserXBase &ref)
+ {
+ if (&ref==this)
+ return;
+
+ // Don't copy bytecode instead cause the parser to create new bytecode
+ // by resetting the parse function.
+ ReInit();
+
+ m_pTokenReader.reset(ref.m_pTokenReader->Clone(this));
+
+ m_OprtDef = ref.m_OprtDef;
+ m_FunDef = ref.m_FunDef;
+ m_PostOprtDef = ref.m_PostOprtDef;
+ m_InfixOprtDef = ref.m_InfixOprtDef;
+ m_valConst = ref.m_valConst;
+ m_valDynVarShadow = ref.m_valDynVarShadow;
+ m_VarDef = ref.m_VarDef; // Copy user defined variables
+ m_nFinalResultIdx = ref.m_nFinalResultIdx;
+
+ // Copy charsets
+ m_sNameChars = ref.m_sNameChars;
+ m_sOprtChars = ref.m_sOprtChars;
+ m_sInfixOprtChars = ref.m_sInfixOprtChars;
+
+ m_bAutoCreateVar = ref.m_bAutoCreateVar;
+
+ // Things that should not be copied:
+ // - m_vStackBuffer
+ // - m_cache
+ // - m_rpn
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Evaluate the expression.
+ \pre A formula must be set.
+ \pre Variables must have been set (if needed)
+ \sa SetExpr
+ \return The evaluation result
+ \throw ParseException if no Formula is set or in case of any other error related to the formula.
+
+ 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 GetExprVar is non const because it explicitely calls Eval() forcing this update.
+ */
+ const IValue& ParserXBase::Eval() const
+ {
+ return (this->*m_pParserEngine)();
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Return the strings of all Operator identifiers.
+ \return Returns a pointer to the c_DefaultOprt array of const char *.
+ \throw nothrow
+
+ GetOprt is a const function returning a pinter to an array of const char pointers.
+ */
+ const char_type** ParserXBase::GetOprtDef() const
+ {
+ return (const char_type **)(&c_DefaultOprt[0]);
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Define the set of valid characters to be used in names of
+ functions, variables, constants.
+ */
+ void ParserXBase::DefineNameChars(const char_type *a_szCharset)
+ {
+ m_sNameChars = a_szCharset;
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Define the set of valid characters to be used in names of
+ binary operators and postfix operators.
+ \param a_szCharset A string containing all characters that can be used
+ in operator identifiers.
+ */
+ void ParserXBase::DefineOprtChars(const char_type *a_szCharset)
+ {
+ m_sOprtChars = a_szCharset;
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Define the set of valid characters to be used in names of
+ infix operators.
+ \param a_szCharset A string containing all characters that can be used
+ in infix operator identifiers.
+ */
+ void ParserXBase::DefineInfixOprtChars(const char_type *a_szCharset)
+ {
+ m_sInfixOprtChars = a_szCharset;
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Virtual function that defines the characters allowed in name identifiers.
+ \sa #ValidOprtChars, #ValidPrefixOprtChars
+ */
+ const char_type* ParserXBase::ValidNameChars() const
+ {
+ assert(m_sNameChars.size());
+ return m_sNameChars.c_str();
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Virtual function that defines the characters allowed in operator definitions.
+ \sa #ValidNameChars, #ValidPrefixOprtChars
+ */
+ const char_type* ParserXBase::ValidOprtChars() const
+ {
+ assert(m_sOprtChars.size());
+ return m_sOprtChars.c_str();
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Virtual function that defines the characters allowed in infix operator definitions.
+ \sa #ValidNameChars, #ValidOprtChars
+ */
+ const char_type* ParserXBase::ValidInfixOprtChars() const
+ {
+ assert(m_sInfixOprtChars.size());
+ return m_sInfixOprtChars.c_str();
+ }
+
+
+ //---------------------------------------------------------------------------
+ /** \brief Initialize the token reader.
+ \post m_pTokenReader.Get()!=0
+ \throw nothrow
+
+ Create new token reader object and submit pointers to function, operator,
+ constant and variable definitions.
+ */
+ void ParserXBase::InitTokenReader()
+ {
+ m_pTokenReader.reset(new TokenReader(this));
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Reset parser to string parsing mode and clear internal buffers.
+ \throw nothrow
+
+ Resets the token reader.
+ */
+ void ParserXBase::ReInit() const
+ {
+ m_pParserEngine = &ParserXBase::ParseFromString;
+ m_pTokenReader->ReInit();
+ m_rpn.Reset();
+ m_vStackBuffer.clear();
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Adds a new package to the parser.
+
+ The parser becomes the owner of the package pointer and is responsible for
+ its deletion.
+ */
+ void ParserXBase::AddPackage(IPackage *p)
+ {
+ p->AddToParser(this);
+ }
+
+ //---------------------------------------------------------------------------
+ void ParserXBase::RemovePackage(IPackage *p)
+ {
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Add a value reader object to muParserX.
+ \param a_pReader Pointer to the value reader object.
+ */
+ void ParserXBase::AddValueReader(IValueReader *a_pReader)
+ {
+ m_pTokenReader->AddValueReader(a_pReader);
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Check if a given name contains invalid characters.
+ \param a_strName The name to check
+ \param a_szCharSet The characterset
+ \throw ParserException if the name contains invalid charakters.
+ */
+ void ParserXBase::CheckName(const string_type &a_strName,
+ const string_type &a_szCharSet) const
+ {
+ if ( !a_strName.length() ||
+ (a_strName.find_first_not_of(a_szCharSet)!=string_type::npos) ||
+ (a_strName[0]>=(char_type)'0' && a_strName[0]<=(char_type)'9'))
+ {
+ Error(ecINVALID_NAME);
+ }
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Set the mathematical expression.
+ \param a_sExpr String with the expression
+ \throw ParserException in case of syntax errors.
+
+ Triggers first time calculation thus the creation of the bytecode and
+ scanning of used variables.
+ */
+ void ParserXBase::SetExpr(const string_type &a_sExpr)
+ {
+ m_pTokenReader->SetExpr(a_sExpr);
+ ReInit();
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Add a user defined operator.
+ \post Will reset the Parser to string parsing mode.
+ \param a_pOprt Pointer to a unary postfix operator object. The parser will
+ become the new owner of this object hence will destroy it.
+ */
+ void ParserXBase::DefinePostfixOprt(IOprtPostfix *a_pOprt)
+ {
+ m_PostOprtDef[a_pOprt->GetIdent()] = ptr_tok_type(a_pOprt);
+ ReInit();
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Add a user defined operator.
+ \param a_pOprt Pointer to a unary postfix operator object. The parser will
+ become the new owner of this object hence will destroy it.
+ */
+ void ParserXBase::DefineInfixOprt(IOprtInfix *a_pOprt)
+ {
+ m_InfixOprtDef[a_pOprt->GetIdent()] = ptr_tok_type(a_pOprt);
+ ReInit();
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Add a user defined variable.
+ \param a_sName The variable name
+ \param a_Var The variable to be added to muParserX
+ */
+ void ParserXBase::DefineVar(const string_type &a_sName, const Variable &a_Var)
+ {
+ CheckName(a_sName, ValidNameChars());
+ m_VarDef[a_sName] = ptr_tok_type( a_Var.Clone() );
+ ReInit();
+ }
+
+
+ //---------------------------------------------------------------------------
+ /** \brief Define a parser Constant.
+ \param a_sName The name of the constant
+ \param a_Val Const reference to the constants value
+
+ Parser constants are handed over by const reference as opposed to variables
+ which are handed over by reference. Consequently the parser can not change
+ their value.
+ */
+ void ParserXBase::DefineConst(const string_type &a_sName, const Value &a_Val)
+ {
+ CheckName(a_sName, ValidNameChars());
+ m_valConst[a_sName] = ptr_tok_type( a_Val.Clone() );
+ ReInit();
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Add a callback object to the parser.
+ \param a_pFunc Pointer to the intance of a parser callback object
+ representing the function.
+ \sa GetFunDef, functions
+
+ The parser takes ownership over the callback object.
+ */
+ void ParserXBase::DefineFun(ICallback *a_pFunc)
+ {
+ a_pFunc->SetParent(this);
+ m_FunDef[ a_pFunc->GetIdent() ] = ptr_tok_type(a_pFunc);
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Define a binara operator.
+ \param a_pCallback Pointer to the callback object
+ */
+ void ParserXBase::DefineOprt(IOprtBin *a_pCallback)
+ {
+ a_pCallback->SetParent(this);
+ m_OprtDef.insert(make_pair(a_pCallback->GetIdent(), ptr_tok_type(a_pCallback)));
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Return a map containing the used variables only. */
+ const var_maptype& ParserXBase::GetExprVar() const
+ {
+ utils::scoped_setter<bool> guard2(m_bIsQueryingExprVar, true);
+
+ // Create RPN, but do not compute the result or switch to RPN
+ // parsing mode. The expression may contain yet to be defined variables.
+ CreateRPN();
+ return m_pTokenReader->GetUsedVar();
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Return a map containing the used variables only. */
+ const var_maptype& ParserXBase::GetVar() const
+ {
+ return m_VarDef;
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Return a map containing all parser constants. */
+ const val_maptype& ParserXBase::GetConst() const
+ {
+ return m_valConst;
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Return prototypes of all parser functions.
+ \return #m_FunDef
+ \sa FunProt, functions
+ \throw nothrow
+
+ The return type is a map of the public type #funmap_type containing the prototype
+ definitions for all numerical parser functions. String functions are not part of
+ this map. The Prototype definition is encapsulated in objects of the class FunProt
+ one per parser function each associated with function names via a map construct.
+ */
+ const fun_maptype& ParserXBase::GetFunDef() const
+ {
+ return m_FunDef;
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Retrieve the mathematical expression. */
+ const string_type& ParserXBase::GetExpr() const
+ {
+ return m_pTokenReader->GetExpr();
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Get the version number of muParserX.
+ \return A string containing the version number of muParserX.
+ */
+ string_type ParserXBase::GetVersion()
+ {
+ return MUP_PARSER_VERSION;
+ }
+
+ //---------------------------------------------------------------------------
+ void ParserXBase::ApplyRemainingOprt(Stack<ptr_tok_type> &stOpt,
+ Stack<ptr_val_type> &stVal) const
+
+
+ {
+ while (stOpt.size() &&
+ stOpt.top()->GetCode() != cmBO &&
+ stOpt.top()->GetCode() != cmIO &&
+ stOpt.top()->GetCode() != cmIF)
+ {
+ ptr_tok_type &op = stOpt.top();
+
+ switch(op->GetCode())
+ {
+ case cmOPRT_BIN:
+ MUP_ASSERT(stOpt.top()->GetCode()==cmOPRT_BIN);
+ ApplyFunc(stOpt, stVal, 2);
+ break;
+
+ case cmELSE:
+ ApplyIfElse(stOpt, stVal);
+ break;
+
+ default:
+ Error(ecINTERNAL_ERROR);
+ } // switch operator token type
+ } // While operator stack not empty
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Calls a parser function with its corresponding arguments.
+ \param a_stOpt The operator stack
+ \param a_stVal The value stack
+ \param a_iArgCount The number of function arguments
+ */
+ void ParserXBase::ApplyFunc(Stack<ptr_tok_type> &a_stOpt,
+ Stack<ptr_val_type> &a_stVal,
+ int a_iArgCount) const
+ {
+ if (a_stOpt.empty())
+ return;
+
+ ptr_tok_type tok = a_stOpt.pop();
+ ICallback *pFun = tok->AsICallback();
+
+ int iArgCount = (pFun->GetArgc()>=0) ? pFun->GetArgc() : a_iArgCount;
+ int iOffset = a_stVal.size() - iArgCount;
+ MUP_ASSERT(iOffset>=0);
+
+ // The paramater stack may be empty since functions may not
+ // have a parameter. They do always have a return value though.
+ // If the param stack is empty create an entry for the function
+ // return value.
+ if (iArgCount==0)
+ a_stVal.push(ptr_val_type(new Value()));
+
+ MUP_ASSERT((std::size_t)iOffset<a_stVal.size());
+ ptr_val_type *pArg = a_stVal.get_data() + iOffset;
+
+ //if (pFun->GetArgc()==0)
+ // a_stVal.push(ptr_val_type(new Value()));
+
+ //ptr_val_type *pArg = a_stVal.get_data() + iOffset;
+
+ try
+ {
+ // Make sure to pass on a volatile flag to the function result
+ bool bResultIsVolatile = false;
+ for (int i=0; i<iArgCount && bResultIsVolatile==false; ++i)
+ {
+ if (pArg[i]->IsFlagSet(IToken::flVOLATILE))
+ bResultIsVolatile = true;
+ }
+
+ // Instead of evaluating the function merely a dummy value of the same type as the function return value
+ // is created
+ *pArg = ptr_val_type(new Value());
+ pFun->SetNumArgsPresent(iArgCount);
+
+ if (bResultIsVolatile)
+ (*pArg)->AddFlags(IToken::flVOLATILE);
+
+ m_rpn.Add(tok);
+ }
+ catch(ParserError &e)
+ {
+ // This are type related errors caused by undefined
+ // variables. They must be ignored if the parser is
+ // just checking the presence of expression variables
+ if (!m_bIsQueryingExprVar)
+ {
+ ErrorContext &err = e.GetContext();
+ err.Pos = m_pTokenReader->GetPos();
+ err.Expr = m_pTokenReader->GetExpr();
+
+ if (err.Ident.empty())
+ err.Ident = pFun->GetIdent();
+
+ throw;
+ }
+ }
+
+ if (iArgCount>0)
+ a_stVal.pop(iArgCount-1); // remove the arguments
+ }
+
+ //---------------------------------------------------------------------------
+ void ParserXBase::ApplyIfElse(Stack<ptr_tok_type> &a_stOpt,
+ Stack<ptr_val_type> &a_stVal) const
+ {
+ while (a_stOpt.size() && a_stOpt.top()->GetCode()==cmELSE)
+ {
+ MUP_ASSERT(a_stOpt.size()>0);
+ MUP_ASSERT(a_stVal.size()>=3);
+ MUP_ASSERT(a_stOpt.top()->GetCode()==cmELSE);
+
+ IToken &tokElse = *(a_stOpt.top().Get());
+
+ // it then else is a ternary operator Pop all three values from the value
+ // stack and just return the right value
+ ptr_val_type vVal2 = a_stVal.pop();
+ ptr_val_type vVal1 = a_stVal.pop();
+ ptr_val_type bExpr = a_stVal.pop();
+
+ // Push a dummy value of the correct type
+ a_stVal.push(ptr_val_type(new Value(/*cType*/)));
+
+ // Pass on volatile flags
+ if (vVal1->IsFlagSet(IToken::flVOLATILE) || vVal2->IsFlagSet(IToken::flVOLATILE))
+ a_stVal.top()->AddFlags(IToken::flVOLATILE);
+
+ ptr_tok_type opElse = a_stOpt.pop();
+ ptr_tok_type opIf = a_stOpt.pop();
+ MUP_ASSERT(opElse->GetCode()==cmELSE)
+ MUP_ASSERT(opIf->GetCode()==cmIF)
+
+ m_rpn.Add(ptr_tok_type(new TokenIfThenElse(cmENDIF)));
+ }
+ }
+
+ //---------------------------------------------------------------------------
+ void ParserXBase::DumpRPN() const
+ {
+ m_rpn.AsciiDump();
+ }
+
+ //---------------------------------------------------------------------------
+ void ParserXBase::CreateRPN() const
+ {
+ if (!m_pTokenReader->GetExpr().length())
+ Error(ecUNEXPECTED_EOF, 0);
+
+ // The Stacks take the ownership over the tokens
+ Stack<ptr_tok_type> stOpt;
+ Stack<ptr_val_type> stVal;
+ Stack<ICallback*> stFunc;
+ Stack<int> stArgCount;
+ Stack<int> stIdxCount;
+ ptr_tok_type pTok, pTokPrev;
+ Value val;
+
+ ReInit();
+
+ // The outermost counter counts the number of seperated items
+ // such as in "a=10,b=20,c=c+a"
+ stArgCount.push(1);
+
+ for(bool bLoop=true; bLoop;)
+ {
+ pTokPrev = pTok;
+ pTok = m_pTokenReader->ReadNextToken();
+
+#if defined(MUP_DUMP_TOKENS)
+ cout << pTok->AsciiDump() << endl;
+#endif
+ ECmdCode eCmd = pTok->GetCode();
+ switch (eCmd)
+ {
+ case cmVAR:
+ case cmVAL:
+ {
+ IValue *pVal = pTok->AsIValue();
+ if (stFunc.empty() && pVal->GetType()=='n')
+ {
+ ErrorContext err;
+ err.Errc = ecUNEXPECTED_PARENS;
+ err.Ident = _T(")");
+ err.Pos = pTok->GetExprPos();
+ throw ParserError(err);
+ }
+
+ stVal.push( ptr_val_type(pVal) );
+
+ // Arrays can't be added directly to the reverse polish notation
+ // since there may be an index operator following next...
+ m_rpn.Add(pTok);
+
+ // Apply infix operator if existant
+ if (stOpt.size() && stOpt.top()->GetCode()==cmOPRT_INFIX)
+ ApplyFunc(stOpt, stVal, 1);
+ }
+ break;
+
+ case cmIC:
+ {
+ // The argument count for parameterless functions is zero
+ // by default an opening bracket sets parameter count to 1
+ // in preparation of arguments to come. If the last token
+ // was an opening bracket we know better...
+ if (pTokPrev.Get()!=NULL && pTokPrev->GetCode()==cmIO)
+ --stArgCount.top();
+
+ ApplyRemainingOprt(stOpt, stVal);
+
+ // if opt is "]" and opta is "[" the bracket content has been evaluated.
+ // Now its time to check if there is either a function or a sign pending.
+ // - Neither the opening nor the closing bracket will be pushed back to
+ // the operator stack
+ // - Check if a function is standing in front of the opening bracket,
+ // if so evaluate it afterwards to apply an infix operator.
+ if ( stOpt.size() && stOpt.top()->GetCode()==cmIO )
+ {
+ //
+ // Find out how many dimensions were used in the index operator.
+ //
+ std::size_t iArgc = stArgCount.pop();
+
+ stOpt.pop(); // Take opening bracket from stack
+
+ IOprtIndex *pOprtIndex = pTok->AsIOprtIndex();
+ MUP_ASSERT(pOprtIndex!=NULL);
+
+ pOprtIndex->SetNumArgsPresent(iArgc);
+ m_rpn.Add(pTok);
+
+ // Pop the index values from the stack
+ MUP_ASSERT(stVal.size()>=iArgc+1);
+ for (std::size_t i=0; i<iArgc; ++i)
+ stVal.pop();
+
+ // Now i would need to pop the topmost value from the stack, apply the index
+ // opertor and push the result back to the stack. But here we are just creating the
+ // RPN and are working with dummy values anyway so i just mark the topmost value as
+ // volatile and leave it were it is. The real index logic is in the RPN evaluator...
+ stVal.top()->AddFlags(IToken::flVOLATILE);
+ } // if opening index bracket is on top of operator stack
+ }
+ break;
+
+ case cmBC:
+ {
+ // The argument count for parameterless functions is zero
+ // by default an opening bracket sets parameter count to 1
+ // in preparation of arguments to come. If the last token
+ // was an opening bracket we know better...
+ if (pTokPrev.Get()!=NULL && pTokPrev->GetCode()==cmBO)
+ --stArgCount.top();
+
+ ApplyRemainingOprt(stOpt, stVal);
+
+ // if opt is ")" and opta is "(" the bracket content has been evaluated.
+ // Now its time to check if there is either a function or a sign pending.
+ // - Neither the opening nor the closing bracket will be pushed back to
+ // the operator stack
+ // - Check if a function is standing in front of the opening bracket,
+ // if so evaluate it afterwards to apply an infix operator.
+ if ( stOpt.size() && stOpt.top()->GetCode()==cmBO )
+ {
+ //
+ // Here is the stuff to evaluate a function token
+ //
+ int iArgc = stArgCount.pop();
+
+ stOpt.pop(); // Take opening bracket from stack
+ if ( stOpt.empty() )
+ break;
+
+ if ( (stOpt.top()->GetCode()!=cmFUNC) && (stOpt.top()->GetCode()!=cmOPRT_INFIX) )
+ break;
+
+ ICallback *pFun = stOpt.top()->AsICallback();
+ stFunc.pop();
+
+ if (pFun->GetArgc()!=-1 && iArgc > pFun->GetArgc())
+ Error(ecTOO_MANY_PARAMS, pTok->GetExprPos(), pFun);
+
+ if (iArgc < pFun->GetArgc())
+ Error(ecTOO_FEW_PARAMS, pTok->GetExprPos(), pFun);
+
+ // Evaluate the function
+ ApplyFunc(stOpt, stVal, iArgc);
+
+ // Apply an infix operator, if present
+ if (stOpt.size() && stOpt.top()->GetCode()==cmOPRT_INFIX)
+ ApplyFunc(stOpt, stVal, 1);
+ }
+ }
+ break;
+
+ case cmELSE:
+ ApplyRemainingOprt(stOpt, stVal);
+ m_rpn.Add(pTok);
+ stOpt.push(pTok);
+ break;
+
+ case cmSCRIPT_NEWLINE:
+ {
+ ApplyRemainingOprt(stOpt, stVal);
+
+ // Value stack plätten
+ // Stack der RPN um die Anzahl im stack enthaltener Werte zurück setzen
+ int n = stVal.size();
+ m_rpn.AddNewline(pTok, n);
+ stVal.clear();
+ stOpt.clear();
+ }
+ break;
+
+ case cmARG_SEP:
+ if (stArgCount.empty())
+ Error(ecUNEXPECTED_COMMA, m_pTokenReader->GetPos());
+
+ ++stArgCount.top();
+
+ //if (stVal.size()) // increase argument counter
+ // stArgCount.top()++;
+
+ ApplyRemainingOprt(stOpt, stVal);
+ break;
+
+ case cmEOE:
+ ApplyRemainingOprt(stOpt, stVal);
+ m_rpn.Finalize();
+ break;
+
+ case cmIF:
+ case cmOPRT_BIN:
+ {
+ while ( stOpt.size() &&
+ stOpt.top()->GetCode() != cmBO &&
+ stOpt.top()->GetCode() != cmIO &&
+ stOpt.top()->GetCode() != cmELSE &&
+ stOpt.top()->GetCode() != cmIF)
+ {
+ IToken *pOprt1 = stOpt.top().Get();
+ IToken *pOprt2 = pTok.Get();
+ MUP_ASSERT(pOprt1 && pOprt2);
+ MUP_ASSERT(pOprt1->AsIPrecedence() && pOprt2->AsIPrecedence());
+
+ int nPrec1 = pOprt1->AsIPrecedence()->GetPri(),
+ nPrec2 = pOprt2->AsIPrecedence()->GetPri();
+
+ if (pOprt1->GetCode()==pOprt2->GetCode())
+ {
+ // Deal with operator associativity
+ EOprtAsct eOprtAsct = pOprt1->AsIPrecedence()->GetAssociativity();
+ if ( (eOprtAsct==oaRIGHT && (nPrec1 <= nPrec2)) ||
+ (eOprtAsct==oaLEFT && (nPrec1 < nPrec2)) )
+ {
+ break;
+ }
+ }
+ else if (nPrec1 < nPrec2)
+ {
+ break;
+ }
+
+ // apply the operator now
+ // (binary operators are identic to functions with two arguments)
+ ApplyFunc(stOpt, stVal, 2);
+ } // while ( ... )
+
+ if (pTok->GetCode()==cmIF)
+ m_rpn.Add(pTok);
+
+ stOpt.push(pTok);
+ }
+ break;
+
+ //
+ // Postfix Operators
+ //
+ case cmOPRT_POSTFIX:
+ {
+ ICallback *pOprt = pTok->AsICallback();
+ MUP_ASSERT(stVal.size());
+
+ ptr_val_type &pVal(stVal.top());
+ try
+ {
+ // place a dummy return value into the value stack, do not
+ // evaluate pOprt (this is important for lazy evaluation!)
+ // The only place where evaluation takes place is the RPN
+ // engine!
+ pVal = ptr_val_type(new Value());
+ m_rpn.Add(pTok);
+ }
+ catch(ParserError &)
+ {
+ if (!m_bIsQueryingExprVar)
+ throw;
+ }
+ }
+ break;
+
+ case cmIO:
+ case cmBO:
+ stOpt.push(pTok);
+ stArgCount.push(1);
+ break;
+
+ //
+ // Functions
+ //
+ case cmOPRT_INFIX:
+ case cmFUNC:
+ {
+ ICallback *pFunc = pTok->AsICallback();
+ MUP_ASSERT(pFunc);
+
+ // Check if this function is a argument to another function
+ // if so check if the the return type fits.
+ if (!stFunc.empty() && stFunc.top()->GetCode()==cmFUNC)
+ {
+ MUP_ASSERT(stArgCount.size());
+ int iArgc = (int)stArgCount.top() /*+ 1*/;
+
+ ICallback *pOuterFunc = stFunc.top();
+ if (pOuterFunc->GetArgc()!=-1 && iArgc>pOuterFunc->GetArgc())
+ Error(ecTOO_MANY_PARAMS, m_pTokenReader->GetPos());
+
+ MUP_ASSERT(pOuterFunc->GetArgc()==-1 || iArgc<=pOuterFunc->GetArgc());
+ }
+
+ stOpt.push(pTok);
+ stFunc.push(pFunc); // to collect runtime type information
+ }
+ break;
+
+ default:
+ Error(ecINTERNAL_ERROR);
+ } // switch Code
+
+ if (ParserXBase::s_bDumpStack)
+ {
+ StackDump( stVal, stOpt );
+ }
+
+ if ( pTok->GetCode() == cmEOE )
+ bLoop = false;
+ } // for (all tokens)
+
+ if (ParserXBase::s_bDumpRPN)
+ {
+ m_rpn.AsciiDump();
+ }
+
+ m_nFinalResultIdx = stArgCount.top()-1;
+ MUP_ASSERT(stVal.size());
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief One of the two main parse functions.
+ \sa ParseCmdCode(), ParseValue()
+
+ Parse expression from input string. Perform syntax checking and create bytecode.
+ After parsing the string and creating the bytecode the function pointer
+ #m_pParseFormula will be changed to the second parse routine the uses bytecode instead of string parsing.
+ */
+ const IValue& ParserXBase::ParseFromString() const
+ {
+ CreateRPN();
+
+ // Umsachalten auf RPN
+ m_vStackBuffer.assign(m_rpn.GetRequiredStackSize(), ptr_val_type());
+ for (std::size_t i=0; i<m_vStackBuffer.size(); ++i)
+ {
+ Value *pValue = new Value;
+ pValue->BindToCache(&m_cache);
+ m_vStackBuffer[i].Reset(pValue);
+ }
+
+ m_pParserEngine = &ParserXBase::ParseFromRPN;
+
+ return (this->*m_pParserEngine)();
+ }
+
+ //---------------------------------------------------------------------------
+ const IValue& ParserXBase::ParseFromRPN() const
+ {
+ ptr_val_type *pStack = &m_vStackBuffer[0];
+ const ptr_tok_type *pRPN = &(m_rpn.GetData()[0]);
+
+ int sidx = -1;
+ std::size_t lenRPN = m_rpn.GetSize();
+ for (std::size_t i=0; i<lenRPN; ++i)
+ {
+ IToken *pTok = pRPN[i].Get();
+ ECmdCode eCode = pTok->GetCode();
+
+ switch (eCode)
+ {
+ case cmSCRIPT_NEWLINE:
+ sidx = -1; //-= static_cast<TokenNewline*>(pTok)->GetStackOffset();
+ m_nFinalResultIdx = 0;
+ continue;
+
+ case cmVAR:
+ {
+ sidx++;
+ assert(sidx<(int)m_vStackBuffer.size());
+ pStack[sidx].Reset(static_cast<IValue*>(pTok));
+ }
+ continue;
+
+ case cmVAL:
+ {
+ sidx++;
+ assert(sidx<(int)m_vStackBuffer.size());
+ ptr_val_type &val = pStack[sidx];
+ if (val->GetCode()==cmVAR)
+ val.Reset(m_cache.CreateFromCache());
+
+ *val = *(static_cast<IValue*>(pTok));
+ }
+ continue;
+
+ case cmIC:
+ {
+ IOprtIndex *pIdxOprt = static_cast<IOprtIndex*>(pTok);
+ int nArgs = pIdxOprt->GetArgsPresent();
+ sidx -= nArgs - 1;
+ assert(sidx>=0);
+
+ ptr_val_type &idx = pStack[sidx]; // Pointer to the first index
+ ptr_val_type &val = pStack[--sidx]; // Pointer to the variable or value beeing indexed
+ pIdxOprt->At(val, &idx, nArgs);
+
+
+
+
+/*
+
+ // apply the index operator
+ ptr_val_type &idx = pStack[sidx--];
+ ptr_val_type &val = pStack[sidx];
+ MUP_ASSERT(val->GetCode()==cmVAR);
+
+ int i;
+ try
+ {
+ i = idx->GetInteger();
+ if (i<0)
+ Error(ecINDEX_OUT_OF_BOUNDS, pTok->GetExprPos(), val.Get());
+ }
+ catch(ParserError &exc)
+ {
+ if (exc.GetCode()==ecTYPE_CONFLICT)
+ Error(ecTYPE_CONFLICT_IDX, pTok->GetExprPos(), val.Get());
+ else
+ throw;
+ }
+ val.Reset(new Variable( &(val->At(i)) ) );
+*/
+ }
+ continue;
+
+ case cmOPRT_POSTFIX:
+ case cmFUNC:
+ case cmOPRT_BIN:
+ case cmOPRT_INFIX:
+ {
+ ICallback *pFun = static_cast<ICallback*>(pTok);
+ int nArgs = pFun->GetArgsPresent();
+ sidx -= nArgs - 1;
+ assert(sidx>=0);
+
+ ptr_val_type &val = pStack[sidx];
+ try
+ {
+ if (val->GetCode()==cmVAR)
+ {
+ ptr_val_type buf(m_cache.CreateFromCache());
+ pFun->Eval(buf, &val, nArgs);
+ val = buf;
+ }
+ else
+ pFun->Eval(val, &val, nArgs);
+ }
+ catch(ParserError &exc)
+ {
+ ErrorContext err;
+ err.Expr = m_pTokenReader->GetExpr();
+ err.Ident = pFun->GetIdent();
+ err.Errc = ecEVAL;
+ err.Pos = pFun->GetExprPos();
+ err.Hint = exc.GetMsg();
+ throw ParserError(err);
+ }
+ catch(MatrixError &exc)
+ {
+ ErrorContext err;
+ err.Expr = m_pTokenReader->GetExpr();
+ err.Ident = pFun->GetIdent();
+ err.Errc = ecEVAL;
+ err.Pos = pFun->GetExprPos();
+ err.Hint = _T("Matrix dimension mismatch");
+ throw ParserError(err);
+ }
+ }
+ continue;
+
+ case cmIF:
+ MUP_ASSERT(sidx>=0);
+ if (pStack[sidx--]->GetBool()==false)
+ i+=static_cast<TokenIfThenElse*>(pTok)->GetOffset();
+ continue;
+
+ case cmELSE:
+ case cmJMP:
+ i += static_cast<TokenIfThenElse*>(pTok)->GetOffset();
+ continue;
+
+ case cmENDIF:
+ continue;
+
+ default:
+ Error(ecINTERNAL_ERROR);
+ } // switch token
+ } // for all RPN tokens
+
+ return *pStack[m_nFinalResultIdx];
+ }
+
+ //---------------------------------------------------------------------------
+ void ParserXBase::Error(EErrorCodes a_iErrc, int a_iPos, const IToken *a_pTok) const
+ {
+ ErrorContext err;
+ err.Errc = a_iErrc;
+ err.Pos = a_iPos;
+ err.Expr = m_pTokenReader->GetExpr();
+ err.Ident = (a_pTok) ? a_pTok->GetIdent() : _T("");
+ throw ParserError(err);
+ }
+
+ //------------------------------------------------------------------------------
+ /** \brief Clear all user defined variables.
+ \throw nothrow
+
+ Resets the parser to string parsing mode by calling #ReInit.
+ */
+ void ParserXBase::ClearVar()
+ {
+ m_VarDef.clear();
+ m_valDynVarShadow.clear();
+ ReInit();
+ }
+
+ //------------------------------------------------------------------------------
+ /** \brief Remove a variable from internal storage.
+ \param a_strVarName Name of the variable to be removed.
+ \throw nothrow
+
+ Removes a variable if it exists. If the Variable does not exist
+ nothing will be done.
+ */
+ void ParserXBase::RemoveVar(const string_type &a_strVarName)
+ {
+ var_maptype::iterator item = m_VarDef.find(a_strVarName);
+ if (item!=m_VarDef.end())
+ {
+ m_VarDef.erase(item);
+ ReInit();
+ }
+ }
+
+ //------------------------------------------------------------------------------
+ /** \brief Clear the expression.
+ \throw nothrow
+
+ Clear the expression and existing bytecode.
+ */
+ void ParserXBase::ClearExpr()
+ {
+ m_pTokenReader->SetExpr(_T(""));
+ ReInit();
+ }
+
+ //------------------------------------------------------------------------------
+ /** \brief Clear all function definitions.
+ \throw nothrow
+ */
+ void ParserXBase::ClearFun()
+ {
+ m_FunDef.clear();
+ ReInit();
+ }
+
+ //------------------------------------------------------------------------------
+ /** \brief Clear all user defined constants.
+ \throw nothrow
+
+ Both numeric and string constants will be removed from the internal storage.
+ */
+ void ParserXBase::ClearConst()
+ {
+ m_valConst.clear();
+ ReInit();
+ }
+
+ //------------------------------------------------------------------------------
+ /** \brief Clear all user defined postfix operators.
+ \throw nothrow
+ */
+ void ParserXBase::ClearPostfixOprt()
+ {
+ m_PostOprtDef.clear();
+ ReInit();
+ }
+
+ //------------------------------------------------------------------------------
+ /** \brief Clear all user defined binary operators.
+ \throw nothrow
+ */
+ void ParserXBase::ClearOprt()
+ {
+ m_OprtDef.clear();
+ ReInit();
+ }
+
+ //------------------------------------------------------------------------------
+ /** \brief Clear the user defined Prefix operators.
+ \throw nothrow
+ */
+ void ParserXBase::ClearInfixOprt()
+ {
+ m_InfixOprtDef.clear();
+ ReInit();
+ }
+
+ //------------------------------------------------------------------------------
+ void ParserXBase::EnableAutoCreateVar(bool bStat)
+ {
+ m_bAutoCreateVar = bStat;
+ }
+
+ //------------------------------------------------------------------------------
+ void ParserXBase::EnableOptimizer(bool bStat)
+ {
+ m_rpn.EnableOptimizer(bStat);
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Enable the dumping of bytecode amd stack content on the console.
+ \param bDumpCmd Flag to enable dumping of the current bytecode to the console.
+ \param bDumpStack Flag to enable dumping of the stack content is written to the console.
+
+ This function is for debug purposes only!
+ */
+ void ParserXBase::EnableDebugDump(bool bDumpRPN, bool bDumpStack)
+ {
+ ParserXBase::s_bDumpRPN = bDumpRPN;
+ ParserXBase::s_bDumpStack = bDumpStack;
+ }
+
+ //------------------------------------------------------------------------------
+ bool ParserXBase::IsAutoCreateVarEnabled() const
+ {
+ return m_bAutoCreateVar;
+ }
+
+ //------------------------------------------------------------------------------
+ /** \brief Dump stack content.
+
+ This function is used for debugging only.
+ */
+ void ParserXBase::StackDump(const Stack<ptr_val_type> &a_stVal,
+ const Stack<ptr_tok_type> &a_stOprt) const
+ {
+ using std::cout;
+ Stack<ptr_tok_type> stOprt(a_stOprt);
+ Stack<ptr_val_type> stVal(a_stVal);
+
+ string_type sInfo = _T("StackDump> ");
+ console() << _T("\n") << sInfo << _T("Value stack:\n");
+ console() << sInfo;
+ while ( !stVal.empty() )
+ {
+ ptr_val_type val = stVal.pop();
+ console() << _T(" ") << *(val.Get()) << _T(" ") << ((val->AsValue()!=NULL) ? _T("(Val)") : _T("(Var)"));
+ }
+
+ if (stOprt.empty())
+ console() << _T("\n") << sInfo << _T("Operator stack is empty.\n");
+ else
+ console() << _T("\n") << sInfo << _T("Operator stack:\n");
+
+ while ( !stOprt.empty() )
+ {
+ ptr_tok_type tok = stOprt.pop();
+ console() << sInfo << _T(" ") << g_sCmdCode[tok->GetCode()] << _T(" \"") << tok->GetIdent() << _T("\" \n");
+ }
+
+ console() <<endl;
+ }
+
+} // namespace mu
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpParserBase.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpParserBase.h Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,198 @@
+/** \file
+ \brief Definition of the muParserX engine.
+
+<pre>
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+</pre>
+*/
+#ifndef MUP_PARSERBASE_H
+#define MUP_PARSERBASE_H
+
+#include <cmath>
+#include <string>
+#include <iostream>
+#include <map>
+#include <memory>
+
+#include "mpIOprt.h"
+#include "mpIValReader.h"
+#include "mpIPackage.h"
+#include "mpStack.h"
+#include "mpTokenReader.h"
+#include "mpError.h"
+#include "mpValue.h"
+#include "mpVariable.h"
+#include "mpTypes.h"
+#include "mpRPN.h"
+#include "mpValueCache.h"
+
+MUP_NAMESPACE_START
+
+ /** \brief Implementation of the parser engine.
+ \author Ingo Berg
+
+ This is the muParser core. It provides the parsing logic and manages
+ the callback functions, operators, variables and constants. Do not
+ instantiate this class directly. Create an instance of mup::ParserX instead.
+ */
+ class ParserXBase
+ {
+ friend class TokenReader;
+
+ private:
+
+ //typedef Value (ParserXBase::*parse_function_type)() const;
+ typedef const IValue& (ParserXBase::*parse_function_type)() const;
+ static const char_type *c_DefaultOprt[];
+ static bool s_bDumpStack;
+ static bool s_bDumpRPN;
+
+ public:
+
+ static string_type GetVersion();
+ static void EnableDebugDump(bool bDumpCmd, bool bDumpRPN);
+
+ ParserXBase();
+ ParserXBase( const ParserXBase &a_Parser );
+ ParserXBase& operator=(const ParserXBase &a_Parser);
+ virtual ~ParserXBase();
+
+ const IValue& Eval() const;
+
+ void SetExpr(const string_type &a_sExpr);
+ void AddValueReader(IValueReader *a_pReader);
+
+ void AddPackage(IPackage *p);
+ void RemovePackage(IPackage *p);
+
+ void DefineFun(ICallback *a_pCallback);
+ void DefineConst(const string_type &a_sName, const Value &a_Val);
+ void DefineVar(const string_type &a_sName, const Variable &a_fVar);
+
+ // adding operators
+ void DefineOprt(IOprtBin *a_pCallback);
+ void DefinePostfixOprt(IOprtPostfix *a_pCallback);
+ void DefineInfixOprt(IOprtInfix *a_pCallback);
+
+ // Clear user defined variables, constants or functions
+ void ClearVar();
+ void ClearFun();
+ void ClearConst();
+ void ClearInfixOprt();
+ void ClearPostfixOprt();
+ void ClearOprt();
+ void DumpRPN() const;
+
+ void RemoveVar(const string_type &a_sVarName);
+ const var_maptype& GetExprVar() const;
+ const var_maptype& GetVar() const;
+ const val_maptype& GetConst() const;
+ const fun_maptype& GetFunDef() const;
+ const string_type& GetExpr() 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);
+
+ void EnableAutoCreateVar(bool bStat);
+ void EnableOptimizer(bool bStat);
+ bool IsAutoCreateVarEnabled() const;
+
+ const char_type* ValidNameChars() const;
+ const char_type* ValidOprtChars() const;
+ const char_type* ValidInfixOprtChars() const;
+
+ void Error(EErrorCodes a_iErrc,
+ int a_iPos = -1,
+ const IToken *a_pTok = 0) const;
+
+ private:
+
+ void Assign(const ParserXBase &a_Parser);
+ void InitTokenReader();
+ void ReInit() const;
+
+ void ApplyFunc(Stack<ptr_tok_type> &a_stOpt, Stack<ptr_val_type> &a_stVal, int a_iArgCount) const;
+ void ApplyIfElse(Stack<ptr_tok_type> &a_stOpt, Stack<ptr_val_type> &a_stVal) const;
+ void ApplyRemainingOprt(Stack<ptr_tok_type> &a_stOpt,
+ Stack<ptr_val_type> &a_stVal) const;
+
+ const IValue& ParseFromString() const;
+ const IValue& ParseFromRPN() const;
+
+ void ClearExpr();
+ void CheckName(const string_type &a_sName, const string_type &a_CharSet) const;
+ void CreateRPN() const;
+ void StackDump( const Stack<ptr_val_type> &a_stVal,
+ const Stack<ptr_tok_type> &a_stOprt ) const;
+
+ /** \brief Pointer to the parser function.
+
+ Eval() calls the function whose address is stored there.
+ */
+ mutable parse_function_type m_pParserEngine;
+
+ /** \brief Managed pointer to the token reader object. */
+ std::auto_ptr<TokenReader> m_pTokenReader;
+
+ fun_maptype m_FunDef; ///< Function definitions
+ oprt_pfx_maptype m_PostOprtDef; ///< Postfix operator callbacks
+ oprt_ifx_maptype m_InfixOprtDef; ///< Infix operator callbacks.
+ oprt_bin_multimap m_OprtDef; ///< Binary operator callbacks
+ val_maptype m_valConst; ///< Definition of parser constants
+ val_vec_type m_valDynVarShadow; ///< Value objects referenced by variables created at parser runtime
+ var_maptype m_VarDef; ///< user defind variables.
+
+ 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
+
+ /** \brief Index of the final result in the stack array.
+
+ The parser supports expressions using with commas for seperating
+ multiple expression. Each comma will increase this number.
+ (i.e. "a=10,b=15,c=a*b")
+ */
+ mutable int m_nFinalResultIdx;
+
+ /** \brief A flag indicating querying of expression variables is underway.
+
+ If this flag is set the parser is momentarily querying the expression
+ variables. In these cases undefined variable errors must be ignored cause
+ the whole point of querying the expression variables is for finding out
+ which variables mut be defined.
+ */
+ mutable bool m_bIsQueryingExprVar;
+
+ mutable bool m_bAutoCreateVar; ///< If this flag is set unknown variables will be defined automatically
+
+ mutable RPN m_rpn; ///< reverse polish notation
+ mutable val_vec_type m_vStackBuffer;
+ mutable ValueCache m_cache; ///< A cache for recycling value items instead of deleting them
+ };
+} // namespace mu
+
+#endif
+
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpRPN.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpRPN.cpp Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,172 @@
+/*
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+*/
+#include "mpRPN.h"
+#include "mpIToken.h"
+#include "mpICallback.h"
+#include "mpError.h"
+#include "mpStack.h"
+#include "mpIfThenElse.h"
+#include "mpScriptTokens.h"
+
+
+MUP_NAMESPACE_START
+
+ //---------------------------------------------------------------------------
+ RPN::RPN()
+ :m_vRPN()
+ ,m_nStackPos(-1)
+ ,m_nLine(0)
+ ,m_nMaxStackPos(0)
+ ,m_bEnableOptimizer(false)
+ {}
+
+ //---------------------------------------------------------------------------
+ RPN::~RPN()
+ {}
+
+ //---------------------------------------------------------------------------
+ void RPN::Add(ptr_tok_type tok)
+ {
+ m_vRPN.push_back(tok);
+ if (tok->AsIValue()!=NULL)
+ {
+ m_nStackPos++;
+ }
+ else if (tok->AsICallback())
+ {
+ ICallback *pFun = tok->AsICallback();
+ MUP_ASSERT(pFun);
+ m_nStackPos -= pFun->GetArgsPresent() - 1;
+ }
+
+ MUP_ASSERT(m_nStackPos>=0);
+ m_nMaxStackPos = std::max(m_nStackPos, m_nMaxStackPos);
+ }
+
+ //---------------------------------------------------------------------------
+ void RPN::AddNewline(ptr_tok_type tok, int n)
+ {
+ static_cast<TokenNewline*>(tok.Get())->SetStackOffset(n);
+ m_vRPN.push_back(tok);
+ m_nStackPos -= n;
+ m_nLine++;
+ }
+
+ //---------------------------------------------------------------------------
+ void RPN::Pop(int num)
+ {
+ if (m_vRPN.size()==0)
+ return;
+
+ for (int i=0; i<num; ++i)
+ {
+ ptr_tok_type tok = m_vRPN.back();
+
+ if (tok->AsIValue()!=0)
+ m_nStackPos--;
+
+ m_vRPN.pop_back();
+ }
+ }
+
+ //---------------------------------------------------------------------------
+ void RPN::Reset()
+ {
+ m_vRPN.clear();
+ m_nStackPos = -1;
+ m_nMaxStackPos = 0;
+ m_nLine = 0;
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief
+
+ At the moment this will only ass the jump distances to the if-else clauses
+ found in the expression.
+ */
+ void RPN::Finalize()
+ {
+ // Determine the if-then-else jump offsets
+ Stack<int> stIf, stElse;
+ int idx;
+ for (std::size_t i=0; i<m_vRPN.size(); ++i)
+ {
+ switch(m_vRPN[i]->GetCode())
+ {
+ case cmIF:
+ stIf.push(i);
+ break;
+
+ case cmELSE:
+ stElse.push(i);
+ idx = stIf.pop();
+ static_cast<TokenIfThenElse*>(m_vRPN[idx].Get())->SetOffset(i - idx);
+ break;
+
+ case cmENDIF:
+ idx = stElse.pop();
+ static_cast<TokenIfThenElse*>(m_vRPN[idx].Get())->SetOffset(i - idx);
+ break;
+ }
+ }
+ }
+
+ //---------------------------------------------------------------------------
+ void RPN::EnableOptimizer(bool bStat)
+ {
+ m_bEnableOptimizer = bStat;
+ }
+
+ //---------------------------------------------------------------------------
+ std::size_t RPN::GetSize() const
+ {
+ return m_vRPN.size();
+ }
+
+ //---------------------------------------------------------------------------
+ const token_vec_type& RPN::GetData() const
+ {
+ return m_vRPN;
+ }
+
+ //---------------------------------------------------------------------------
+ int RPN::GetRequiredStackSize() const
+ {
+ return m_nMaxStackPos + 1;
+ }
+
+ //---------------------------------------------------------------------------
+ void RPN::AsciiDump() const
+ {
+ console() << "Number of tokens: " << m_vRPN.size() << "\n";
+ console() << "MaxStackPos: " << m_nMaxStackPos << "\n";
+ for (std::size_t i=0; i<m_vRPN.size(); ++i)
+ {
+ ptr_tok_type pTok = m_vRPN[i];
+ console() << i << " : " << pTok->GetExprPos() << " : " << pTok->AsciiDump() << "\n";
+ }
+ }
+
+MUP_NAMESPACE_END
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpRPN.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpRPN.h Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,69 @@
+/*
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+*/
+#ifndef MUP_RPN_H
+#define MUP_RPN_H
+
+#include "mpFwdDecl.h"
+#include "mpTypes.h"
+
+
+MUP_NAMESPACE_START
+
+ //---------------------------------------------------------------------------
+ /** \brief A class representing the reverse polnish notation of the expression.
+
+ */
+ class RPN
+ {
+ public:
+
+ RPN();
+ ~RPN();
+
+ void Add(ptr_tok_type tok);
+ void AddNewline(ptr_tok_type tok, int n);
+ void Pop(int num);
+ void Reset();
+ void Finalize();
+ void AsciiDump() const;
+
+ const token_vec_type& GetData() const;
+ std::size_t GetSize() const;
+
+ int GetRequiredStackSize() const;
+ void EnableOptimizer(bool bStat);
+
+ private:
+
+ token_vec_type m_vRPN;
+ int m_nStackPos;
+ int m_nLine;
+ int m_nMaxStackPos;
+ bool m_bEnableOptimizer;
+ };
+
+MUP_NAMESPACE_END
+
+#endif
\ No newline at end of file
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpScriptTokens.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpScriptTokens.cpp Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,43 @@
+#include "mpScriptTokens.h"
+#include "mpTypes.h"
+
+
+MUP_NAMESPACE_START
+
+ //---------------------------------------------------------------------------
+ TokenNewline::TokenNewline()
+ :IToken(cmSCRIPT_NEWLINE)
+ ,m_nOffset(0)
+ {}
+
+ //---------------------------------------------------------------------------
+ IToken* TokenNewline::Clone() const
+ {
+ return new TokenNewline(*this);
+ }
+
+ //---------------------------------------------------------------------------
+ void TokenNewline::SetStackOffset(int nOffset)
+ {
+ m_nOffset = nOffset;
+ }
+
+ //---------------------------------------------------------------------------
+ int TokenNewline::GetStackOffset() const
+ {
+ return m_nOffset;
+ }
+
+ //---------------------------------------------------------------------------
+ string_type TokenNewline::AsciiDump() const
+ {
+ stringstream_type ss;
+
+ ss << "NEWLINE";
+ ss << _T(" [addr=0x") << std::hex << this << std::dec;
+ ss << _T(" ; offset=") << m_nOffset;
+ ss << _T("]");
+ return ss.str();
+ }
+
+MUP_NAMESPACE_END
\ No newline at end of file
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpScriptTokens.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpScriptTokens.h Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,61 @@
+/** \file
+ \brief Definition of basic types used by muParserX
+
+<pre>
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+ </pre>
+*/
+#ifndef MUP_SCRIPT_TOKENS_H
+#define MUP_SCRIPT_TOKENS_H
+
+#include "mpIToken.h"
+
+
+MUP_NAMESPACE_START
+
+ //---------------------------------------------------------------------------
+ /** \brief A class for encapsulation a newline token. */
+ class TokenNewline : public IToken
+ {
+ public:
+
+ TokenNewline();
+
+ //---------------------------------------------
+ // IToken interface
+ //---------------------------------------------
+
+ virtual IToken* Clone() const;
+ virtual string_type AsciiDump() const;
+
+ int GetStackOffset() const;
+ void SetStackOffset(int nOffset);
+
+ private:
+ int m_nOffset;
+ };
+
+MUP_NAMESPACE_END
+
+#endif
\ No newline at end of file
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpStack.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpStack.h Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,147 @@
+/*
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+*/
+#ifndef MUP_STACK_H
+#define MUP_STACK_H
+
+#include <cassert>
+#include <string>
+#include <vector>
+
+#include "mpError.h"
+
+
+MUP_NAMESPACE_START
+
+ /** \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) 2010 Ingo Berg
+ */
+ template <typename TVal, typename TCont = std::vector<TVal> >
+ class Stack
+ {
+ private:
+ /** \brief Type of the underlying container. */
+ typedef TCont cont_type;
+ cont_type m_Cont;
+
+ public:
+ typedef TVal value_type;
+
+ //---------------------------------------------------------------------------
+ Stack()
+ :m_Cont()
+ {}
+
+ //---------------------------------------------------------------------------
+ virtual ~Stack()
+ {
+ m_Cont.clear();
+ }
+
+ //---------------------------------------------------------------------------
+ void clear()
+ {
+ m_Cont.clear();
+ }
+
+ //---------------------------------------------------------------------------
+ /** \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)
+ */
+ value_type pop()
+ {
+ if (empty())
+ throw ParserError(_T("stack is empty."));
+
+ value_type el = top();
+ m_Cont.pop_back();
+ return el;
+ }
+
+ //---------------------------------------------------------------------------
+ void pop(unsigned a_iNum)
+ {
+ for (unsigned i=0; i<a_iNum; ++i)
+ m_Cont.pop_back();
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Push an object into the stack.
+ \param a_Val object to push into the stack.
+ \throw nothrow
+ */
+ void push(const value_type& a_Val)
+ {
+ m_Cont.push_back(a_Val);
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Return the number of stored elements. */
+ unsigned size() const
+ {
+ return (unsigned)m_Cont.size();
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Returns true if stack is empty false otherwise. */
+ bool empty() const
+ {
+ return m_Cont.empty();
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Return reference to the top object in the stack.
+
+ The top object is the one pushed most recently.
+ */
+ value_type& top()
+ {
+ return m_Cont.back();
+ }
+
+ //---------------------------------------------------------------------------
+ value_type* get_data()
+ {
+ return &m_Cont[0];
+ }
+
+ //---------------------------------------------------------------------------
+ const value_type* get_data() const
+ {
+ return &m_Cont[0];
+ }
+ };
+} // namespace mu
+
+#endif
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpTest.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpTest.cpp Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,1636 @@
+/** \file
+ \brief Implementation of the unit test for muParserX.
+
+<pre>
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+</pre>
+*/
+#include "mpTest.h"
+#include "mpValue.h"
+
+#include <cstdio>
+#include <cstdlib>
+#include <cmath>
+#include <iostream>
+#include <complex>
+
+#define MUP_CONST_PI 3.141592653589793238462643
+#define MUP_CONST_E 2.718281828459045235360287
+
+using namespace std;
+
+
+MUP_NAMESPACE_START
+
+ //------------------------------------------------------------------------------
+ class FunTest0 : public ICallback
+ {
+ public:
+ FunTest0() : ICallback(cmFUNC, _T("test0"), 0)
+ {}
+
+ virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc)
+ {
+ ParserXBase &parser = *GetParent();
+ *ret = 0;
+ }
+
+ virtual const char_type* GetDesc() const
+ {
+ return _T("");
+ }
+
+ virtual IToken* Clone() const
+ {
+ return new FunTest0(*this);
+ }
+ }; // class FunTest0
+
+
+ //---------------------------------------------------------------------------
+ int ParserTester::c_iCount = 0;
+
+ //---------------------------------------------------------------------------
+ ParserTester::ParserTester()
+ :m_vTestFun()
+ ,m_stream(&console())
+ {
+ AddTest(&ParserTester::TestParserValue);
+ AddTest(&ParserTester::TestUndefVar);
+ AddTest(&ParserTester::TestErrorCodes);
+ AddTest(&ParserTester::TestEqn);
+ AddTest(&ParserTester::TestIfElse);
+ AddTest(&ParserTester::TestMultiLine);
+ AddTest(&ParserTester::TestStringFun);
+ AddTest(&ParserTester::TestMatrix);
+ AddTest(&ParserTester::TestComplex);
+ AddTest(&ParserTester::TestVector);
+ AddTest(&ParserTester::TestBinOp);
+ AddTest(&ParserTester::TestPostfix);
+ AddTest(&ParserTester::TestInfix);
+ AddTest(&ParserTester::TestMultiArg);
+ AddTest(&ParserTester::TestNames);
+ ParserTester::c_iCount = 0;
+ }
+
+ //---------------------------------------------------------------------------
+ int ParserTester::TestUndefVar()
+ {
+ int iNumErr = 0;
+ *m_stream << _T("testing implicit definition of undefined variables...");
+
+ // Test 1: No variables defined, test detection of undefined variables
+ {
+ ParserX p;
+ p.SetExpr(_T("a+b+c+d"));
+ const mup::var_maptype &expr_var = p.GetExprVar();
+ const mup::var_maptype &var = p.GetVar();
+
+ // The expression contains 4 undefined variables
+ if (expr_var.size()!=4)
+ iNumErr++;
+
+ // There are no variables defined
+ if (var.size()!=0)
+ iNumErr++;
+ }
+
+ // Test 2: Variables were defined explicitely, test detection of variables
+ {
+ ParserX p;
+
+ // Now define the variables and perform the check again
+ Value vVarVal[] = { 1, 2, 3, 4};
+ p.DefineVar( _T("a"), Variable(&vVarVal[0]) );
+ p.DefineVar( _T("b"), Variable(&vVarVal[1]) );
+ p.DefineVar( _T("c"), Variable(&vVarVal[2]) );
+ p.DefineVar( _T("d"), Variable(&vVarVal[3]) );
+
+ p.SetExpr(_T("a+b+c+d"));
+ const mup::var_maptype &expr_var = p.GetExprVar();
+ const mup::var_maptype &var = p.GetVar();
+
+ // The expression contains 4 undefined variables
+ if (expr_var.size()!=4)
+ iNumErr++;
+
+ // There are no variables defined
+ if (var.size()!=4)
+ iNumErr++;
+ }
+
+ // Test 3: Variables were defined implicitels, test detection of undefined variables
+ {
+ ParserX p;
+
+ // Now define the variables and perform the check again
+ p.EnableAutoCreateVar(true);
+
+ p.SetExpr(_T("a+b+c+d"));
+ const mup::var_maptype &expr_var = p.GetExprVar();
+ const mup::var_maptype &var = p.GetVar();
+
+ // The expression contains 4 undefined variables
+ if (expr_var.size()!=4)
+ iNumErr++;
+
+ // There are no variables defined
+ if (var.size()!=4)
+ iNumErr++;
+ }
+
+ Assessment(iNumErr);
+ return iNumErr;
+ }
+
+ //---------------------------------------------------------------------------
+ int ParserTester::TestMatrix()
+ {
+ int iNumErr = 0;
+ *m_stream << _T("testing matrix calculations...");
+
+ Value unity(3, 3, 0);
+ unity.At(0, 0) = 1;
+ unity.At(1, 1) = 1;
+ unity.At(2, 2) = 1;
+
+ Value va(3, 0);
+ va.At(0) = 1;
+ va.At(1) = 2;
+ va.At(2) = 3;
+
+ //Value m2(3, 3, 0);
+ //m2.At(0, 0) = 1; m2.At(0, 1) = 2; m2.At(0, 2) = 3;
+ //m2.At(1, 0) = 4; m2.At(1, 1) = 5; m2.At(1, 2) = 6;
+ //m2.At(2, 0) = 7; m2.At(2, 1) = 8; m2.At(2, 2) = 9;
+
+ Value m1_plus_m2(3, 3, 0);
+ m1_plus_m2.At(0, 0) = 2; m1_plus_m2.At(0, 1) = 2; m1_plus_m2.At(0, 2) = 3;
+ m1_plus_m2.At(1, 0) = 4; m1_plus_m2.At(1, 1) = 6; m1_plus_m2.At(1, 2) = 6;
+ m1_plus_m2.At(2, 0) = 7; m1_plus_m2.At(2, 1) = 8; m1_plus_m2.At(2, 2) = 10;
+
+ Value m2_minus_m1(3, 3, 0);
+ m2_minus_m1.At(0, 0) = 0; m2_minus_m1.At(0, 1) = 2; m2_minus_m1.At(0, 2) = 3;
+ m2_minus_m1.At(1, 0) = 4; m2_minus_m1.At(1, 1) = 4; m2_minus_m1.At(1, 2) = 6;
+ m2_minus_m1.At(2, 0) = 7; m2_minus_m1.At(2, 1) = 8; m2_minus_m1.At(2, 2) = 8;
+
+ Value m2_times_10(3, 3, 0);
+ m2_times_10.At(0, 0) = 10; m2_times_10.At(0, 1) = 20; m2_times_10.At(0, 2) = 30;
+ m2_times_10.At(1, 0) = 40; m2_times_10.At(1, 1) = 50; m2_times_10.At(1, 2) = 60;
+ m2_times_10.At(2, 0) = 70; m2_times_10.At(2, 1) = 80; m2_times_10.At(2, 2) = 90;
+
+ Value va_times_vb_transp(3, 3, 0);
+ va_times_vb_transp.At(0, 0) = 4; va_times_vb_transp.At(0, 1) = 3; va_times_vb_transp.At(0, 2) = 2;
+ va_times_vb_transp.At(1, 0) = 8; va_times_vb_transp.At(1, 1) = 6; va_times_vb_transp.At(1, 2) = 4;
+ va_times_vb_transp.At(2, 0) = 12; va_times_vb_transp.At(2, 1) = 9; va_times_vb_transp.At(2, 2) = 6;
+
+ // Check matrix dimension mismatch error
+ iNumErr += ThrowTest(_T("\"hallo\"+m1"), ecEVAL);
+ iNumErr += ThrowTest(_T("m1+\"hallo\""), ecEVAL);
+ iNumErr += ThrowTest(_T("va+m1"), ecEVAL);
+ iNumErr += ThrowTest(_T("m1+va"), ecEVAL);
+ iNumErr += ThrowTest(_T("va-m1"), ecEVAL);
+ iNumErr += ThrowTest(_T("m1-va"), ecEVAL);
+ iNumErr += ThrowTest(_T("va*m1"), ecEVAL); // matrix dimension mismatch
+ iNumErr += ThrowTest(_T("m1[1]"), ecINDEX_DIMENSION);
+ iNumErr += ThrowTest(_T("m1[1,2,3]"), ecINDEX_DIMENSION);
+ iNumErr += ThrowTest(_T("va[1,2]"), ecINDEX_DIMENSION);
+
+ iNumErr += ThrowTest(_T("a+m1"), ecEVAL);
+ iNumErr += ThrowTest(_T("m1+a"), ecEVAL);
+ iNumErr += ThrowTest(_T("a-m1"), ecEVAL);
+ iNumErr += ThrowTest(_T("m1-a"), ecEVAL);
+
+ // sample expressions
+ iNumErr += EqnTest(_T("m1"), unity, true);
+ iNumErr += EqnTest(_T("m1*m1"), unity, true);
+ iNumErr += EqnTest(_T("m1+m2"), m1_plus_m2, true);
+ iNumErr += EqnTest(_T("m2-m1"), m2_minus_m1, true);
+ iNumErr += EqnTest(_T("10*m2"), m2_times_10, true);
+ iNumErr += EqnTest(_T("m2*10"), m2_times_10, true);
+ iNumErr += EqnTest(_T("5*m2*b"), m2_times_10, true);
+ iNumErr += EqnTest(_T("b*m2*5"), m2_times_10, true);
+ iNumErr += EqnTest(_T("m1*va"), va, true);
+
+ // ones
+ Value ones_3(3, 1.0);
+ Value ones_3x3(3, 3, 1.0);
+ iNumErr += ThrowTest(_T("ones(1,2,3)"), ecEVAL);
+ iNumErr += ThrowTest(_T("ones()"), ecEVAL);
+ iNumErr += EqnTest(_T("ones(1,1)"), 1, true);
+ iNumErr += EqnTest(_T("ones(1)"), 1, true);
+ iNumErr += EqnTest(_T("ones(3,3)"), ones_3x3, true);
+ iNumErr += EqnTest(_T("ones(3,1)"), ones_3, true);
+ iNumErr += EqnTest(_T("ones(3)"), ones_3, true);
+
+ // transposition
+ iNumErr += EqnTest(_T("va'*vb"), 16, true);
+ iNumErr += EqnTest(_T("2*va'*vb"), 32, true);
+ iNumErr += EqnTest(_T("va*vb'"), va_times_vb_transp, true);
+
+ Assessment(iNumErr);
+ return iNumErr;
+ }
+
+ //---------------------------------------------------------------------------
+ int ParserTester::TestComplex()
+ {
+ int iNumErr = 0;
+ *m_stream << _T("testing complex calculations...");
+
+ // complex numbers
+ // ca=1+i, cb=2+3i, cc=3+4i
+ iNumErr += EqnTest(_T("ca==1+i"), true, true);
+ iNumErr += EqnTest(_T("ca==ca"), true, true);
+ iNumErr += EqnTest(_T("ca!=1+i"), false, true);
+ iNumErr += EqnTest(_T("ca!=ca"), false, true);
+ iNumErr += EqnTest(_T("ca!=cb"), true, true);
+ iNumErr += EqnTest(_T("ca!=va"), true, true);
+ iNumErr += EqnTest(_T("ca==va"), false, true);
+
+ // When comparing complex number Matlab/Octave compare only the real part
+ // I'll do the same...
+ iNumErr += EqnTest(_T("ca<10+i"), true, true);
+ iNumErr += EqnTest(_T("ca>10+i"), false, true);
+ iNumErr += EqnTest(_T("ca<=10+i"), true, true);
+ iNumErr += EqnTest(_T("ca>=10+i"), false, true);
+ iNumErr += EqnTest(_T("ca<=1"), true, true);
+ iNumErr += EqnTest(_T("ca>=1"), true, true);
+
+ // complex numbers
+ iNumErr += EqnTest(_T("i*i"), -1, true, 0);
+ iNumErr += EqnTest(_T("norm(3+4i)"), 25, true, 0);
+ iNumErr += EqnTest(_T("norm(4i+3)"), 25, true, 0);
+ iNumErr += EqnTest(_T("norm(3i+4)"), 25, true, 0);
+ iNumErr += EqnTest(_T("real(4.1i+3.1)"), (float_type)3.1, true, 0);
+ iNumErr += EqnTest(_T("imag(3.1i+4.1)"), (float_type)3.1, true, 0);
+ iNumErr += EqnTest(_T("real(3.1)"), (float_type)3.1, true, 0);
+ iNumErr += EqnTest(_T("imag(2.1i)"), (float_type)2.1, true, 0);
+ iNumErr += EqnTest(_T("-(4i+5)"), cmplx_type(-5, -4), true, 0);
+ iNumErr += EqnTest(_T("sqrt(-1)"), cmplx_type(0, 1), true, 0);
+ iNumErr += EqnTest(_T("sqrt(i*i)"), cmplx_type(0, 1), true, 0);
+ iNumErr += EqnTest(_T("sqrt(f)"), cmplx_type(0, 1), true, 1);
+ iNumErr += EqnTest(_T("sqrt(2-3)"), cmplx_type(0, 1), true, 0);
+ iNumErr += EqnTest(_T("sqrt(a-b)"), cmplx_type(0, 1), true, 2);
+ iNumErr += EqnTest(_T("sqrt((2-3))"), cmplx_type(0, 1), true, 0);
+ iNumErr += EqnTest(_T("sqrt((a-b))"), cmplx_type(0, 1), true, 2);
+ iNumErr += EqnTest(_T("sqrt(-(1))"), cmplx_type(0, 1), true, 0);
+ iNumErr += EqnTest(_T("sqrt((-1))"), cmplx_type(0, 1), true, 0);
+ iNumErr += EqnTest(_T("sqrt(-(-1))"), cmplx_type(1, 0), true, 0);
+ iNumErr += EqnTest(_T("sqrt(1)"), cmplx_type(1, 0), true, 0);
+ iNumErr += EqnTest(_T("a=1+2i"), cmplx_type(1, 2), true, 1);
+ iNumErr += EqnTest(_T("-(1+2i)"), cmplx_type(-1, -2), true, 0);
+ iNumErr += EqnTest(_T("-(-1-2i)"), cmplx_type(1, 2), true, 0);
+ iNumErr += EqnTest(_T("a*i"), cmplx_type(0, 1), true, 1);
+ iNumErr += EqnTest(_T("-(a+b*i)"), cmplx_type(-1, -2), true, 2);
+ iNumErr += EqnTest(_T("-(-a-b*i)"), cmplx_type(1, 2), true, 2);
+ iNumErr += EqnTest(_T("(2+4i)*(8-6i)"), cmplx_type(40, 20), true, 0);
+
+ // Test assignment operator with complex numbers. This needs to be written
+ // in a bit of an obfuscated way in order to make the test work. EqnTest
+ // computes the expression multiple times which would assign the variable
+ // multiple times with different values. This would cause false positives
+ // in the fail count. The result of the test expression is assigned to the
+ // variable c, the original variable is then reset and finally the value
+ // in c is used as the expression result...
+ iNumErr += EqnTest(_T("c=(a+=1+2i), a=1, c"), cmplx_type(2, 2), true, 2);
+ iNumErr += EqnTest(_T("c=(a-=1+2i), a=1, c"), cmplx_type(0, -2), true, 2);
+ iNumErr += EqnTest(_T("c=(b*=1+2i), b=2, c"), cmplx_type(2, 4), true, 2);
+ iNumErr += EqnTest(_T("c=(b/=1+2i), b=2, c"), cmplx_type((float_type)0.4, (float_type)-0.8), true, 2);
+
+ Assessment(iNumErr);
+ return iNumErr;
+ }
+
+ //---------------------------------------------------------------------------
+ int ParserTester::TestParserValue()
+ {
+ int iNumErr = 0;
+ *m_stream << _T("testing parser value types...");
+
+ // Define values and variables for each type
+ Value bVal = true;
+ Value iVal = 10;
+ Value fVal = (float_type)3.14;
+ Value sVal = string_type(_T("hello world"));
+ Value sVal1 = _T("hello world"); // Test assignment from const char* to string
+ Value cVal = cmplx_type(1,1);
+ Value aVal(2,0);
+ aVal.At(0) = (float_type)2.0;
+ aVal.At(1) = (float_type)3.0;
+
+ // Create a 3x3 matrix
+ Value matrix(3, 0);
+ matrix.At(0) = Value(3, 0);
+ matrix.At(1) = Value(3, 0);
+ matrix.At(2) = Value(3, 0);
+
+ Variable bVar(&bVal),
+ iVar(&iVal),
+ fVar(&fVal),
+ sVar(&sVal),
+ sVar1(&sVal1),
+ cVar(&cVal),
+ aVar(&aVal);
+
+ // Check the value types
+ try
+ {
+ // Test if matrix values do work
+ if (!matrix.IsMatrix() || matrix.GetRows()!=3)
+ iNumErr++;
+
+ std::size_t sz = matrix.GetRows();
+ for (std::size_t i=0; i<sz; ++i)
+ {
+ std::size_t dim_row = matrix.At(i).GetRows();
+ if (dim_row!=3)
+ {
+ iNumErr++;
+ console() << _T("\n Array dimension mismatch in matrix row ") << i
+ << _T(" (expected=3; dim=") << dim_row << _T(")");
+ }
+ }
+
+
+ // test type checking of values
+ if ( !iVal.IsScalar() || iVal.IsMatrix() || iVal.GetType()!='i') iNumErr++;
+ if ( !fVal.IsScalar() || fVal.IsMatrix() || fVal.GetType()!='f') iNumErr++;
+ if ( !cVal.IsScalar() || cVal.IsMatrix() || cVal.GetType()!='c') iNumErr++;
+ if ( aVal.IsScalar() || !aVal.IsMatrix() || aVal.GetType()!='m') iNumErr++;
+ if ( sVal.IsScalar() || sVal.IsMatrix() || sVal.GetType()!='s') iNumErr++;
+ if ( sVal1.IsScalar() || sVal1.IsMatrix() || sVal1.GetType()!='s') iNumErr++;
+ if ( bVal.IsScalar() || bVal.IsMatrix() || bVal.GetType()!='b') iNumErr++;
+
+ // test type checking of variables
+ if ( !iVar.IsScalar() || iVar.IsMatrix() || iVar.GetType()!='i') iNumErr++;
+ if ( !fVar.IsScalar() || fVar.IsMatrix() || fVar.GetType()!='f') iNumErr++;
+ if ( !cVar.IsScalar() || cVar.IsMatrix() || cVar.GetType()!='c') iNumErr++;
+ if ( aVar.IsScalar() || !aVar.IsMatrix() || aVar.GetType()!='m') iNumErr++;
+ if ( sVar.IsScalar() || sVar.IsMatrix() || sVar.GetType()!='s') iNumErr++;
+ if ( sVar1.IsScalar() || sVar1.IsMatrix() || sVar1.GetType()!='s') iNumErr++;
+ if ( bVar.IsScalar() || bVar.IsMatrix() || bVar.GetType()!='b') iNumErr++;
+
+ // Test type identifier after calling an assignment operator
+
+ // a double that can be mapped to an integer without rounding error will become one
+ iVal = (float_type)10.0;
+ if ( iVar.GetType()!='i') iNumErr++;
+
+ iVal = 10;
+ if ( iVar.GetType()!='i') iNumErr++;
+
+ // a complex number that can be mapped to an integer without rounding error will become one
+ iVal = cmplx_type(10, 0);
+ if ( iVar.GetType()!='i') iNumErr++;
+
+ iVal = (float_type)10.1;
+ if ( iVar.GetType()!='f') iNumErr++;
+
+ iVal = cmplx_type(10, 1);
+ if ( iVar.GetType()!='c') iNumErr++;
+
+ iVal = _T("test");
+ if ( iVar.GetType()!='s') iNumErr++;
+
+ iVal = string_type(_T("test"));
+ if ( iVar.GetType()!='s') iNumErr++;
+
+ iVal = false;
+ if ( iVar.GetType()!='b') iNumErr++;
+ }
+ catch(...)
+ {
+ iNumErr++;
+ }
+
+ bool bError;
+
+#define VALUE_THROWCHECK(VAR, FAIL, MEMBER) \
+ bError = (FAIL); \
+ try \
+ { \
+ VAR.MEMBER(); \
+ } \
+ catch(...) \
+ { \
+ bError ^= true ; \
+ } \
+ iNumErr += (bError) ? 1 : 0; \
+ c_iCount++;
+
+ // Check if the getter functions really throw an exception
+ // when used with an incorrect value type
+ // Case 1: test float values
+ VALUE_THROWCHECK(fVal, false, GetFloat)
+ VALUE_THROWCHECK(fVal, false, GetImag)
+ VALUE_THROWCHECK(fVal, true, GetBool)
+ VALUE_THROWCHECK(fVal, true, GetString)
+ VALUE_THROWCHECK(fVal, true, GetArray)
+ // for variables
+ VALUE_THROWCHECK(fVar, false, GetFloat)
+ VALUE_THROWCHECK(fVar, false, GetImag)
+ VALUE_THROWCHECK(fVar, true, GetBool)
+ VALUE_THROWCHECK(fVar, true, GetString)
+ VALUE_THROWCHECK(fVar, true, GetArray)
+
+ // Case 2: test bool values
+ VALUE_THROWCHECK(bVal, false, GetFloat)
+ VALUE_THROWCHECK(bVal, true, GetImag)
+ VALUE_THROWCHECK(bVal, false, GetBool)
+ VALUE_THROWCHECK(bVal, true, GetString)
+ VALUE_THROWCHECK(bVal, true, GetArray)
+ // for variables
+ VALUE_THROWCHECK(bVar, false, GetFloat)
+ VALUE_THROWCHECK(bVar, true, GetImag)
+ VALUE_THROWCHECK(bVar, false, GetBool)
+ VALUE_THROWCHECK(bVar, true, GetString)
+ VALUE_THROWCHECK(bVar, true, GetArray)
+
+ // Case 3: test string values
+// VALUE_THROWCHECK(sVal, true, GetFloat)
+ VALUE_THROWCHECK(sVal, true, GetImag)
+ VALUE_THROWCHECK(sVal, true, GetBool)
+ VALUE_THROWCHECK(sVal, false, GetString)
+ VALUE_THROWCHECK(sVal, true, GetArray)
+ // for variables
+// VALUE_THROWCHECK(sVar, true, GetFloat)
+ VALUE_THROWCHECK(sVar, true, GetImag)
+ VALUE_THROWCHECK(sVar, true, GetBool)
+ VALUE_THROWCHECK(sVar, false, GetString)
+ VALUE_THROWCHECK(sVar, true, GetArray)
+
+ // Case 4: test array values
+// VALUE_THROWCHECK(aVal, true, GetFloat)
+ VALUE_THROWCHECK(aVal, true, GetImag)
+ VALUE_THROWCHECK(aVal, true, GetBool)
+ VALUE_THROWCHECK(aVal, true, GetString)
+ VALUE_THROWCHECK(aVal, false, GetArray)
+ // for variables
+// VALUE_THROWCHECK(aVar, true, GetFloat)
+ VALUE_THROWCHECK(aVar, true, GetImag)
+ VALUE_THROWCHECK(aVar, true, GetBool)
+ VALUE_THROWCHECK(aVar, true, GetString)
+ VALUE_THROWCHECK(aVar, false, GetArray)
+
+ // Case 5: test complex values
+// VALUE_THROWCHECK(cVal, false, GetFloat)
+ VALUE_THROWCHECK(cVal, false, GetImag)
+ VALUE_THROWCHECK(cVal, true, GetBool)
+ VALUE_THROWCHECK(cVal, true, GetString)
+ VALUE_THROWCHECK(cVal, true, GetArray)
+ // for variables
+// VALUE_THROWCHECK(cVar, false, GetFloat)
+ VALUE_THROWCHECK(cVar, false, GetImag)
+ VALUE_THROWCHECK(cVar, true, GetBool)
+ VALUE_THROWCHECK(cVar, true, GetString)
+ VALUE_THROWCHECK(cVar, true, GetArray)
+#undef VALUE_THROWCHECK
+
+ Assessment(iNumErr);
+ return iNumErr;
+ }
+
+
+ //---------------------------------------------------------------------------
+ int ParserTester::TestErrorCodes()
+ {
+ int iNumErr = 0;
+ *m_stream << _T("testing error codes...");
+
+ // This is allowed now:
+ //iNumErr += ThrowTest(_T("1,2"), ecUNEXPECTED_COMMA);
+ //iNumErr += ThrowTest(_T("(1,2)"), ecUNEXPECTED_COMMA);
+ //iNumErr += ThrowTest(_T("2*1,2"), ecUNEXPECTED_COMMA);
+
+ iNumErr += ThrowTest(_T("sin(1,2)"), ecTOO_MANY_PARAMS);
+
+ // Invalid function argument types
+ iNumErr += ThrowTest(_T("sin(\"test\")"), ecEVAL, 0);
+ iNumErr += ThrowTest(_T("max(1, \"test\")"), ecEVAL, 0);
+ iNumErr += ThrowTest(_T("max(1,sin(8), \"t\")"), ecEVAL, 0);
+ iNumErr += ThrowTest(_T("str2dbl(sin(3.14))"), ecEVAL, 0);
+
+ // Invalid unary operator argument types
+ iNumErr += ThrowTest(_T("\"test\"{n}"), ecEVAL, 6); // (nano can only be applied to floats)
+ iNumErr += ThrowTest(_T("(1+3i)/(8*9i)+\"hallo\""), ecEVAL);
+ iNumErr += ThrowTest(_T("(1+3i)/(8*9i)-\"hallo\""), ecEVAL);
+ iNumErr += ThrowTest(_T("(1+3i)/(8*9i)*\"hallo\""), ecEVAL);
+ iNumErr += ThrowTest(_T("(1+3i)/(8*9i)/\"hallo\""), ecEVAL);
+ iNumErr += ThrowTest(_T("10+va"), ecEVAL, 2);
+
+ // Type conflicts in binary operators
+ iNumErr += ThrowTest(_T("\"test\" // 8"), ecEVAL, 7);
+ iNumErr += ThrowTest(_T("8//\"test\""), ecEVAL, 1);
+ iNumErr += ThrowTest(_T("5//8"), ecEVAL, 1);
+ iNumErr += ThrowTest(_T("\"t\"//sin(8)"), ecEVAL, 3);
+ iNumErr += ThrowTest(_T("sin(8)//\"t\""), ecEVAL, 6);
+
+ // Unexpected end of expression
+ iNumErr += ThrowTest(_T("3+"), ecUNEXPECTED_EOF);
+ iNumErr += ThrowTest(_T("8*"), ecUNEXPECTED_EOF);
+ iNumErr += ThrowTest(_T("3+("), ecUNEXPECTED_EOF);
+ iNumErr += ThrowTest(_T("3+sin"), ecUNEXPECTED_EOF);
+ iNumErr += ThrowTest(_T("(2+"), ecUNEXPECTED_EOF);
+
+ iNumErr += ThrowTest(_T("3+)"), ecUNEXPECTED_PARENS);
+ iNumErr += ThrowTest(_T("3)"), ecUNEXPECTED_PARENS);
+ iNumErr += ThrowTest(_T("(3))"), ecUNEXPECTED_PARENS);
+ iNumErr += ThrowTest(_T("()"), ecUNEXPECTED_PARENS);
+ iNumErr += ThrowTest(_T("(2+)"), ecUNEXPECTED_PARENS);
+ iNumErr += ThrowTest(_T("sin(cos)"), ecUNEXPECTED_PARENS);
+ iNumErr += ThrowTest(_T("sin(())"), ecUNEXPECTED_PARENS);
+ iNumErr += ThrowTest(_T("sin()"), ecTOO_FEW_PARAMS);
+ iNumErr += ThrowTest(_T("sin)"), ecUNEXPECTED_PARENS);
+ iNumErr += ThrowTest(_T("pi)"), ecUNEXPECTED_PARENS);
+ iNumErr += ThrowTest(_T("a)"), ecUNEXPECTED_PARENS);
+ iNumErr += ThrowTest(_T("2(-m)"), ecUNEXPECTED_PARENS);
+ iNumErr += ThrowTest(_T("2(m)"), ecUNEXPECTED_PARENS);
+
+ iNumErr += ThrowTest(_T("(1+2"), ecMISSING_PARENS);
+ iNumErr += ThrowTest(_T("((3)"), ecMISSING_PARENS);
+
+ // The behaviour in the next function depends on whether
+ // implicit variable creation is allowed or not. (momentarily its active)
+ iNumErr += ThrowTest(_T("5z)"), ecUNASSIGNABLE_TOKEN);
+ iNumErr += ThrowTest(_T("sin(3)xyz"), ecUNASSIGNABLE_TOKEN);
+ iNumErr += ThrowTest(_T("5t6"), ecUNASSIGNABLE_TOKEN);
+ iNumErr += ThrowTest(_T("5 t 6"), ecUNASSIGNABLE_TOKEN);
+ iNumErr += ThrowTest(_T("ksdfj"), ecUNASSIGNABLE_TOKEN);
+
+ // unexpected operator
+ iNumErr += ThrowTest(_T("-{m}"), ecUNEXPECTED_OPERATOR);
+ iNumErr += ThrowTest(_T("{m}4"), ecUNEXPECTED_OPERATOR);
+ iNumErr += ThrowTest(_T("sin({m})"), ecUNEXPECTED_OPERATOR);
+ iNumErr += ThrowTest(_T("{m} {m}"), ecUNEXPECTED_OPERATOR);
+ iNumErr += ThrowTest(_T("{m}(8)"), ecUNEXPECTED_OPERATOR);
+ iNumErr += ThrowTest(_T("4 + {m}"), ecUNEXPECTED_OPERATOR);
+ iNumErr += ThrowTest(_T("5+*3)"), ecUNEXPECTED_OPERATOR);
+
+ // unexpected comma (used without a function)
+ iNumErr += ThrowTest(_T(",3"), ecUNEXPECTED_COMMA);
+ iNumErr += ThrowTest(_T("sin(,sin(8))"), ecUNEXPECTED_COMMA);
+
+ iNumErr += ThrowTest(_T("sin(3)cos(3)"), ecUNEXPECTED_FUN);
+ iNumErr += ThrowTest(_T("sin(3)3"), ecUNEXPECTED_VAL);
+ iNumErr += ThrowTest(_T("sin(3)+"), ecUNEXPECTED_EOF);
+
+ // value recognition
+ iNumErr += ThrowTest(_T("0x"), ecUNASSIGNABLE_TOKEN); // incomplete hex value
+ iNumErr += ThrowTest(_T("1+0x"), ecUNASSIGNABLE_TOKEN); // incomplete hex value
+ iNumErr += ThrowTest(_T("a+0x"), ecUNASSIGNABLE_TOKEN); // incomplete hex value
+
+ // index operator
+ iNumErr += ThrowTest(_T("min(3,]"), ecUNEXPECTED_SQR_BRACKET);
+ iNumErr += ThrowTest(_T("sin(]"), ecUNEXPECTED_SQR_BRACKET);
+ iNumErr += ThrowTest(_T("va[]"), ecUNEXPECTED_SQR_BRACKET);
+ iNumErr += ThrowTest(_T("3+]"), ecUNEXPECTED_SQR_BRACKET);
+ iNumErr += ThrowTest(_T("sin[a)"), ecUNEXPECTED_SQR_BRACKET);
+ iNumErr += ThrowTest(_T("1+[8]"), ecUNEXPECTED_SQR_BRACKET);
+ iNumErr += ThrowTest(_T("1[8]"), ecUNEXPECTED_SQR_BRACKET);
+ iNumErr += ThrowTest(_T("3{n}[1]"), ecUNEXPECTED_SQR_BRACKET);
+ iNumErr += ThrowTest(_T("[1]"), ecUNEXPECTED_SQR_BRACKET);
+ iNumErr += ThrowTest(_T("]1"), ecUNEXPECTED_SQR_BRACKET);
+ iNumErr += ThrowTest(_T("va[[3]]"), ecUNEXPECTED_SQR_BRACKET);
+
+ Assessment(iNumErr);
+ return iNumErr;
+ }
+
+ //---------------------------------------------------------------------------
+ int ParserTester::TestStringFun()
+ {
+ int iNumErr = 0;
+ *m_stream << _T("testing string functions...");
+
+ iNumErr += EqnTest(_T("strlen(\"12345\")"), 5, true);
+ iNumErr += EqnTest(_T("strlen(toupper(\"abcde\"))"), 5, true);
+ iNumErr += EqnTest(_T("sin(0)+(float)strlen(\"12345\")"), (float_type)5.0, true);
+ iNumErr += EqnTest(_T("10*(float)strlen(toupper(\"12345\"))"), (float_type)50.0, true);
+ iNumErr += EqnTest(_T("\"hello \"//\"world\""), string_type(_T("hello world")), true);
+ iNumErr += EqnTest(_T("toupper(\"hello \")//\"world\""), string_type(_T("HELLO world")), true);
+ iNumErr += EqnTest(_T("\"hello \"//toupper(\"world\")//\" !!!\""), string_type(_T("hello WORLD !!!")), true);
+
+ Assessment(iNumErr);
+
+ return iNumErr;
+ }
+
+ //---------------------------------------------------------------------------
+ int ParserTester::TestPostfix()
+ {
+ int iNumErr = 0;
+ *m_stream << _T("testing postfix operators...");
+
+ // application
+ iNumErr += EqnTest(_T("8{n}"), (float_type)8e-9, true);
+ iNumErr += EqnTest(_T("8{n}"), (float_type)123.0, false);
+ iNumErr += EqnTest(_T("3{m}+5"), (float_type)5.003, true);
+ iNumErr += EqnTest(_T("1000{m}"), (float_type)1.0, true);
+ iNumErr += EqnTest(_T("1000 {m}"), (float_type)1.0, true);
+ iNumErr += EqnTest(_T("a{m}"), (float_type)1e-3, true);
+ iNumErr += EqnTest(_T("(a){m}"), (float_type)1e-3, true);
+ iNumErr += EqnTest(_T("-(a){m}"), (float_type)-1e-3, true);
+ iNumErr += EqnTest(_T("-a{m}"), (float_type)-1e-3, true);
+ iNumErr += EqnTest(_T("-2{m}"), (float_type)-2e-3, true);
+ iNumErr += EqnTest(_T("a++b"), 3, true);
+ iNumErr += EqnTest(_T("a ++ b"), 3, true);
+ iNumErr += EqnTest(_T("1++2"), 3, true);
+ iNumErr += EqnTest(_T("1 ++ 2"), 3, true);
+ //iNumErr += EqnTest(_T("f1of1(1000)m"), 1, true);
+ //iNumErr += EqnTest(_T("-f1of1(1000)m"), -1, true);
+ //iNumErr += EqnTest(_T("-f1of1(-1000)m"), 1, true);
+ //iNumErr += EqnTest(_T("f4of4(0,0,0,1000)m"), 1, true);
+ iNumErr += EqnTest(_T("2+(a*1000){m}"), (float_type)3.0, true);
+ // some incorrect results
+ iNumErr += EqnTest(_T("1000{m}"), (float_type)0.1, false);
+ iNumErr += EqnTest(_T("(a){m}"), (float_type)2.0, false);
+
+ Assessment(iNumErr);
+ return iNumErr;
+ }
+
+ //---------------------------------------------------------------------------
+ int ParserTester::TestInfix()
+ {
+ int iNumErr = 0;
+ *m_stream << _T("testing parser reader implementations...");
+
+ iNumErr += EqnTest(_T("-1"), (float_type)-1.0, true);
+ iNumErr += EqnTest(_T("-(-1)"), (float_type)1.0, true);
+ iNumErr += EqnTest(_T("-(-1)*2"), (float_type)2.0, true);
+ iNumErr += EqnTest(_T("-(-2)*sqrt(4)"), (float_type)4.0, true);
+ iNumErr += EqnTest(_T("-a"), (float_type)-1.0, true);
+ iNumErr += EqnTest(_T("-(a)"), (float_type)-1.0, true);
+ iNumErr += EqnTest(_T("-(-a)"), (float_type)1.0, true);
+ iNumErr += EqnTest(_T("-(-a)*2"), (float_type)2.0, true);
+ iNumErr += EqnTest(_T("-(8)"), (float_type)-8.0, true);
+ iNumErr += EqnTest(_T("-8"), (float_type)-8.0, true);
+ iNumErr += EqnTest(_T("-(2+1)"), (float_type)-3.0, true);
+ //iNumErr += EqnTest("-(f1of1(1+2*3)+1*2)", -9.0, true);
+ //iNumErr += EqnTest("-(-f1of1(1+2*3)+1*2)", 5.0, true);
+ iNumErr += EqnTest(_T("-sin(8)"), (float_type)-0.989358, true);
+ iNumErr += EqnTest(_T("-sin(8)"), (float_type)0.989358, false);
+ iNumErr += EqnTest(_T("3-(-a)"), (float_type)4.0, true);
+ iNumErr += EqnTest(_T("3--a"), (float_type)4.0, true);
+ iNumErr += EqnTest(_T("2++4"), (float_type)6.0, true);
+ iNumErr += EqnTest(_T("--1"), (float_type)1.0, true);
+
+ // Postfix / infix priorities
+ //iNumErr += EqnTest("~2#", 12, true);
+ //iNumErr += EqnTest("~f1of1(2)#", 12, true);
+ //iNumErr += EqnTest("~(b)#", 12, true);
+ //iNumErr += EqnTest("(~b)#", 12, true);
+ //iNumErr += EqnTest("~(2#)", 8, true);
+ //iNumErr += EqnTest("~(f1of1(2)#)", 8, true);
+
+ Assessment(iNumErr);
+ return iNumErr;
+ }
+
+ //---------------------------------------------------------------------------
+ int ParserTester::TestMultiArg()
+ {
+ int iNumErr = 0;
+ *m_stream << _T("testing multiarg functions...");
+
+ // application
+ iNumErr += EqnTest(_T("max(1,8,9,(int)6)"), (float_type)9.0, true);
+ iNumErr += EqnTest(_T("max((int)6, 1+2, 4, -9)"), (float_type)6.0, true);
+ iNumErr += EqnTest(_T("min((int)6, 1+2, 4, -9)"), (float_type)-9.0, true);
+
+ //
+ iNumErr += EqnTest(_T("a=test0()"), (float_type)0, true);
+ iNumErr += EqnTest(_T("b=a+test0()"), (float_type)1, true);
+
+ // added as response to this bugreport:
+ // http://code.google.com/p/muparserx/issues/detail?id=1
+ // cause of the error: Function tokens were not cloned in the tokenreader when beeing found.
+ // a pointer to the one and only function onject was returned instead
+ // consequently the argument counter was overwritten by the second function call
+ // causing an assertion later on.
+ iNumErr += EqnTest(_T("sum(1,2)/sum(3,4)"), (float_type)0.428571, true);
+ iNumErr += EqnTest(_T("3/sum(3,4,5)"), (float_type)0.25, true);
+ iNumErr += EqnTest(_T("sum(3)/sum(3,4,5)"), (float_type)0.25, true);
+ iNumErr += EqnTest(_T("sum(3)+sum(3,4,5)"), (float_type)15, true);
+ iNumErr += EqnTest(_T("sum(1,2)/sum(3,4,5)"), (float_type)0.25, true);
+
+ Assessment(iNumErr);
+ return iNumErr;
+ }
+
+ //---------------------------------------------------------------------------
+ int ParserTester::TestVector()
+ {
+ int iNumErr = 0;
+ *m_stream << _T("testing vector operations...");
+
+ // Vector operations
+ iNumErr += ThrowTest(_T("10+2*va"), ecEVAL); // fail: number + vector
+ iNumErr += ThrowTest(_T("10+va*2"), ecEVAL); // fail: number + vector
+ iNumErr += ThrowTest(_T("va+vc"), ecEVAL); // fail: vectors of different size
+ iNumErr += ThrowTest(_T("va-vc"), ecEVAL); // fail: vectors of different size
+ iNumErr += ThrowTest(_T("va*vc"), ecEVAL); // fail: vectors of different size
+ iNumErr += ThrowTest(_T("va*vb"), ecEVAL); // fail: matrix dimension mismatch
+ iNumErr += ThrowTest(_T("va*va"), ecEVAL); // fail: matrix dimension mismatch
+ iNumErr += ThrowTest(_T("(va*vb)*b"), ecEVAL); // fail: matrix dimension mismatch
+ iNumErr += ThrowTest(_T("va[1.23]"), ecTYPE_CONFLICT_IDX, 7); // fail: float value used as index
+ iNumErr += ThrowTest(_T("va[sin(8)]"), ecTYPE_CONFLICT_IDX, 9); // fail: float value used as index
+ iNumErr += ThrowTest(_T("va[-1]"), ecINDEX_OUT_OF_BOUNDS); // fail: negative value used as an index
+ iNumErr += ThrowTest(_T("va[c]"), ecINDEX_OUT_OF_BOUNDS);
+ iNumErr += ThrowTest(_T("va[(3)]"), ecINDEX_OUT_OF_BOUNDS);
+ iNumErr += ThrowTest(_T("a[1]"), ecINDEX_DIMENSION);
+ iNumErr += ThrowTest(_T("va[1"), ecMISSING_SQR_BRACKET);
+ iNumErr += ThrowTest(_T("va[1]]"), ecUNEXPECTED_SQR_BRACKET);
+
+ //iNumErr += ThrowTest(_T("va==9"), ecEVAL);
+ //iNumErr += ThrowTest(_T("va==a"), ecEVAL);
+ //iNumErr += ThrowTest(_T("a==va"), ecEVAL);
+ //iNumErr += ThrowTest(_T("9==va"), ecEVAL);
+
+ Value v(3, 0);
+ v.At(0) = 5.0, v.At(1) = 5.0, v.At(2) = 5.0;
+ iNumErr += EqnTest(_T("va+vb"), v, true);
+
+ v.At(0) = 5.0, v.At(1) = 5.0, v.At(2) = 6.0;
+ iNumErr += EqnTest(_T("va+vb"), v, false);
+
+ v.At(0) = -1.0, v.At(1) = -2.0, v.At(2) = -3.0;
+ iNumErr += EqnTest(_T("-va"), v, true);
+
+ iNumErr += EqnTest(_T("sizeof(va+vb)"), 3, true);
+ iNumErr += EqnTest(_T("sizeof(va-vb)"), 3, true);
+
+ iNumErr += EqnTest(_T("va==vb"), false, true);
+ iNumErr += EqnTest(_T("va!=vb"), true, true);
+ //iNumErr += EqnTest(_T("va<vb"), false, true);
+ //iNumErr += EqnTest(_T("va>vb"), true, true);
+ //iNumErr += EqnTest(_T("va<=vb"), false, true);
+ //iNumErr += EqnTest(_T("va>=vb"), true, true);
+
+ iNumErr += EqnTest(_T("vb[va[0]]"), 3, true);
+ iNumErr += EqnTest(_T("m1[0,0]+m1[1,1]+m1[2,2]"), 3, true);
+ iNumErr += EqnTest(_T("vb[m1[0,0]]"), 3, true);
+
+ iNumErr += EqnTest(_T("m1[0,0]=2"), 2, true);
+ iNumErr += EqnTest(_T("m1[1,1]=2"), 2, true);
+ iNumErr += EqnTest(_T("m1[2,2]=2"), 2, true);
+ iNumErr += EqnTest(_T("va[0]=12.3"), (float_type)12.3, true);
+ iNumErr += EqnTest(_T("va[1]=12.3"), (float_type)12.3, true);
+ iNumErr += EqnTest(_T("va[2]=12.3"), (float_type)12.3, true);
+
+ iNumErr += EqnTest(_T("va[0]"), 1, true);
+ iNumErr += EqnTest(_T("va[1]"), 2, true);
+ iNumErr += EqnTest(_T("va[2]"), 3, true);
+ iNumErr += EqnTest(_T("(va[2])"), 3, true);
+ iNumErr += EqnTest(_T("va[a]"), 2, true);
+ iNumErr += EqnTest(_T("(va[a])"), 2, true);
+ iNumErr += EqnTest(_T("va[b]"), 3, true);
+ iNumErr += EqnTest(_T("va[(2)]"), 3, true);
+ iNumErr += EqnTest(_T("va[-(-2)]"), 3, true);
+ iNumErr += EqnTest(_T("(va[(2)])"), 3, true);
+ iNumErr += EqnTest(_T("(va[-(-2)])"), 3, true);
+ iNumErr += EqnTest(_T("va[1+1]"), 3, true);
+ iNumErr += EqnTest(_T("va[(int)sin(8)+1]"), 2, true);
+
+ iNumErr += EqnTest(_T("va[2]+4"), 7, true);
+ iNumErr += EqnTest(_T("4+va[2]"), 7, true);
+ iNumErr += EqnTest(_T("va[2]*4"), 12, true);
+ iNumErr += EqnTest(_T("4*va[2]"), 12, true);
+ iNumErr += EqnTest(_T("va[2]+a"), 4, true);
+ iNumErr += EqnTest(_T("a+va[2]"), 4, true);
+ iNumErr += EqnTest(_T("va[2]*b"), 6, true);
+ iNumErr += EqnTest(_T("b*va[2]"), 6, true);
+
+ //Value buf(3,0);
+ //buf[0] = 3;
+ //buf[1] = 4;
+ //buf[2] = 5;
+ //iNumErr += EqnTest(_T("vx+vy"), buf, true);
+
+ Assessment(iNumErr);
+ return iNumErr;
+ }
+
+ //---------------------------------------------------------------------------
+ int ParserTester::TestBinOp()
+ {
+ int iNumErr = 0;
+ *m_stream << _T("testing binary operators...");
+
+ // standard aperators
+ iNumErr += EqnTest(_T("1+7"), (float_type)8.0, true);
+ iNumErr += EqnTest(_T("10-1"), (float_type)9.0, true);
+ iNumErr += EqnTest(_T("3*4"), (float_type)12.0, true);
+ iNumErr += EqnTest(_T("10/2"), (float_type)5.0, true);
+ // operator associativity
+ iNumErr += EqnTest(_T("2^2^3"), (float_type)256.0, true);
+ iNumErr += EqnTest(_T("3+4*2/(1-5)^2^3"), (float_type)3.0001220703125, true);
+ iNumErr += EqnTest(_T("1/2/3"), (float_type)1.0/(float_type)6.0, true);
+
+ // operator precedencs
+ iNumErr += EqnTest(_T("1+2-3*4/5^6"), (float_type)2.99923, true);
+ iNumErr += EqnTest(_T("a+b-c*4/5^6"), (float_type)2.99923, true);
+ iNumErr += EqnTest(_T("1^2/3*4-5+6"), (float_type)2.3333, true);
+ iNumErr += EqnTest(_T("a^b/c*4-5+6"), (float_type)2.3333, true);
+ iNumErr += EqnTest(_T("1+2*3"), (float_type)7.0, true);
+ iNumErr += EqnTest(_T("a+b*c"), (float_type)7.0, true);
+ iNumErr += EqnTest(_T("(1+2)*3"), (float_type)9.0, true);
+ iNumErr += EqnTest(_T("(a+b)*c"), (float_type)9.0, true);
+ iNumErr += EqnTest(_T("(1+2)*(-3)"), (float_type)-9.0, true);
+ iNumErr += EqnTest(_T("(a+b)*(-c)"), (float_type)-9.0, true);
+ iNumErr += EqnTest(_T("2/4"), (float_type)0.5, true);
+ iNumErr += EqnTest(_T("4&4"), 4, true);
+ iNumErr += EqnTest(_T("2+2&(a+b+c)"), 4, true);
+ iNumErr += EqnTest(_T("3&3"), 3, true);
+ iNumErr += EqnTest(_T("c&3"), 3, true);
+ iNumErr += EqnTest(_T("(c)&3"), 3, true);
+ iNumErr += EqnTest(_T("(a+b)&3"), 3, true);
+ iNumErr += EqnTest(_T("(a+b+c)&6"), 6, true);
+ iNumErr += EqnTest(_T("(1+2+3)&6"), 6, true);
+ iNumErr += EqnTest(_T("3&c"), 3, true);
+ iNumErr += EqnTest(_T("(a<<1)+2"), 4, true);
+ iNumErr += EqnTest(_T("(a<<2)+2"), 6, true);
+ iNumErr += EqnTest(_T("(a<<3)+2"), 10, true);
+ iNumErr += EqnTest(_T("(a<<4)+2"), 18, true);
+ iNumErr += EqnTest(_T("(a<<5)+2"), 34, true);
+
+ // bool operators for comparing values
+ iNumErr += EqnTest(_T("a<b"), true, true);
+ iNumErr += EqnTest(_T("b>a"), true, true);
+ iNumErr += EqnTest(_T("a>a"), false, true);
+ iNumErr += EqnTest(_T("a<a"), false, true);
+ iNumErr += EqnTest(_T("a>a"), false, true);
+ iNumErr += EqnTest(_T("a<=a"), true, true);
+ iNumErr += EqnTest(_T("a<=b"), true, true);
+ iNumErr += EqnTest(_T("b<=a"), false, true);
+ iNumErr += EqnTest(_T("a>=a"), true, true);
+ iNumErr += EqnTest(_T("b>=a"), true, true);
+ iNumErr += EqnTest(_T("a>=b"), false, true);
+ // The following equations were raising type conflict errors once
+ // since the result of sqrt(1) is 1 which is an integer as fas as muParserX
+ // is concerned:
+ iNumErr += EqnTest(_T("sqrt(a)<sin(8)"), false, true);
+ iNumErr += EqnTest(_T("sqrt(a)<=sin(8)"), false, true);
+ iNumErr += EqnTest(_T("sqrt(a)>sin(8)"), true, true);
+ iNumErr += EqnTest(_T("sqrt(a)>=sin(8)"), true, true);
+ iNumErr += EqnTest(_T("sqrt(a)==sin(8)"), false, true);
+ iNumErr += EqnTest(_T("sqrt(a)!=sin(8)"), true, true);
+ iNumErr += EqnTest(_T("sqrt(a)+1.01"), 2.01, true);
+ iNumErr += EqnTest(_T("sqrt(a)-1.01"), -0.01, true);
+
+ // interaction with sign operator
+ iNumErr += EqnTest( _T("3-(-a)"), 4, true);
+ iNumErr += EqnTest( _T("3--a"), 4, true);
+
+ Assessment(iNumErr);
+ return iNumErr;
+ }
+
+ //---------------------------------------------------------------------------
+ int ParserTester::TestMultiLine()
+ {
+ int iNumErr = 0;
+ *m_stream << _T("testing multiline expressions...");
+
+ // Test error detection
+ iNumErr += ThrowTest(_T("sin(\n"), ecUNEXPECTED_NEWLINE);
+ iNumErr += ThrowTest(_T("1+\n"), ecUNEXPECTED_NEWLINE);
+ iNumErr += ThrowTest(_T("a,\n"), ecUNEXPECTED_NEWLINE);
+ iNumErr += ThrowTest(_T("a*\n"), ecUNEXPECTED_NEWLINE);
+ iNumErr += ThrowTest(_T("va[\n"), ecUNEXPECTED_NEWLINE);
+ iNumErr += ThrowTest(_T("(true) ? \n"), ecUNEXPECTED_NEWLINE);
+ iNumErr += ThrowTest(_T("(true) ? 10:\n"), ecUNEXPECTED_NEWLINE);
+
+ // Expressions spanning multiple lines
+ iNumErr += EqnTest(_T("a=1\n")
+ _T("b=2\n")
+ _T("c=3\n")
+ _T("a+b+c") , 6, true);
+ iNumErr += EqnTest(_T("a=1,b=2\n")
+ _T("c=a+b\n")
+ _T("a+b+c") , 6, true);
+
+ Assessment(iNumErr);
+ return iNumErr;
+ }
+
+ //---------------------------------------------------------------------------
+ int ParserTester::TestIfElse()
+ {
+ int iNumErr = 0;
+ *m_stream << _T("testing if-else conditional...");
+
+ // Test error detection
+ iNumErr += ThrowTest(_T(": 2"), ecUNEXPECTED_CONDITIONAL);
+ iNumErr += ThrowTest(_T("? 1 : 2"), ecUNEXPECTED_CONDITIONAL);
+ iNumErr += ThrowTest(_T("(a<b) ? (b<c) ? 1 : 2"), ecMISSING_ELSE_CLAUSE);
+ iNumErr += ThrowTest(_T("(a<b) ? 1"), ecMISSING_ELSE_CLAUSE);
+ iNumErr += ThrowTest(_T("(a<b) ? a"), ecMISSING_ELSE_CLAUSE);
+ iNumErr += ThrowTest(_T("(a<b) ? a+b"), ecMISSING_ELSE_CLAUSE);
+ iNumErr += ThrowTest(_T("a : b"), ecMISPLACED_COLON, 2);
+ iNumErr += ThrowTest(_T("1 : 2"), ecMISPLACED_COLON, 2);
+ iNumErr += ThrowTest(_T("(true) ? 1 : 2 : 3"), ecMISPLACED_COLON);
+ iNumErr += EqnTest(_T("true ? 128 : 255"), 128, true);
+ iNumErr += EqnTest(_T("1<2 ? 128 : 255"), 128, true);
+ iNumErr += EqnTest(_T("a<b ? 128 : 255"), 128, true);
+ iNumErr += EqnTest(_T("((a>b) ? true : false) ? 1 : 2"), 2, true);
+ iNumErr += EqnTest(_T("((a>b) ? true : false) ? 1 : sum((a>b) ? 1 : 2)"), 2, true);
+ iNumErr += EqnTest(_T("((a>b) ? false : true) ? 1 : sum((a>b) ? 1 : 2)"), 1, true);
+ iNumErr += EqnTest(_T("(true) ? 10 : 11"), 10, true);
+ iNumErr += EqnTest(_T("(true) ? a+b : c+d"), 3, true);
+ iNumErr += EqnTest(_T("(true) ? false : true"), false, true);
+ iNumErr += EqnTest(_T("(false) ? 10 : 11"), 11, true);
+ iNumErr += EqnTest(_T("(false) ? a+b : c+d"), 1, true);
+ iNumErr += EqnTest(_T("(false) ? false : true"), true, true);
+ iNumErr += EqnTest(_T("(a<b) ? 10 : 11"), 10, true);
+ iNumErr += EqnTest(_T("(a>b) ? 10 : 11"), 11, true);
+ iNumErr += EqnTest(_T("(a<b) ? c : d"), 3, true);
+ iNumErr += EqnTest(_T("(a>b) ? c : d"), -2, true);
+ iNumErr += EqnTest(_T("(a>b) ? true : false"), false, true);
+
+ // With multiarg functions
+ iNumErr += EqnTest(_T("sum((a>b) ? 1 : 2)"), 2, true);
+ iNumErr += EqnTest(_T("sum((a>b) ? 1 : 2, 100)"), 102, true);
+ iNumErr += EqnTest(_T("sum((true) ? 1 : 2)"), 1, true);
+ iNumErr += EqnTest(_T("sum((true) ? 1 : 2, 100)"), 101, true);
+ iNumErr += EqnTest(_T("sum(3, (a>b) ? 3 : 10)"), 13, true);
+ iNumErr += EqnTest(_T("sum(3, (a<b) ? 3 : 10)"), 6, true);
+ iNumErr += EqnTest(_T("sum(3, (a>b) ? 3 : 10)*10"), 130, true);
+ iNumErr += EqnTest(_T("sum(3, (a<b) ? 3 : 10)*10"), 60, true);
+ iNumErr += EqnTest(_T("10*sum(3, (a>b) ? 3 : 10)"), 130, true);
+ iNumErr += EqnTest(_T("10*sum(3, (a<b) ? 3 : 10)"), 60, true);
+ iNumErr += EqnTest(_T("(a<b) ? sum(3, (a<b) ? 3 : 10)*10 : 99"), 60, true);
+ iNumErr += EqnTest(_T("(a>b) ? sum(3, (a<b) ? 3 : 10)*10 : 99"), 99, true);
+ iNumErr += EqnTest(_T("(a<b) ? sum(3, (a<b) ? 3 : 10,10,20)*10 : 99"), 360, true);
+ iNumErr += EqnTest(_T("(a>b) ? sum(3, (a<b) ? 3 : 10,10,20)*10 : 99"), 99, true);
+ iNumErr += EqnTest(_T("(a>b) ? sum(3, (a<b) ? 3 : 10,10,20)*10 : sum(3, (a<b) ? 3 : 10)*10"), 60, true);
+
+ iNumErr += EqnTest(_T("(a<b)&&(a<b) ? 128 : 255"), 128, true);
+ iNumErr += EqnTest(_T("(a>b)&&(a<b) ? 128 : 255"), 255, true);
+ iNumErr += EqnTest(_T("(1<2)&&(1<2) ? 128 : 255"), 128, true);
+ iNumErr += EqnTest(_T("(1>2)&&(1<2) ? 128 : 255"), 255, true);
+ iNumErr += EqnTest(_T("((1<2)&&(1<2)) ? 128 : 255"), 128, true);
+ iNumErr += EqnTest(_T("((1>2)&&(1<2)) ? 128 : 255"), 255, true);
+ iNumErr += EqnTest(_T("((a<b)&&(a<b)) ? 128 : 255"), 128, true);
+ iNumErr += EqnTest(_T("((a>b)&&(a<b)) ? 128 : 255"), 255, true);
+
+ // nested conditionals with brackets
+ iNumErr += EqnTest(_T("(a<b) ? ((b<c) ? 2*(a+b) : 2) : 3"), 6, true);
+ iNumErr += EqnTest(_T("(a<b) ? 3 : ((b<c) ? 2*(a+b) : 2)"), 3, true);
+ iNumErr += EqnTest(_T("(a<b) ? ((b>c) ? 1 : 2) : 3"), 2, true);
+ iNumErr += EqnTest(_T("(a>b) ? ((b<c) ? 1 : 2) : 3"), 3, true);
+ iNumErr += EqnTest(_T("(a>b) ? ((b>c) ? 1 : 2) : 3"), 3, true);
+
+ // nested conditionals without brackets
+ iNumErr += EqnTest(_T("(a<b) ? (b<c) ? 1 : 2 : 3"), 1, true);
+ iNumErr += EqnTest(_T("(a<b) ? (b>c) ? 1 : 2 : 3"), 2, true);
+ iNumErr += EqnTest(_T("(a>b) ? (b<c) ? 1 : 2 : 3"), 3, true);
+ iNumErr += EqnTest(_T("(a>b) ? (b>c) ? 1 : 2 : 3"), 3, true);
+
+ // Neue Tests
+ iNumErr += EqnTest(_T("(a<b)&&(a<b) ? 128 : 255"), 128, true);
+ iNumErr += EqnTest(_T("(a>b)&&(a<b) ? 128 : 255"), 255, true);
+ iNumErr += EqnTest(_T("(1<2)&&(1<2) ? 128 : 255"), 128, true);
+ iNumErr += EqnTest(_T("(1>2)&&(1<2) ? 128 : 255"), 255, true);
+ iNumErr += EqnTest(_T("((1<2)&&(1<2)) ? 128 : 255"), 128, true);
+ iNumErr += EqnTest(_T("((1>2)&&(1<2)) ? 128 : 255"), 255, true);
+ iNumErr += EqnTest(_T("((a<b)&&(a<b)) ? 128 : 255"), 128, true);
+ iNumErr += EqnTest(_T("((a>b)&&(a<b)) ? 128 : 255"), 255, true);
+
+ iNumErr += EqnTest(_T("1>0 ? 1>2 ? 128 : 255 : 1>0 ? 32 : 64"), 255, true);
+ iNumErr += EqnTest(_T("1>0 ? 1>2 ? 128 : 255 :(1>0 ? 32 : 64)"), 255, true);
+ iNumErr += EqnTest(_T("1>0 ? 1>0 ? 128 : 255 : 1>2 ? 32 : 64"), 128, true);
+ iNumErr += EqnTest(_T("1>0 ? 1>0 ? 128 : 255 :(1>2 ? 32 : 64)"), 128, true);
+ iNumErr += EqnTest(_T("1>2 ? 1>2 ? 128 : 255 : 1>0 ? 32 : 64"), 32, true);
+ iNumErr += EqnTest(_T("1>2 ? 1>0 ? 128 : 255 : 1>2 ? 32 : 64"), 64, true);
+ iNumErr += EqnTest(_T("1>0 ? 50 : 1>0 ? 128 : 255"), 50, true);
+ iNumErr += EqnTest(_T("1>0 ? 50 : (1>0 ? 128 : 255)"), 50, true);
+ iNumErr += EqnTest(_T("1>0 ? 1>0 ? 128 : 255 : 50"), 128, true);
+ iNumErr += EqnTest(_T("1>2 ? 1>2 ? 128 : 255 : 1>0 ? 32 : 1>2 ? 64 : 16"), 32, true);
+ iNumErr += EqnTest(_T("1>2 ? 1>2 ? 128 : 255 : 1>0 ? 32 :(1>2 ? 64 : 16)"), 32, true);
+ iNumErr += EqnTest(_T("1>0 ? 1>2 ? 128 : 255 : 1>0 ? 32 :1>2 ? 64 : 16"), 255, true);
+ iNumErr += EqnTest(_T("1>0 ? 1>2 ? 128 : 255 : (1>0 ? 32 :1>2 ? 64 : 16)"), 255, true);
+ iNumErr += EqnTest(_T("true ? false ? 128 : 255 : true ? 32 : 64"), 255, true);
+
+ // assignment operators
+ iNumErr += EqnTest(_T("a= false ? 128 : 255, a"), 255, true);
+ iNumErr += EqnTest(_T("a=((a>b)&&(a<b)) ? 128 : 255, a"), 255, true);
+ iNumErr += EqnTest(_T("c=(a<b)&&(a<b) ? 128 : 255, c"), 128, true);
+ iNumErr += EqnTest(_T("false ? a=a+1 : 666, a"), 1, true);
+ iNumErr += EqnTest(_T("true?a=10:a=20, a"), 10, true);
+ iNumErr += EqnTest(_T("false?a=10:a=20, a"), 20, true);
+ iNumErr += EqnTest(_T("false?a=sum(3,4):10, a"), 1, true); // a should not change its value due to lazy calculation
+
+ iNumErr += EqnTest(_T("a=true?b=true?3:4:5, a"), 3, true);
+ iNumErr += EqnTest(_T("a=true?b=true?3:4:5, b"), 3, true);
+ iNumErr += EqnTest(_T("a=false?b=true?3:4:5, a"), 5, true);
+ iNumErr += EqnTest(_T("a=false?b=true?3:4:5, b"), 2, true);
+
+ iNumErr += EqnTest(_T("a=true?5:b=true?3:4, a"), 5, true);
+ iNumErr += EqnTest(_T("a=true?5:b=true?3:4, b"), 2, true);
+ iNumErr += EqnTest(_T("a=false?5:b=true?3:4, a"), 3, true);
+ iNumErr += EqnTest(_T("a=false?5:b=true?3:4, b"), 3, true);
+
+ Assessment(iNumErr);
+ return iNumErr;
+ }
+
+ //---------------------------------------------------------------------------
+ int ParserTester::TestEqn()
+ {
+ int iNumErr = 0;
+ *m_stream << _T("testing sample equations...");
+
+ iNumErr += EqnTest(_T("-2--8"), (float_type)6.0, true);
+ iNumErr += EqnTest(_T("2*(a=9)*3"), 54, true);
+
+ // Functions
+ iNumErr += EqnTest(_T("10*strlen(toupper(\"12345\"))"), 50, true);
+
+ // hex value recognition
+ iNumErr += EqnTest(_T("0xff"), 255, true);
+ iNumErr += EqnTest(_T("10+0xff"), 265, true);
+ iNumErr += EqnTest(_T("0xff+10"), 265, true);
+ iNumErr += EqnTest(_T("10*0xff"), 2550, true);
+ iNumErr += EqnTest(_T("0xff*10"), 2550, true);
+ iNumErr += EqnTest(_T("10+0xff+1"), 266, true);
+ iNumErr += EqnTest(_T("1+0xff+10"), 266, true);
+
+ // ...
+ iNumErr += EqnTest(_T("exp(ln(7))"), (float_type)7.0, true);
+ iNumErr += EqnTest(_T("e^ln(7)"), (float_type)7.0, true);
+ iNumErr += EqnTest(_T("e^(ln(7))"), (float_type)7.0, true);
+ iNumErr += EqnTest(_T("(e^(ln(7)))"), (float_type)7.0, true);
+ iNumErr += EqnTest(_T("1-(e^(ln(7)))"), (float_type)-6.0, true);
+ iNumErr += EqnTest(_T("2*(e^(ln(7)))"), (float_type)14.0, true);
+ iNumErr += EqnTest(_T("10^log(5)"), (float_type)5.0, true);
+ iNumErr += EqnTest(_T("10^log10(5)"), (float_type)5.0, true);
+ iNumErr += EqnTest(_T("2^log2(4)"), (float_type)4.0, true);
+ iNumErr += EqnTest(_T("-(sin(0)+1)"), (float_type)-1.0, true);
+ iNumErr += EqnTest(_T("-(2^1.1)"), (float_type)-2.14354692, true);
+
+ // infix + postfix operator in arguments for binary operators (Reference: Matlab)
+ iNumErr += EqnTest(_T("-sin(8){m}*6"), (float_type)-0.00593615, true);
+ iNumErr += EqnTest(_T("-sin(8){m}/6"), (float_type)-1.6489e-4, true);
+ iNumErr += EqnTest(_T("-sin(8){m}+6"), (float_type)5.99901, true);
+ iNumErr += EqnTest(_T("-sin(8){m}-6"), (float_type)-6.000989, true);
+
+ iNumErr += EqnTest(_T("(cos(2.41)/b)"), (float_type)-0.372056, true);
+
+ // long formula (Reference: Matlab)
+ iNumErr += EqnTest(
+ _T("(((-9))-e/(((((((pi-(((-7)+(-3)/4/e))))/(((-5))-2)-((pi+(-0))*(sqrt((e+e))*(-8))*(((-pi)+(-pi)-(-9)*(6*5))")
+ _T("/(-e)-e))/2)/((((sqrt(2/(-e)+6)-(4-2))+((5/(-2))/(1*(-pi)+3))/8)*pi*((pi/((-2)/(-6)*1*(-1))*(-6)+(-e)))))/")
+ _T("((e+(-2)+(-e)*((((-3)*9+(-e)))+(-9)))))))-((((e-7+(((5/pi-(3/1+pi)))))/e)/(-5))/(sqrt((((((1+(-7))))+((((-")
+ _T("e)*(-e)))-8))*(-5)/((-e)))*(-6)-((((((-2)-(-9)-(-e)-1)/3))))/(sqrt((8+(e-((-6))+(9*(-9))))*(((3+2-8))*(7+6")
+ _T("+(-5))+((0/(-e)*(-pi))+7)))+(((((-e)/e/e)+((-6)*5)*e+(3+(-5)/pi))))+pi))/sqrt((((9))+((((pi))-8+2))+pi))/e")
+ _T("*4)*((-5)/(((-pi))*(sqrt(e)))))-(((((((-e)*(e)-pi))/4+(pi)*(-9)))))))+(-pi)"), (float_type)-12.23016549, true);
+
+ // long formula (Reference: Matlab)
+ iNumErr += EqnTest(_T("1+2-3*4/5^6*(2*(1-5+(3*7^9)*(4+6*7-3)))+12"), (float_type)-7995810.09926, true);
+
+ /* <ibg 20100321 atan currently unsupported/>
+
+ // long formula (Reference: Matlab)
+ iNumErr += EqnTest(
+ "(atan(sin((((((((((((((((pi/cos((a/((((0.53-b)-pi)*e)/b))))+2.51)+a)-0.54)/0.98)+b)*b)+e)/a)+b)+a)+b)+pi)/e"
+ ")+a)))*2.77)", -2.16995656, true);
+ */
+
+ Assessment(iNumErr);
+ return iNumErr;
+ }
+
+
+ //---------------------------------------------------------------------------
+ int ParserTester::TestNames()
+ {
+ int iStat= 0;
+
+ *m_stream << "testing name restriction enforcement...";
+
+ ParserX p;
+
+#define PARSER_THROWCHECK(DOMAIN, FAIL, EXPR, ARG) \
+ iErr = 0; \
+ ParserTester::c_iCount++; \
+ try \
+ { \
+ p.Define##DOMAIN(EXPR, ARG); \
+ } \
+ catch(Parser::exception_type&) \
+ { \
+ iErr = (FAIL==false) ? 0 : 1; \
+ } \
+ iStat += iErr;
+
+ // constant names
+// PARSER_THROWCHECK(Const, false, "0a", 1)
+// PARSER_THROWCHECK(Const, false, "9a", 1)
+// PARSER_THROWCHECK(Const, false, "+a", 1)
+// PARSER_THROWCHECK(Const, false, "-a", 1)
+// PARSER_THROWCHECK(Const, false, "a-", 1)
+// PARSER_THROWCHECK(Const, false, "a*", 1)
+// PARSER_THROWCHECK(Const, false, "a?", 1)
+// PARSER_THROWCHECK(Const, false, "a?", 1)
+// PARSER_THROWCHECK(Const, false, "a?", 1)
+// PARSER_THROWCHECK(Const, true, "a", 1)
+// PARSER_THROWCHECK(Const, true, "a_min", 1)
+// PARSER_THROWCHECK(Const, true, "a_min0", 1)
+// PARSER_THROWCHECK(Const, true, "a_min9", 1)
+// // variable names
+// Parser::value_type a;
+// p.ClearConst();
+// PARSER_THROWCHECK(Var, false, "9a", &a)
+// PARSER_THROWCHECK(Var, false, "0a", &a)
+// PARSER_THROWCHECK(Var, false, "+a", &a)
+// PARSER_THROWCHECK(Var, false, "-a", &a)
+// PARSER_THROWCHECK(Var, false, "?a", &a)
+// PARSER_THROWCHECK(Var, false, "!a", &a)
+// PARSER_THROWCHECK(Var, false, "a+", &a)
+// PARSER_THROWCHECK(Var, false, "a-", &a)
+// PARSER_THROWCHECK(Var, false, "a*", &a)
+// PARSER_THROWCHECK(Var, false, "a?", &a)
+// PARSER_THROWCHECK(Var, true, "a", &a)
+// PARSER_THROWCHECK(Var, true, "a_min", &a)
+// PARSER_THROWCHECK(Var, true, "a_min0", &a)
+// PARSER_THROWCHECK(Var, true, "a_min9", &a)
+// PARSER_THROWCHECK(Var, false, "a_min9", 0)
+// // Postfix operators
+// // fail
+// PARSER_THROWCHECK(PostfixOprt, false, "(k", f1of1)
+// PARSER_THROWCHECK(PostfixOprt, false, "9+", f1of1)
+// PARSER_THROWCHECK(PostfixOprt, false, "+", 0)
+// // pass
+// PARSER_THROWCHECK(PostfixOprt, true, "-a", f1of1)
+// PARSER_THROWCHECK(PostfixOprt, true, "?a", f1of1)
+// PARSER_THROWCHECK(PostfixOprt, true, "_", f1of1)
+// PARSER_THROWCHECK(PostfixOprt, true, "#", f1of1)
+// PARSER_THROWCHECK(PostfixOprt, true, "&&", f1of1)
+// PARSER_THROWCHECK(PostfixOprt, true, "||", f1of1)
+// PARSER_THROWCHECK(PostfixOprt, true, "&", f1of1)
+// PARSER_THROWCHECK(PostfixOprt, true, "|", f1of1)
+// PARSER_THROWCHECK(PostfixOprt, true, "++", f1of1)
+// PARSER_THROWCHECK(PostfixOprt, true, "--", f1of1)
+// PARSER_THROWCHECK(PostfixOprt, true, "?>", f1of1)
+// PARSER_THROWCHECK(PostfixOprt, true, "?<", f1of1)
+// PARSER_THROWCHECK(PostfixOprt, true, "**", f1of1)
+// PARSER_THROWCHECK(PostfixOprt, true, "xor", f1of1)
+// PARSER_THROWCHECK(PostfixOprt, true, "and", f1of1)
+// PARSER_THROWCHECK(PostfixOprt, true, "or", f1of1)
+// PARSER_THROWCHECK(PostfixOprt, true, "not", f1of1)
+// PARSER_THROWCHECK(PostfixOprt, true, "!", f1of1)
+// // Binary operator
+// // The following must fail with builtin operators activated
+// // p.EnableBuiltInOp(true); -> this is the default
+// PARSER_THROWCHECK(Oprt, false, "+", f1of2)
+// PARSER_THROWCHECK(Oprt, false, "-", f1of2)
+// PARSER_THROWCHECK(Oprt, false, "*", f1of2)
+// PARSER_THROWCHECK(Oprt, false, "/", f1of2)
+// // without activated built in operators it should work
+// p.EnableBuiltInOprt(false);
+// PARSER_THROWCHECK(Oprt, true, "+", f1of2)
+// PARSER_THROWCHECK(Oprt, true, "-", f1of2)
+// PARSER_THROWCHECK(Oprt, true, "*", f1of2)
+// PARSER_THROWCHECK(Oprt, true, "/", f1of2)
+//
+#undef PARSER_THROWCHECK
+
+ if (iStat==0)
+ *m_stream << "passed" << endl;
+ else
+ *m_stream << "\n failed with " << iStat << " errors" << endl;
+
+ return iStat;
+ }
+
+ //---------------------------------------------------------------------------
+ void ParserTester::AddTest(testfun_type a_pFun)
+ {
+ m_vTestFun.push_back(a_pFun);
+ }
+
+ //---------------------------------------------------------------------------
+ void ParserTester::Run()
+ {
+ int iStat = 0;
+ try
+ {
+ for (int i=0; i<(int)m_vTestFun.size(); ++i)
+ iStat += (this->*m_vTestFun[i])();
+ }
+ catch(ParserError &e)
+ {
+ *m_stream << e.GetMsg() << endl;
+ *m_stream << e.GetToken() << endl;
+ Abort();
+ }
+ catch(std::exception &e)
+ {
+ *m_stream << e.what() << endl;
+ Abort();
+ }
+ catch(...)
+ {
+ *m_stream << _T("Internal error");
+ Abort();
+ }
+
+ if (iStat==0)
+ {
+ *m_stream << _T("Test passed (") << ParserTester::c_iCount << _T(" expressions)") << endl;
+ }
+ else
+ {
+ *m_stream << _T("Test failed with ") << iStat
+ << _T(" errors (") << ParserTester::c_iCount
+ << _T(" expressions)") << endl;
+ }
+ ParserTester::c_iCount = 0;
+
+#ifdef MUP_LEAKAGE_REPORT
+ // All tokens must have been destroyed by now, verify this
+ IToken::LeakageReport();
+#endif
+ }
+
+
+ //---------------------------------------------------------------------------
+ int ParserTester::ThrowTest(const string_type &a_sExpr, int a_nErrc, int a_nPos)
+ {
+ bool a_bFail = true;
+ ParserTester::c_iCount++;
+
+ try
+ {
+ ParserX p;
+
+ // Add variables
+ Value vVarVal[] = { 1, 2, 3, -2};
+ p.DefineVar( _T("a"), Variable(&vVarVal[0]) );
+ p.DefineVar( _T("b"), Variable(&vVarVal[1]) );
+ p.DefineVar( _T("c"), Variable(&vVarVal[2]) );
+ p.DefineVar( _T("d"), Variable(&vVarVal[3]) );
+
+ // array variables
+ Value aVal1(3, 0);
+ aVal1.At(0) = (float_type)1.0;
+ aVal1.At(1) = (float_type)2.0;
+ aVal1.At(2) = (float_type)3.0;
+
+ Value aVal2(3, 0);
+ aVal2.At(0) = (float_type)4.0;
+ aVal2.At(1) = (float_type)3.0;
+ aVal2.At(2) = (float_type)2.0;
+
+ Value aVal3(4, 0);
+ aVal3.At(0) = (float_type)4.0;
+ aVal3.At(1) = (float_type)3.0;
+ aVal3.At(2) = (float_type)2.0;
+ aVal3.At(3) = (float_type)5.0;
+
+ Value aVal4(4, 0);
+ aVal4.At(0) = (float_type)4.0;
+ aVal4.At(1) = false;
+ aVal4.At(2) = _T("hallo");
+
+ // Matrix variables
+ Value m1(3, 3, 0);
+ m1.At(0, 0) = 1;
+ m1.At(1, 1) = 1;
+ m1.At(2, 2) = 1;
+
+ Value m2(3, 3, 0);
+ m2.At(0, 0) = 1; m2.At(0, 1) = 2; m2.At(0, 2) = 3;
+ m2.At(1, 0) = 4; m2.At(1, 1) = 5; m2.At(1, 2) = 6;
+ m2.At(2, 0) = 7; m2.At(2, 1) = 8; m2.At(2, 2) = 9;
+
+ p.DefineVar(_T("m1"), Variable(&m1));
+ p.DefineVar(_T("m2"), Variable(&m2));
+ p.DefineVar(_T("va"), Variable(&aVal1));
+ p.DefineVar(_T("vb"), Variable(&aVal2));
+ p.DefineVar(_T("vc"), Variable(&aVal3));
+ p.DefineVar(_T("vd"), Variable(&aVal4));
+
+ p.SetExpr(a_sExpr);
+ Value fRes = p.Eval();
+ }
+ catch(ParserError &e)
+ {
+ // output the formula in case of an failed test
+ if (a_nErrc!=e.GetCode() )
+ {
+ *m_stream << _T("\n ")
+ << _T("Expression: \"") << a_sExpr
+ << _T("\" Code:") << e.GetCode()
+ << _T(" Expected:") << a_nErrc;
+ }
+
+ // Check whether the error is reported at the correct expression position
+ if (a_nPos!=-1 && a_nPos!=e.GetPos())
+ {
+ *m_stream << _T("\n ")
+ << _T("Invalid error position: \"") << a_sExpr
+ << _T("\" Pos:") << e.GetPos()
+ << _T(" Expected:") << a_nPos;
+ }
+
+ return (a_nErrc==e.GetCode() && (a_nPos==-1 || a_nPos==e.GetPos()) ) ? 0 : 1;
+ }
+
+ *m_stream << _T("\n ")
+ << _T("Expression failed: \"")
+ << a_sExpr
+ << _T("\" (no exception raised).");
+
+ return 1;
+ }
+
+ //---------------------------------------------------------------------------
+ int ParserTester::EqnTest(const string_type &a_str, Value a_val, bool a_fPass, int nExprVar)
+ {
+ ParserTester::c_iCount++;
+ int iRet(1);
+ Value fVal[5];
+
+ try
+ {
+ // p1 is a pointer since I'm going to delete it in order to test if
+ // parsers after copy construction still refer to members of the deleted object.
+ // !! If this is the case this function will crash !!
+ std::auto_ptr<ParserX> p1(new ParserX());
+
+ // Add variables
+ Value vVarVal[] = { 1, 2, 3, -2, -1};
+
+ // m1 ist die Einheitsmatrix
+ Value m1(3, 3, 0);
+ m1.At(0, 0) = 1;
+ m1.At(1, 1) = 1;
+ m1.At(2, 2) = 1;
+
+ // m2 ist die Einheitsmatrix
+ Value m2(3, 3, 0);
+ m2.At(0, 0) = 1; m2.At(0, 1) = 2; m2.At(0, 2) = 3;
+ m2.At(1, 0) = 4; m2.At(1, 1) = 5; m2.At(1, 2) = 6;
+ m2.At(2, 0) = 7; m2.At(2, 1) = 8; m2.At(2, 2) = 9;
+
+ p1->DefineOprt(new DbgSillyAdd);
+ p1->DefineFun(new FunTest0);
+
+ p1->DefineVar( _T("a"), Variable(&vVarVal[0]) );
+ p1->DefineVar( _T("b"), Variable(&vVarVal[1]) );
+ p1->DefineVar( _T("c"), Variable(&vVarVal[2]) );
+ p1->DefineVar( _T("d"), Variable(&vVarVal[3]) );
+ p1->DefineVar( _T("f"), Variable(&vVarVal[4]) );
+ p1->DefineVar( _T("m1"), Variable(&m1) );
+ p1->DefineVar( _T("m2"), Variable(&m2) );
+
+ // Add constants
+ p1->DefineConst(_T("pi"), (float_type)MUP_CONST_PI);
+ p1->DefineConst(_T("e"), (float_type)MUP_CONST_E);
+ p1->DefineConst(_T("const"), 1);
+ p1->DefineConst(_T("const1"), 2);
+ p1->DefineConst(_T("const2"), 3);
+
+ // some vector variables
+ Value aVal1(3, 0);
+ aVal1.At(0) = (float_type)1.0;
+ aVal1.At(1) = (float_type)2.0;
+ aVal1.At(2) = (float_type)3.0;
+
+ Value aVal2(3, 0);
+ aVal2.At(0) = (float_type)4.0;
+ aVal2.At(1) = (float_type)3.0;
+ aVal2.At(2) = (float_type)2.0;
+ p1->DefineVar(_T("va"), Variable(&aVal1));
+ p1->DefineVar(_T("vb"), Variable(&aVal2));
+
+ // complex variables
+ Value cVal[3];
+ cVal[0] = mup::cmplx_type(1, 1);
+ cVal[1] = mup::cmplx_type(2, 3);
+ cVal[2] = mup::cmplx_type(3, 4);
+ p1->DefineVar(_T("ca"), Variable(&cVal[0]));
+ p1->DefineVar(_T("cb"), Variable(&cVal[1]));
+ p1->DefineVar(_T("cc"), Variable(&cVal[2]));
+
+ p1->SetExpr(a_str);
+
+ fVal[0] = p1->Eval();
+
+ // Test copy and assignement operators
+ std::vector<ParserX> vParser;
+ vParser.push_back(*p1); // Push p1 into the vector
+ ParserX p2 = vParser[0]; // take parser from vector
+
+ // destroy the originals from p2
+ vParser.clear(); // delete the vector
+ p1.reset(0); // delete the original
+
+ fVal[1] = p2.Eval(); // If copy constructions does not work
+ // we may see a crash here
+
+ // Test assignement operator
+ // additionally disable Optimizer this time
+ ParserX p3;
+ p3 = p2;
+ fVal[2] = p3.Eval(); // If assignment does not work
+ // we may see a crash here
+
+ // Calculating a second time will parse from rpn rather than from
+ // string. The result must be the same...
+ fVal[3] = p3.Eval();
+
+ // Calculate yet another time. There is the possibility of
+ // changing variables as a side effect of expression
+ // evaluation. So there are really bugs that could make this fail...
+ fVal[4] = p3.Eval();
+
+ // Check i number of used variables is correct
+ if (nExprVar!=-1)
+ {
+ int n2 = p2.GetExprVar().size();
+ int n3 = p3.GetExprVar().size();
+
+ if (n2+n3!=2*n2 || n2!=nExprVar)
+ {
+ *m_stream << _T(" Number of expression variables is incorrect. (expected: ")
+ << nExprVar << _T("; detected: ") << n2 << _T(")");
+ }
+ }
+
+ // Check the three results
+ // 1.) Types must be identic
+ bool bStat = fVal[0].GetType()==fVal[1].GetType() &&
+ fVal[0].GetType()==fVal[2].GetType() &&
+ fVal[0].GetType()==fVal[3].GetType() &&
+ fVal[0].GetType()==fVal[4].GetType();
+ char_type cType = fVal[1].GetType();
+ if (!bStat)
+ {
+ *m_stream << _T("\n ") << a_str << _T(" : inconsistent result type (")
+ << fVal[0].GetType() << _T(", ")
+ << fVal[1].GetType() << _T(", ")
+ << fVal[2].GetType() << _T(", ")
+ << fVal[3].GetType() << _T(", ")
+ << fVal[4].GetType() << _T(")");
+ return 1;
+ }
+
+ // Compare the results
+ switch(cType)
+ {
+ case 'i':
+ case 'b':
+ case 's': bStat = (a_val==fVal[0] &&
+ a_val==fVal[1] &&
+ a_val==fVal[2] &&
+ a_val==fVal[3] &&
+ a_val==fVal[4]);
+ break;
+
+ // We need more attention for comaring float values due to floating point
+ // inaccuracies.
+ case 'f':
+ {
+ bStat = true;
+ int num = sizeof(fVal)/sizeof(Value);
+ for (int i=0; i<num; ++i)
+ bStat &= (fabs(a_val.GetFloat()-fVal[i].GetFloat()) <= fabs(fVal[i].GetFloat()*0.0001));
+ }
+ break;
+
+ case 'c':
+ {
+ bStat = true;
+ int num = sizeof(fVal)/sizeof(Value);
+ for (int i=0; i<num; ++i)
+ {
+ bStat &= (fabs(a_val.GetFloat()- fVal[i].GetFloat()) <= std::max((float_type)1e-15, fabs(fVal[i].GetFloat() * (float_type)0.0000001)));
+ bStat &= (fabs(a_val.GetImag() - fVal[i].GetImag()) <= std::max((float_type)1e-15, fabs(fVal[i].GetImag() * (float_type)0.0000001)));
+ }
+ }
+ break;
+
+ case 'm':
+ {
+ bStat = true;
+ int num = sizeof(fVal)/sizeof(Value);
+
+ for (int i=0; i<num; ++i)
+ {
+ struct CheckArray
+ {
+ CheckArray()
+ {}
+
+ bool Check(IValue &v1, IValue &v2)
+ {
+ if (v1.GetType()!=v2.GetType())
+ return false;
+
+ if (v1.GetRows()!=v2.GetRows())
+ return false;
+
+ if (v1.IsMatrix())
+ {
+
+ bool bCheck = true;
+ for (int i=0; i<v1.GetRows(); ++i)
+ {
+ if (!Check(v1.At(i), v2.At(i)))
+ return false;
+ }
+
+ return true;
+ }
+ else
+ {
+ return (fabs(v1.GetFloat()- v2.GetFloat()) <= std::max((float_type)1e-15, fabs(v1.GetFloat() * (float_type)0.0000001)));
+ }
+ }
+ } checker;
+
+ bStat = checker.Check(a_val, fVal[i]);
+ if (!bStat)
+ break;
+ }
+ }
+ break;
+
+ default:
+ throw std::runtime_error("Parser return value has an unexpected typecode.");
+ }
+
+ iRet = (bStat==a_fPass) ? 0 : 1;
+ }
+ catch(ParserError &e)
+ {
+ *m_stream << _T("\n ") << a_str << _T(" : ") << e.GetMsg();
+ return 1;
+ }
+ catch(std::exception &e)
+ {
+ *m_stream << _T("\n ") << a_str << _T(" : ") << e.what() << _T("\n");
+ return 1;
+ }
+ catch(...)
+ {
+ *m_stream << _T("\n \"") << a_str << _T("\" : ") << _T("Unexpected Eception");
+ return 1;
+ }
+
+ if (iRet)
+ {
+ *m_stream << _T("\n ") << a_str << _T(" : ") << _T("(at least one incorrect result ")
+ << fVal[0] << _T(", ")
+ << fVal[1] << _T(", ")
+ << fVal[2] << _T(", ")
+ << fVal[3] << _T(", ")
+ << fVal[4] << _T("; expected=") << a_val << _T(")");
+ }
+
+ return iRet;
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Internal error in test class Test is going to be aborted. */
+ void ParserTester::Abort() const
+ {
+ *m_stream << _T("\nTest failed (internal error in test class)") << endl;
+ while (!getchar());
+ exit(-1);
+ }
+
+ //---------------------------------------------------------------------------
+ void ParserTester::Assessment(int a_iNumErr) const
+ {
+ if (a_iNumErr==0)
+ *m_stream << _T("passed") << endl;
+ else
+ *m_stream << _T("\n failed with ") << a_iNumErr << _T(" errors") << endl;
+ }
+MUP_NAMESPACE_END
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpTest.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpTest.h Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,101 @@
+/*
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2011 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+*/
+#ifndef MU_PARSER_TEST_H
+#define MU_PARSER_TEST_H
+
+#include <string>
+#include <numeric> // for accumulate
+#include "mpParser.h"
+#include "mpOprtBinCommon.h"
+
+
+MUP_NAMESPACE_START
+
+MUP_BINARY_OPERATOR(DbgSillyAdd, _T("++"), float_type, _T(""), 3, oaLEFT, a+b)
+
+ /** \brief Test cases for unit testing the parser framework.
+
+ (C) 2011 Ingo Berg
+ */
+ class ParserTester // final
+ {
+ private:
+ static int c_iCount;
+
+ int TestParserValue();
+ int TestNames();
+ int TestErrorCodes();
+ int TestStringFun();
+ int TestVector();
+ int TestBinOp();
+ int TestPostfix();
+ int TestInfix();
+ int TestEqn();
+ int TestMultiArg();
+ int TestUndefVar();
+ int TestIfElse();
+ int TestMultiLine();
+ int TestMatrix();
+ int TestComplex();
+
+ void Assessment(int a_iNumErr) const;
+ void Abort() const;
+
+ public:
+ typedef int (ParserTester::*testfun_type)();
+
+ ParserTester();
+
+ /** \brief Destructor (trivial). */
+ ~ParserTester() {};
+
+ /** \brief Copy constructor is deactivated. */
+ ParserTester(const ParserTester &a_Obj)
+ :m_vTestFun()
+ ,m_stream(a_Obj.m_stream)
+ {};
+
+ void Run();
+
+ private:
+ std::vector<testfun_type> m_vTestFun;
+
+#if defined(_UNICODE)
+ std::wostream *m_stream;
+#else
+ std::ostream *m_stream;
+#endif
+
+ void AddTest(testfun_type a_pFun);
+
+ // Test Double Parser
+ int EqnTest(const string_type &a_str, Value a_val, bool a_fPass, int nExprVar = -1);
+ int ThrowTest(const string_type &a_str, int a_nErrc, int a_nPos = -1);
+ }; // ParserTester
+} // namespace mu
+
+#endif
+
+
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpTokenReader.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpTokenReader.cpp Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,944 @@
+/** \file
+ \brief Implementation of the token reader used to break the expression string up
+ into tokens.
+
+<pre>
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2011 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+ </pre>
+*/
+
+#include "mpTokenReader.h"
+
+#include <cassert>
+
+#include "mpParserBase.h"
+#include "mpIValReader.h"
+#include "mpIfThenElse.h"
+#include "mpScriptTokens.h"
+#include "mpOprtIndex.h"
+
+
+MUP_NAMESPACE_START
+
+ //---------------------------------------------------------------------------
+ /** \brief Copy constructor.
+ \sa Assign
+ \throw nothrow
+ */
+ TokenReader::TokenReader(const TokenReader &a_Reader)
+ {
+ Assign(a_Reader);
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Assignement operator.
+ \param a_Reader Object to copy to this token reader.
+ \throw nothrow
+
+ Self assignement will be suppressed otherwise #Assign is called.
+ */
+ TokenReader& TokenReader::operator=(const TokenReader &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 TokenReader::Assign(const TokenReader &obj)
+ {
+ m_pParser = obj.m_pParser;
+ m_sExpr = obj.m_sExpr;
+ m_nPos = obj.m_nPos;
+ m_nNumBra = obj.m_nNumBra;
+ m_nNumIndex = obj.m_nNumIndex;
+ m_nNumIfElse = obj.m_nNumIfElse;
+ m_nSynFlags = obj.m_nSynFlags;
+ m_UsedVar = obj.m_UsedVar;
+ m_pVarDef = obj.m_pVarDef;
+ m_pPostOprtDef = obj.m_pPostOprtDef;
+ m_pInfixOprtDef = obj.m_pInfixOprtDef;
+ m_pOprtDef = obj.m_pOprtDef;
+ m_pFunDef = obj.m_pFunDef;
+ m_pConstDef = obj.m_pConstDef;
+ m_pDynVarShadowValues = obj.m_pDynVarShadowValues;
+ m_vTokens = obj.m_vTokens;
+
+ // Reader klassen klonen
+ DeleteValReader();
+ std::size_t i, iSize = obj.m_vValueReader.size();
+ for (i=0; i<iSize; ++i)
+ {
+ m_vValueReader.push_back(obj.m_vValueReader[i]->Clone(this));
+ }
+ }
+
+ //---------------------------------------------------------------------------
+ /** \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.
+ */
+ TokenReader::TokenReader(ParserXBase *a_pParent)
+ :m_pParser(a_pParent)
+ ,m_sExpr()
+ ,m_nPos(0)
+ ,m_nNumBra(0)
+ ,m_nNumIndex(0)
+ ,m_nNumIfElse(0)
+ ,m_nSynFlags(0)
+ ,m_vTokens()
+ ,m_eLastTokCode(cmUNKNOWN)
+ ,m_pFunDef(NULL)
+ ,m_pOprtDef(NULL)
+ ,m_pInfixOprtDef(NULL)
+ ,m_pPostOprtDef(NULL)
+ ,m_pConstDef(NULL)
+ ,m_pDynVarShadowValues(NULL)
+ ,m_pVarDef(NULL)
+ ,m_vValueReader()
+ ,m_UsedVar()
+ ,m_fZero(0)
+ {
+ assert(m_pParser);
+ SetParent(m_pParser);
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Destructor (trivial).
+
+ \throw nothrow
+ */
+ TokenReader::~TokenReader()
+ {
+ DeleteValReader();
+ }
+
+ //---------------------------------------------------------------------------
+ void TokenReader::DeleteValReader()
+ {
+ int iSize = (int)m_vValueReader.size();
+ for (int i=0; i<iSize; ++i)
+ delete m_vValueReader[i];
+
+ m_vValueReader.clear();
+ }
+
+ //---------------------------------------------------------------------------
+ /** \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
+ */
+ TokenReader* TokenReader::Clone(ParserXBase *a_pParent) const
+ {
+ std::auto_ptr<TokenReader> ptr(new TokenReader(*this));
+ ptr->SetParent(a_pParent);
+ return ptr.release();
+ }
+
+ //---------------------------------------------------------------------------
+ void TokenReader::AddValueReader(IValueReader *a_pReader)
+ {
+ a_pReader->SetParent(this);
+ m_vValueReader.push_back(a_pReader);
+ }
+
+ //---------------------------------------------------------------------------
+ void TokenReader::AddSynFlags(int flag)
+ {
+ m_nSynFlags |= flag;
+ }
+
+ //---------------------------------------------------------------------------
+ const TokenReader::token_buf_type& TokenReader::GetTokens() const
+ {
+ return m_vTokens;
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Return the current position of the token reader in the formula string.
+
+ \return #m_nPos
+ \throw nothrow
+ */
+ int TokenReader::GetPos() const
+ {
+ return m_nPos;
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Return a reference to the formula.
+
+ \return #m_sExpr
+ \throw nothrow
+ */
+ const string_type& TokenReader::GetExpr() const
+ {
+ return m_sExpr;
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Return a map containing the used variables only. */
+ const var_maptype& TokenReader::GetUsedVar() const
+ {
+ return m_UsedVar;
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Initialize the token Reader.
+
+ Sets the expression position index to zero and set Syntax flags to
+ default for initial parsing.
+ */
+ void TokenReader::SetExpr(const string_type &a_sFormula)
+ {
+ m_sExpr = a_sFormula;
+ m_vTokens.clear();
+ ReInit();
+ }
+
+
+ //---------------------------------------------------------------------------
+ /** \brief Reset the token reader to the start of the formula.
+ \post #m_nPos==0, #m_nSynFlags = noOPT | noBC | noPOSTOP | noSTR
+ \throw nothrow
+ \sa ESynCodes
+
+ The syntax flags will be reset to a value appropriate for the
+ start of a formula.
+ */
+ void TokenReader::ReInit()
+ {
+ m_nPos = 0;
+ m_nNumBra = 0;
+ m_nNumIndex = 0;
+ m_nNumIfElse = 0;
+ m_nSynFlags = noOPT | noBC | noPFX | noCOMMA | noIO | noIC | noIF | noELSE;
+ m_UsedVar.clear();
+ m_eLastTokCode = cmUNKNOWN;
+ }
+
+ //---------------------------------------------------------------------------
+ const ptr_tok_type& TokenReader::Store(const ptr_tok_type &t, int token_pos)
+ {
+ m_eLastTokCode = t->GetCode();
+ t->SetExprPos(token_pos);
+ m_vTokens.push_back(t);
+ return t;
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Read the next token from the string. */
+ ptr_tok_type TokenReader::ReadNextToken()
+ {
+ assert(m_pParser);
+ const char_type *szFormula = m_sExpr.c_str();
+
+ while (szFormula[m_nPos]==' ')
+ ++m_nPos;
+
+ int token_pos = m_nPos;
+
+ ptr_tok_type pTok;
+
+ // Check for end of expression
+ if (IsEOF(pTok))
+ return Store(pTok, token_pos);
+
+ if (IsNewline(pTok))
+ return Store(pTok, token_pos);
+
+ if ( !(m_nSynFlags & noOPT) && IsOprt(pTok))
+ return Store(pTok, token_pos); // Check for user defined binary operator
+
+ if ( !(m_nSynFlags & noIFX) && IsInfixOpTok(pTok))
+ return Store(pTok, token_pos); // Check for unary operators
+
+ if (IsValTok(pTok))
+ return Store(pTok, token_pos); // Check for values / constant tokens
+
+ if (IsBuiltIn(pTok))
+ return Store(pTok, token_pos); // Check built in operators / tokens
+
+ if (IsVarOrConstTok(pTok))
+ return Store(pTok, token_pos); // Check for variable tokens
+
+ if (IsFunTok(pTok))
+ return Store(pTok, token_pos);
+
+ if ( !(m_nSynFlags & noPFX) && IsPostOpTok(pTok))
+ return Store(pTok, token_pos); // Check for unary operators
+
+ // 2.) We have found no token, maybe there is a token that we don't expect here.
+ // Again call the Identifier functions but this time only those we don't expect
+ // to find.
+ if ( (m_nSynFlags & noOPT) && IsOprt(pTok))
+ return Store(pTok, token_pos); // Check for user defined binary operator
+
+ if ( (m_nSynFlags & noIFX) && IsInfixOpTok(pTok))
+ return Store(pTok, token_pos); // Check for unary operators
+
+ if ( (m_nSynFlags & noPFX) && IsPostOpTok(pTok))
+ return Store(pTok, token_pos); // Check for unary operators
+ // </ibg>
+
+ // Now we are in trouble because there is something completely unknown....
+
+ // Check the string for an undefined variable token. This is 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 GetExprVar function must supress the error for undefined
+ // variables in order to collect all variable names including the
+ // undefined ones.
+ if ( (m_pParser->m_bIsQueryingExprVar || m_pParser->m_bAutoCreateVar) && IsUndefVarTok(pTok) )
+ return Store(pTok, token_pos);
+
+ // Check for unknown token
+ //
+ // !!! From this point on there is no exit without an exception possible...
+ //
+ string_type sTok;
+ int iEnd = ExtractToken(m_pParser->ValidNameChars(), sTok, m_nPos);
+
+ ErrorContext err;
+ err.Errc = ecUNASSIGNABLE_TOKEN;
+ err.Expr = m_sExpr;
+ err.Pos = m_nPos;
+
+ if (iEnd!=m_nPos)
+ err.Ident = sTok;
+ else
+ err.Ident = m_sExpr.substr(m_nPos);
+
+ throw ParserError(err);
+ }
+
+ //---------------------------------------------------------------------------
+ void TokenReader::SetParent(ParserXBase *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_pConstDef = &a_pParent->m_valConst;
+ m_pDynVarShadowValues = &a_pParent->m_valDynVarShadow;
+ }
+
+ //---------------------------------------------------------------------------
+ /** \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 TokenReader::ExtractToken(const char_type *a_szCharSet,
+ string_type &a_sTok,
+ int a_iPos) const
+ {
+ int iEnd = (int)m_sExpr.find_first_not_of(a_szCharSet, a_iPos);
+
+ if (iEnd==(int)string_type::npos)
+ iEnd = (int)m_sExpr.length();
+
+ if (iEnd!=a_iPos)
+ a_sTok.assign(m_sExpr.begin()+a_iPos, m_sExpr.begin()+iEnd);
+
+ return iEnd;
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Check if a built in operator or other token can be found.
+ */
+ bool TokenReader::IsBuiltIn(ptr_tok_type &a_Tok)
+ {
+ const char_type **pOprtDef = m_pParser->GetOprtDef(),
+ *szFormula = m_sExpr.c_str();
+ int i;
+
+ try
+ {
+ // Compare token with function and operator strings
+ // check string for operator/function
+ for (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_nPos, szFormula + m_nPos + len) )
+ {
+ switch(i)
+ {
+ case cmARG_SEP:
+ if (m_nSynFlags & noCOMMA)
+ throw ecUNEXPECTED_COMMA;
+
+ m_nSynFlags = noBC | noOPT | noEND | noNEWLINE | noCOMMA | noPFX | noIC | noIO | noIF | noELSE;
+ a_Tok = ptr_tok_type(new GenericToken((ECmdCode)i, pOprtDef[i]));
+ break;
+
+ case cmELSE:
+ if (m_nSynFlags & noELSE)
+ throw ecUNEXPECTED_CONDITIONAL;
+
+ m_nNumIfElse--;
+ if (m_nNumIfElse<0)
+ throw ecMISPLACED_COLON;
+
+ m_nSynFlags = noBC | noIO | noIC | noPFX | noEND | noNEWLINE | noCOMMA | noOPT | noIF | noELSE;
+ a_Tok = ptr_tok_type(new TokenIfThenElse(cmELSE));
+ break;
+
+ case cmIF:
+ if (m_nSynFlags & noIF)
+ throw ecUNEXPECTED_CONDITIONAL;
+
+ m_nNumIfElse++;
+ m_nSynFlags = noBC | noIO | noPFX | noIC | noEND | noNEWLINE | noCOMMA | noOPT | noIF | noELSE;
+ a_Tok = ptr_tok_type(new TokenIfThenElse(cmIF));
+ break;
+
+ case cmBO:
+ if (m_nSynFlags & noBO)
+ throw ecUNEXPECTED_PARENS;
+
+ if (m_eLastTokCode==cmFUNC)
+ m_nSynFlags = noOPT | noEND | noNEWLINE | noCOMMA | noPFX | noIC | noIO | noIF | noELSE;
+ else
+ m_nSynFlags = noBC | noOPT | noEND | noNEWLINE | noCOMMA | noPFX | noIC | noIO | noIF | noELSE;
+
+ m_nNumBra++;
+ a_Tok = ptr_tok_type(new GenericToken((ECmdCode)i, pOprtDef[i]));
+ break;
+
+ case cmBC:
+ if (m_nSynFlags & noBC)
+ throw ecUNEXPECTED_PARENS;
+
+ m_nSynFlags = noBO | noVAR | noVAL | noFUN | noIFX | noIO;
+ m_nNumBra--;
+
+ if (m_nNumBra<0)
+ throw ecUNEXPECTED_PARENS;
+
+ a_Tok = ptr_tok_type(new GenericToken((ECmdCode)i, pOprtDef[i]));
+ break;
+
+ case cmIO:
+ if (m_nSynFlags & noIO)
+ throw ecUNEXPECTED_SQR_BRACKET;
+
+ m_nSynFlags = noIC | noIO | noOPT | noPFX | noBC | noNEWLINE;
+ m_nNumIndex++;
+ a_Tok = ptr_tok_type(new GenericToken((ECmdCode)i, pOprtDef[i]));
+ break;
+
+ case cmIC:
+ if (m_nSynFlags & noIC)
+ throw ecUNEXPECTED_SQR_BRACKET;
+
+ m_nSynFlags = noBO | noIFX;
+ m_nNumIndex--;
+
+ if (m_nNumIndex<0)
+ throw ecUNEXPECTED_SQR_BRACKET;
+
+// a_Tok = ptr_tok_type(new GenericToken((ECmdCode)i, pOprtDef[i]));
+ a_Tok = ptr_tok_type(new OprtIndex());
+ break;
+
+ default: // The operator is listed in c_DefaultOprt, but not here. This is a bad thing...
+ throw ecINTERNAL_ERROR;
+ } // switch operator id
+
+ m_nPos += (int)len;
+ return true;
+ } // if operator string found
+ } // end of for all operator strings
+ }
+ catch (EErrorCodes e)
+ {
+ ErrorContext err;
+ err.Errc = e;
+ err.Expr = m_sExpr;
+ err.Ident = pOprtDef[i];
+ err.Pos = m_nPos;
+ throw ParserError(err);
+ }
+
+ return false;
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Check for End of expression
+ */
+ bool TokenReader::IsNewline(ptr_tok_type &a_Tok)
+ {
+ // nicht nach: bionop, infixop, argumentseparator,
+ // erlaubt nach: Werten, variablen, schließenden klammern, schliessendem index
+ bool bRet(false);
+ try
+ {
+ if ( m_sExpr[m_nPos]=='\n')
+ {
+ // Check if all brackets were closed
+ if ( m_nSynFlags & noNEWLINE )
+ throw ecUNEXPECTED_NEWLINE;
+
+ if (m_nNumBra>0)
+ throw ecMISSING_PARENS;
+
+ if (m_nNumIndex>0)
+ throw ecMISSING_SQR_BRACKET;
+
+ if (m_nNumIfElse>0)
+ throw(ecMISSING_ELSE_CLAUSE);
+
+ m_nPos++;
+ m_nSynFlags = sfSTART_OF_LINE;
+ a_Tok = ptr_tok_type(new TokenNewline());
+ bRet = true;
+ }
+ }
+ catch(EErrorCodes e)
+ {
+ ErrorContext err;
+ err.Errc = e;
+ err.Ident = _T("");
+ err.Expr = m_sExpr;
+ err.Pos = m_nPos;
+ throw ParserError(err);
+ }
+
+ return bRet;
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Check for End of expression
+ */
+ bool TokenReader::IsEOF(ptr_tok_type &a_Tok)
+ {
+ bool bRet(false);
+ try
+ {
+ if ( m_sExpr.length() && m_nPos>=(int)m_sExpr.length())
+ {
+ if ( m_nSynFlags & noEND )
+ throw ecUNEXPECTED_EOF;
+
+ if (m_nNumBra>0)
+ throw ecMISSING_PARENS;
+
+ if (m_nNumIndex>0)
+ throw ecMISSING_SQR_BRACKET;
+
+ if (m_nNumIfElse>0)
+ throw ecMISSING_ELSE_CLAUSE;
+
+ m_nSynFlags = 0;
+ a_Tok = ptr_tok_type(new GenericToken(cmEOE));
+ bRet = true;
+ }
+ }
+ catch(EErrorCodes e)
+ {
+ ErrorContext err;
+ err.Errc = e;
+ err.Ident = _T("");
+ err.Expr = m_sExpr;
+ err.Pos = m_nPos;
+ throw ParserError(err);
+ }
+
+ return bRet;
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Check if a string position contains a unary infix operator.
+ \return true if a function token has been found false otherwise.
+ */
+ bool TokenReader::IsInfixOpTok(ptr_tok_type &a_Tok)
+ {
+ string_type sTok;
+ int iEnd = ExtractToken(m_pParser->ValidInfixOprtChars(), sTok, m_nPos);
+
+ if (iEnd==m_nPos)
+ return false;
+
+ try
+ {
+ // iteraterate over all infix operator strings
+ oprt_ifx_maptype::const_iterator item = m_pInfixOprtDef->begin();
+ for (item=m_pInfixOprtDef->begin(); item!=m_pInfixOprtDef->end(); ++item)
+ {
+ if (sTok.find(item->first)!=0)
+ continue;
+
+ a_Tok = ptr_tok_type(item->second->Clone());
+ m_nPos += (int)item->first.length();
+
+ if (m_nSynFlags & noIFX)
+ throw ecUNEXPECTED_OPERATOR;
+
+ m_nSynFlags = noPFX | noIFX | noOPT | noBC | noIC | noIO | noEND | noCOMMA | noNEWLINE;
+ return true;
+ }
+
+ return false;
+ }
+ catch(EErrorCodes e)
+ {
+ ErrorContext err;
+ err.Errc = e;
+ err.Pos = m_nPos;
+ err.Ident = a_Tok->GetIdent();
+ err.Expr = m_sExpr;
+ throw ParserError(err);
+ }
+ }
+
+
+ //---------------------------------------------------------------------------
+ /** \brief Check expression for function tokens. */
+ bool TokenReader::IsFunTok(ptr_tok_type &a_Tok)
+ {
+ if (m_pFunDef->size()==0)
+ return false;
+
+ string_type sTok;
+ int iEnd = ExtractToken(m_pParser->ValidNameChars(), sTok, m_nPos);
+ if (iEnd==m_nPos)
+ return false;
+
+ try
+ {
+ fun_maptype::iterator item = m_pFunDef->find(sTok);
+ if (item==m_pFunDef->end())
+ return false;
+
+ m_nPos = (int)iEnd;
+ a_Tok = ptr_tok_type(item->second->Clone());
+ a_Tok->Compile(_T("xxx"));
+
+ if (m_nSynFlags & noFUN)
+ throw ecUNEXPECTED_FUN;
+
+ m_nSynFlags = sfALLOW_NONE ^ noBO;
+ return true;
+ }
+ catch(EErrorCodes e)
+ {
+ ErrorContext err;
+ err.Errc = e;
+ err.Pos = m_nPos - (int)a_Tok->GetIdent().length();
+ err.Ident = a_Tok->GetIdent();
+ err.Expr = m_sExpr;
+ throw ParserError(err);
+ }
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Check if a string position contains a unary post value operator. */
+ bool TokenReader::IsPostOpTok(ptr_tok_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_nPos);
+ if (iEnd==m_nPos)
+ return false;
+
+ try
+ {
+ // iteraterate over all postfix operator strings
+ oprt_pfx_maptype::const_iterator item;
+ for (item=m_pPostOprtDef->begin(); item!=m_pPostOprtDef->end(); ++item)
+ {
+ if (sTok.find(item->first)!=0)
+ continue;
+
+ a_Tok = ptr_tok_type(item->second->Clone());
+ m_nPos += (int)item->first.length();
+
+ if (m_nSynFlags & noPFX)
+ throw ecUNEXPECTED_OPERATOR;
+
+ m_nSynFlags = noVAL | noVAR | noFUN | noBO | noPFX | noIO;
+ return true;
+ }
+
+ return false;
+ }
+ catch(EErrorCodes e)
+ {
+ ErrorContext err;
+ err.Errc = e;
+ err.Pos = m_nPos - (int)a_Tok->GetIdent().length();
+ err.Ident = a_Tok->GetIdent();
+ err.Expr = m_sExpr;
+ throw ParserError(err);
+ }
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Check if a string position contains a binary operator. */
+ bool TokenReader::IsOprt(ptr_tok_type &a_Tok)
+ {
+ string_type sTok;
+ int iEnd = ExtractToken(m_pParser->ValidOprtChars(), sTok, m_nPos);
+ if (iEnd==m_nPos)
+ return false;
+
+ oprt_bin_multimap::reverse_iterator item;
+ try
+ {
+ // Note:
+ // All tokens in oprt_bin_maptype are have been sorted by their length
+ // Long operators must come first! Otherwise short names (like: "add") that
+ // are part of long token names (like: "add123") will be found instead
+ // of the long ones.
+ // Length sorting is done with ascending length so we use a reverse iterator here.
+ for (item=m_pOprtDef->rbegin(); item!=m_pOprtDef->rend(); ++item)
+ {
+ if (sTok.find(item->first)!=0)
+ continue;
+
+ // operator found, check if we expect one...
+ if (m_nSynFlags & 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 use the same characters in their identifiers.
+ if (IsInfixOpTok(a_Tok))
+ return true;
+
+ // nope, it's no infix operator and we dont expect
+ // an operator
+ throw ecUNEXPECTED_OPERATOR;
+ }
+ else
+ {
+ a_Tok = ptr_tok_type(item->second->Clone());
+
+ m_nPos += (int)a_Tok->GetIdent().length();
+ m_nSynFlags = noBC | noIO | noIC | noOPT | noCOMMA | noEND | noNEWLINE | noPFX;
+ return true;
+ }
+ }
+
+ return false;
+ }
+ catch(EErrorCodes e)
+ {
+ ErrorContext err;
+ err.Errc = e;
+ err.Pos = m_nPos; // - (int)item->first.length();
+ err.Ident = item->first;
+ err.Expr = m_sExpr;
+ throw ParserError(err);
+ }
+ }
+
+ //---------------------------------------------------------------------------
+ /** \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 TokenReader::IsValTok(ptr_tok_type &a_Tok)
+ {
+ if (m_vValueReader.size()==0)
+ return false;
+
+ stringstream_type stream(m_sExpr.c_str() + m_nPos);
+ string_type sTok;
+
+ try
+ {
+ // call the value recognition functions provided by the user
+ // Call user defined value recognition functions
+ int iSize = (int)m_vValueReader.size();
+ Value val;
+ for (int i=0; i<iSize; ++i)
+ {
+ int iStart = m_nPos;
+ if ( m_vValueReader[i]->IsValue(m_sExpr.c_str(), m_nPos, val) )
+ {
+ sTok.assign(m_sExpr.c_str(), iStart, m_nPos);
+ if (m_nSynFlags & noVAL)
+ throw ecUNEXPECTED_VAL;
+
+ m_nSynFlags = noVAL | noVAR | noFUN | noBO | noIFX | noIO;
+ a_Tok = ptr_tok_type(val.Clone());
+ a_Tok->SetIdent( string_type(sTok.begin(), sTok.begin()+(m_nPos-iStart)) );
+ return true;
+ }
+ }
+ }
+ catch(EErrorCodes e)
+ {
+ ErrorContext err;
+ err.Errc = e;
+ err.Pos = m_nPos;
+ err.Ident = sTok;
+ err.Expr = m_sExpr;
+ err.Pos = m_nPos - (int)sTok.length();
+ throw ParserError(err);
+ }
+
+ return false;
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Check wheter a token at a given position is a variable token.
+ \param a_Tok [out] If a variable token has been found it will be placed here.
+ \return true if a variable token has been found.
+ */
+ bool TokenReader::IsVarOrConstTok(ptr_tok_type &a_Tok)
+ {
+ if (!m_pVarDef->size() && !m_pConstDef->size() && !m_pFunDef->size())
+ return false;
+
+ string_type sTok;
+ int iEnd;
+ try
+ {
+ iEnd = ExtractToken(m_pParser->ValidNameChars(), sTok, m_nPos);
+ if (iEnd==m_nPos)
+ return false;
+
+ // Check for variables
+ var_maptype::const_iterator item = m_pVarDef->find(sTok);
+ if (item!=m_pVarDef->end())
+ {
+ if (m_nSynFlags & noVAR)
+ throw ecUNEXPECTED_VAR;
+
+ m_nPos = iEnd;
+ m_nSynFlags = noVAL | noVAR | noFUN | noBO | noIFX;
+ a_Tok = item->second;
+ a_Tok->SetIdent(sTok);
+ m_UsedVar[item->first] = item->second; // Add variable to used-var-list
+ return true;
+ }
+
+ // Check for constants
+ item = m_pConstDef->find(sTok);
+ if (item!=m_pConstDef->end())
+ {
+ if (m_nSynFlags & noVAL)
+ throw ecUNEXPECTED_VAL;
+
+ m_nPos = iEnd;
+ m_nSynFlags = noVAL | noVAR | noFUN | noBO | noIFX | noIO;
+ a_Tok = item->second;
+ a_Tok->SetIdent(sTok);
+ return true;
+ }
+
+ return false;
+ }
+ catch(EErrorCodes e)
+ {
+ ErrorContext err;
+ err.Errc = e;
+ err.Pos = m_nPos;
+ err.Ident = sTok;
+ err.Expr = m_sExpr;
+ throw ParserError(err);
+ }
+
+ return true;
+ }
+
+ //---------------------------------------------------------------------------
+ bool TokenReader::IsComment()
+ {
+ return false;
+ }
+
+ //---------------------------------------------------------------------------
+ /** \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 TokenReader::IsUndefVarTok(ptr_tok_type &a_Tok)
+ {
+ string_type sTok;
+ int iEnd = ExtractToken(m_pParser->ValidNameChars(), sTok, m_nPos);
+ if (iEnd==m_nPos)
+ return false;
+
+ if (m_nSynFlags & noVAR)
+ {
+ ErrorContext err;
+ err.Errc = ecUNEXPECTED_VAR;
+ err.Ident = sTok;
+ err.Expr = m_sExpr;
+ err.Pos = m_nPos - (int)sTok.length();
+ throw ParserError(err);
+ }
+
+ // Create a variable token
+ if (m_pParser->m_bAutoCreateVar)
+ {
+ ptr_val_type val(new Value); // Create new value token
+ m_pDynVarShadowValues->push_back(val); // push to the vector of shadow values
+ a_Tok = ptr_tok_type(new Variable(val.Get())); // bind variable to the new value item
+ (*m_pVarDef)[sTok] = a_Tok; // add new variable to the variable list
+ }
+ else
+ a_Tok = ptr_tok_type(new Variable(NULL)); // bind variable to empty variable
+
+ a_Tok->SetIdent(sTok);
+ m_UsedVar[sTok] = a_Tok; // add new variable to used-var-list
+
+ m_nPos = iEnd;
+ m_nSynFlags = noVAL | noVAR | noFUN | noBO | noIFX;
+ return true;
+ }
+} // namespace mu
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpTokenReader.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpTokenReader.h Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,130 @@
+/** \file
+ \brief Definition of the token reader used to break the expression string up
+ into tokens.
+
+<pre>
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+ </pre>
+*/
+
+#ifndef MUP_TOKEN_READER_H
+#define MUP_TOKEN_READER_H
+
+//--- Standard includes ----------------------------------------------------
+#include <cstdio>
+#include <cstring>
+#include <map>
+#include <stack>
+#include <string>
+#include <list>
+
+//--- muParserX framework --------------------------------------------------
+#include "mpIToken.h"
+#include "mpError.h"
+#include "mpStack.h"
+#include "mpFwdDecl.h"
+
+MUP_NAMESPACE_START
+
+ /** \brief Token reader for the ParserXBase class. */
+ class TokenReader
+ {
+ friend class ParserXBase;
+
+ public:
+
+ typedef std::vector<ptr_tok_type> token_buf_type;
+
+ private:
+
+ TokenReader(const TokenReader &a_Reader);
+ TokenReader& operator=(const TokenReader &a_Reader);
+ void Assign(const TokenReader &a_Reader);
+ void DeleteValReader();
+ void SetParent(ParserXBase *a_pParent);
+
+ int ExtractToken(const char_type *a_szCharSet, string_type &a_sTok, int a_iPos) const;
+
+ bool IsBuiltIn(ptr_tok_type &t);
+ bool IsEOF(ptr_tok_type &t);
+ bool IsNewline(ptr_tok_type &a_Tok);
+ bool IsNewLine(ptr_tok_type &t);
+ bool IsInfixOpTok(ptr_tok_type &t);
+ bool IsFunTok(ptr_tok_type &t);
+ bool IsPostOpTok(ptr_tok_type &t);
+ bool IsOprt(ptr_tok_type &t);
+ bool IsValTok(ptr_tok_type &t);
+ bool IsVarOrConstTok(ptr_tok_type &t);
+ bool IsUndefVarTok(ptr_tok_type &t);
+ bool IsComment();
+
+ const ptr_tok_type& Store(const ptr_tok_type &t, int pos);
+
+ ParserXBase *m_pParser; ///< Pointer to the parser bound to this token reader
+ string_type m_sExpr; ///< The expression beeing currently parsed
+ int m_nPos; ///< Current parsing position in the expression
+ int m_nNumBra; ///< Number of open parenthesis
+ int m_nNumIndex; ///< Number of open index paranethesis
+ int m_nNumIfElse; ///< Coubter for if-then-else levels
+ int m_nSynFlags; ///< Flags to controll the syntax flow
+
+ token_buf_type m_vTokens;
+ ECmdCode m_eLastTokCode;
+
+ mutable fun_maptype *m_pFunDef;
+ mutable oprt_bin_multimap *m_pOprtDef;
+ mutable oprt_ifx_maptype *m_pInfixOprtDef;
+ mutable oprt_pfx_maptype *m_pPostOprtDef;
+ mutable val_maptype *m_pConstDef;
+ val_vec_type *m_pDynVarShadowValues; ///< Value items created for holding values of variables created at parser runtime
+ var_maptype *m_pVarDef; ///< The only non const pointer to parser internals
+
+ readervec_type m_vValueReader; ///< Value token identification function
+ var_maptype m_UsedVar;
+ float_type m_fZero; ///< Dummy value of zero, referenced by undefined variables
+
+ public:
+
+ TokenReader(ParserXBase *a_pParent);
+ ~TokenReader();
+ TokenReader* Clone(ParserXBase *a_pParent) const;
+
+ void AddValueReader(IValueReader *a_pReader);
+ void AddSynFlags(int flag);
+ //void SetVarCreator(facfun_type a_pFactory);
+ int GetPos() const;
+ const string_type& GetExpr() const;
+ const var_maptype& GetUsedVar() const;
+ const token_buf_type& GetTokens() const;
+ void SetExpr(const string_type &a_sExpr);
+
+ void ReInit();
+ ptr_tok_type ReadNextToken();
+ }; // class TokenReader
+
+MUP_NAMESPACE_END
+
+#endif
+
+
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpTypes.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpTypes.h Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,313 @@
+/** \file
+ \brief Definition of basic types used by muParserX
+
+<pre>
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+</pre>
+*/
+#ifndef MUP_TYPES_H
+#define MUP_TYPES_H
+
+//--- Standard include ------------------------------------------------------
+#include <string>
+#include <iostream>
+#include <sstream>
+#include <vector>
+#include <map>
+#include <complex>
+
+//--- muParserX framework ---------------------------------------------------
+#include "suSortPred.h" // We need the string utils sorting predicates
+#include "mpDefines.h"
+#include "mpMatrix.h"
+
+
+MUP_NAMESPACE_START
+
+// Forward declarations
+ class IValueReader;
+ class IOprtBin;
+ class IOprtPostfix;
+ class IOprtInfix;
+ class IFunction;
+ class IToken;
+ class IValue;
+ class ParserXBase;
+ class Value;
+ class Variable;
+ class TokenReader;
+
+ // smart pointer types
+ template<typename T>
+ class TokenPtr;
+
+ /** \brief Type of a managed pointer storing parser tokens. */
+ typedef TokenPtr<IToken> ptr_tok_type;
+
+ /** \brief Type of a managed pointer storing value tokens. */
+ typedef TokenPtr<IValue> ptr_val_type;
+
+ /** \brief Type of a managed pointer storing binary operator tokens. */
+ typedef TokenPtr<IOprtBin> ptr_binop_type;
+
+ /** \brief Type for a vector of tokens. */
+ typedef std::vector<ptr_tok_type> token_vec_type;
+
+ /** \brief Type for a vector of value items. */
+ typedef std::vector<ptr_val_type> val_vec_type;
+
+ // parser type definitions
+
+ /** \brief Parser datatype for floating point value. */
+ typedef /*long*/ double float_type;
+
+ /** \brief Parser datatype for integer valuse. */
+ typedef int int_type;
+
+ /** \brief The basic type used for representing complex numbers. */
+ typedef std::complex<float_type> cmplx_type;
+
+ /** \brief Parser boolean datatype.
+
+ This must be bool! The only reason for this typedef is that I need the name bool_type
+ for a preprocessor macro definition to avoid inconsistent naming of the macro parameters.
+ */
+ typedef bool bool_type;
+
+ /** \brief The parsers underlying matrix type. */
+ typedef Matrix<Value> matrix_type;
+
+ /** \brief Parser datatype for strings. */
+ typedef MUP_STRING_TYPE string_type;
+
+ /** \brief Character type of the parser. */
+ typedef string_type::value_type char_type;
+
+ typedef std::basic_stringstream<char_type,
+ std::char_traits<char_type>,
+ std::allocator<char_type> > stringstream_type;
+
+ /** \brief Type of a vector holding pointers to value reader objects. */
+ typedef std::vector<IValueReader*> readervec_type;
+
+ /** \brief type for the parser variable storage. */
+ typedef std::map<string_type, ptr_tok_type> var_maptype;
+
+ /** \brief type of a container used to store parser values. */
+ typedef std::map<string_type, ptr_tok_type> val_maptype;
+
+ /** \brief Type of a container that binds Callback object pointer
+ to operator identifiers. */
+ typedef std::map<string_type, ptr_tok_type> fun_maptype;
+
+ /** \brief Type of a container that binds Callback object pointer
+ to operator identifiers. */
+ typedef std::map<string_type, ptr_tok_type, su::pred::SortByLength<string_type> > oprt_bin_maptype;
+
+ typedef std::multimap<string_type, ptr_tok_type, su::pred::SortByLength<string_type> > oprt_bin_multimap;
+
+ /** \brief Type of a map for storing postfix operators by their name. */
+ typedef std::map<string_type, ptr_tok_type> oprt_pfx_maptype;
+
+ /** \brief Type of a map for storing infix operators by their name. */
+ typedef std::map<string_type, ptr_tok_type> oprt_ifx_maptype;
+
+ //------------------------------------------------------------------------------
+ /** \brief Bytecode values.
+ \attention The order of the operator entries must match the order in
+ ParserXBase::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.
+ cmBO = 0, ///< Operator item: opening bracket
+ cmBC = 1, ///< Operator item: closing bracket
+ cmIO = 2, ///< Operator item: index operator opening
+ cmIC = 3, ///< Operator item: index operator closing
+ cmARG_SEP = 4, ///< Operator item: comma
+ cmIF = 5, ///< Ternary if then else operator
+ cmELSE = 6, ///< Ternary if then else operator
+ cmENDIF = 7, ///< Ternary if then else operator
+ cmJMP = 8, ///< Reserved for future use
+ cmVAR = 9, ///< variable item
+ cmVAL = 10, ///< value item
+ cmFUNC = 11, ///< Code for a function item
+ cmOPRT_BIN = 12, ///< Binary operator
+ cmOPRT_INFIX = 13, ///< Infix operator
+ cmOPRT_POSTFIX = 14, ///< Postfix operator
+ cmEOE = 15, ///< End of expression
+
+ // The following codes are reserved in case i will ever turn this
+ // into a scripting language
+ cmSCRIPT_GOTO = 16, ///< Reserved for future use
+ cmSCRIPT_LABEL = 17, ///< Reserved for future use
+ cmSCRIPT_FOR = 18, ///< Reserved for future use
+ cmSCRIPT_IF = 19, ///< Reserved for future use
+ cmSCRIPT_ELSE = 20, ///< Reserved for future use
+ cmSCRIPT_ELSEIF = 21, ///< Reserved for future use
+ cmSCRIPT_ENDIF = 22, ///< Reserved for future use
+ cmSCRIPT_NEWLINE = 23, ///< Newline
+ cmSCRIPT_FUNCTION = 24, ///< Reserved for future use
+
+ // misc codes
+ cmUNKNOWN = 25, ///< uninitialized item
+ cmCOUNT = 26 ///< Dummy entry for counting the enum values
+ }; // ECmdCode
+
+
+ //------------------------------------------------------------------------------
+ /** \brief Strings assigned to the enum codes of ECmdCode.
+
+ Used for debugging purposes only.
+ */
+ extern const char_type *g_sCmdCode[];
+
+ //------------------------------------------------------------------------------
+ enum EPackages
+ {
+ pckCOMMON = 1 << 0,
+ pckUNIT = 1 << 1,
+ pckCOMPLEX = 1 << 2,
+ pckNON_COMPLEX = 1 << 3,
+ pckSTRING = 1 << 4,
+ pckMATRIX = 1 << 5,
+ pckALL_COMPLEX = pckCOMMON | pckCOMPLEX | pckSTRING | pckUNIT | pckMATRIX,
+ pckALL_NON_COMPLEX = pckCOMMON | pckNON_COMPLEX | pckSTRING | pckUNIT | pckMATRIX
+ };
+
+ //------------------------------------------------------------------------------
+ /** \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 "()"
+ noIO = 1 << 2, ///< No opening bracket "["
+ noIC = 1 << 3, ///< No closing bracket "]"
+ noVAL = 1 << 4, ///< to avoid i.e. "tan 2" or "sin(8)3.14"
+ noVAR = 1 << 5, ///< to avoid i.e. "sin a" or "sin(8)a"
+ noCOMMA = 1 << 6, ///< to avoid i.e. ",," or "+," ...
+ noFUN = 1 << 7, ///< to avoid i.e. "sqrt cos" or "(1)sin"
+ noOPT = 1 << 8, ///< to avoid i.e. "(+)"
+ noPFX = 1 << 9, ///< to avoid i.e. "(5!!)" "sin!"
+ noIFX = 1 << 10, ///< to avoid i.e. "++4" "!!4"
+ noEND = 1 << 11, ///< to avoid unexpected end of expression
+ noIF = 1 << 12,
+ noELSE = 1 << 13,
+ noNEWLINE = 1 << 14, ///< to avoid i.e. "a+\nb" or "sin(\na)"
+
+ sfSTART_OF_LINE = noOPT | noBC | noPFX | noCOMMA | noIO | noIC | noIF | noELSE,
+ sfALLOW_NONE = ~0 ///< All of he above flags set
+ };
+
+ //------------------------------------------------------------------------------
+ /** \brief Binary operator associativity values. */
+ enum EOprtAsct
+ {
+ oaNONE = 0,
+ oaLEFT = 1,
+ oaRIGHT = 2,
+ };
+
+ //------------------------------------------------------------------------------
+ /** \brief Parser operator precedence values.
+
+ These are predefined values for the operator precedence.
+ */
+ enum EOprtPrecedence
+ {
+ // assignment operators
+ prASSIGN = -1,
+
+ // if-then-else
+ prIF_THEN_ELSE = 0,
+
+ // binary operators
+ prLOGIC_OR = 1,
+ prLOGIC_AND = 2,
+ prBIT_OR = 3,
+ prBIT_AND = 4,
+
+ prRELATIONAL1 = 5, ///< For "==", "!="
+ prRELATIONAL2 = 6, ///< Relational operators "<", "<=", ">", ">="
+ prSHIFT = 7, ///< Shift operators "<<", ">>"
+
+ prCOLON = 8, ///< Colon operator
+
+ prADD_SUB = 9, ///< addition
+ prMUL_DIV = 10, ///< multiplication/division
+ prPOW = 11, ///< power operator priority (highest)
+
+ // infix operators
+ prINFIX = 10, ///< Signs have a higher priority than ADD_SUB, but lower than power operator
+ prPOSTFIX = 10 ///< Postfix operator priority (currently unused)
+ };
+
+#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 // _UNICODE
+
+} // namespace mu
+
+#endif
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpValReader.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpValReader.cpp Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,279 @@
+/** \file
+ \brief Implementation of classes that interpret values in a string.
+
+<pre>
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+ </pre>
+*/
+#include "mpValReader.h"
+#include "mpError.h"
+
+
+MUP_NAMESPACE_START
+
+ //------------------------------------------------------------------------------
+ //
+ // Reader for floating point values
+ //
+ //------------------------------------------------------------------------------
+
+ DblValReader::DblValReader()
+ :IValueReader()
+ {}
+
+ //------------------------------------------------------------------------------
+ DblValReader::~DblValReader()
+ {}
+
+ //------------------------------------------------------------------------------
+ bool DblValReader::IsValue(const char_type *a_szExpr, int &a_iPos, Value &a_Val)
+ {
+ stringstream_type stream(a_szExpr + a_iPos);
+ float_type fVal(0);
+ std::streamoff iStart(0), iEnd(0);
+
+ iStart = stream.tellg(); // Record position before reading
+ stream >> fVal;
+ iEnd = stream.tellg(); // Position after reading
+
+ if (iEnd==-1)
+ return false;
+
+ a_iPos += (int)iEnd;
+
+ // Finally i have to check if the next sign is the "i" for a imaginary unit
+ // if so this is an imaginary value
+ if (a_szExpr[a_iPos]=='i')
+ {
+ a_Val = cmplx_type(0.0, fVal);
+ a_iPos++;
+ }
+ else
+ {
+ a_Val = cmplx_type(fVal, 0.0);
+ }
+
+ return true;
+ }
+
+ //------------------------------------------------------------------------------
+ IValueReader* DblValReader::Clone(TokenReader *pTokenReader) const
+ {
+ IValueReader *pReader = new DblValReader(*this);
+ pReader->SetParent(pTokenReader);
+
+ return pReader;
+ }
+
+ //------------------------------------------------------------------------------
+ //
+ // Reader for boolean values
+ //
+ //------------------------------------------------------------------------------
+
+ BoolValReader::BoolValReader()
+ :IValueReader()
+ {}
+
+ //------------------------------------------------------------------------------
+ BoolValReader::~BoolValReader()
+ {}
+
+ //------------------------------------------------------------------------------
+ bool BoolValReader::IsValue(const char_type *a_szExpr, int &a_iPos, Value &a_Val)
+ {
+ string_type sExpr(a_szExpr + a_iPos);
+
+ if (sExpr.find(_T("true"))==0)
+ {
+ a_Val = true;
+ a_iPos += 4;
+ return true;
+ }
+ else if (sExpr.find(_T("false"))==0)
+ {
+ a_Val = false;
+ a_iPos += 5;
+ return true;
+ }
+
+ return false;
+ }
+
+ //------------------------------------------------------------------------------
+ IValueReader* BoolValReader::Clone(TokenReader *pTokenReader) const
+ {
+ IValueReader *pReader = new BoolValReader(*this);
+ pReader->SetParent(pTokenReader);
+
+ return pReader;
+ }
+
+ //------------------------------------------------------------------------------
+ //
+ // Reader for hex values
+ //
+ //------------------------------------------------------------------------------
+
+ HexValReader::HexValReader()
+ :IValueReader()
+ {}
+
+ //------------------------------------------------------------------------------
+ /** \brief Try to read a hex value from a given position in the expression.
+ \param a_szExpr The Expression
+ \param [in/out] a_iPos The current position in the expression
+ \param [out] a_val The value that was read
+
+ Hex values must start with a "0x" characters. The position a_iPos is advanded in case
+ a hex value was found.
+ */
+ bool HexValReader::IsValue(const char_type *a_szExpr, int &a_iPos, Value &a_val)
+ {
+ std::size_t len = std::char_traits<char_type>::length(a_szExpr);
+ if ( a_iPos>=(int)len || a_szExpr[a_iPos+1]!='x' || a_szExpr[a_iPos+1]==0 || a_szExpr[a_iPos]!='0')
+ return 0;
+
+ unsigned iVal(0);
+
+ stringstream_type::pos_type nPos(0);
+ stringstream_type ss(a_szExpr + a_iPos + 2);
+ ss >> std::hex >> iVal;
+ nPos = ss.tellg();
+
+ if (nPos==(stringstream_type::pos_type)0)
+ return 1;
+
+ a_iPos += (int)(2 + nPos);
+ a_val = (int)iVal;
+ return 1;
+ }
+
+ //------------------------------------------------------------------------------
+ IValueReader* HexValReader::Clone(TokenReader *pTokenReader) const
+ {
+ IValueReader *pReader = new HexValReader(*this);
+ pReader->SetParent(pTokenReader);
+ return pReader;
+ }
+
+ //------------------------------------------------------------------------------
+ //
+ // Reader for binary values
+ //
+ //------------------------------------------------------------------------------
+
+ BinValReader::BinValReader()
+ :IValueReader()
+ {}
+
+ //------------------------------------------------------------------------------
+ BinValReader::~BinValReader()
+ {}
+
+ //------------------------------------------------------------------------------
+ bool BinValReader::IsValue(const char_type *a_szExpr, int &a_iPos, Value &a_Val)
+ {
+ const char_type *szExpr = a_szExpr + a_iPos;
+
+ if (szExpr[0]!='#')
+ return false;
+
+ unsigned iVal = 0, iBits = sizeof(iVal)*8, i;
+ for (i=0; (szExpr[i+1]=='0' || szExpr[i+1]=='1') && i<iBits; ++i)
+ iVal |= (int)(szExpr[i+1]=='1') << ((iBits-1)-i);
+
+ if (i==0)
+ return false;
+
+ if (i==iBits)
+ throw ParserError(_T("Binary to integer conversion error (overflow)."));
+
+ a_Val = (int)(iVal >> (iBits-i) );
+ a_iPos += i+1;
+
+ return true;
+ }
+
+ //------------------------------------------------------------------------------
+ IValueReader* BinValReader::Clone(TokenReader *pTokenReader) const
+ {
+ IValueReader *pReader = new BinValReader(*this);
+ pReader->SetParent(pTokenReader);
+
+ return pReader;
+ }
+
+ //------------------------------------------------------------------------------
+ //
+ // Reader for string values
+ //
+ //------------------------------------------------------------------------------
+
+ StrValReader::StrValReader()
+ :IValueReader()
+ {}
+
+ //------------------------------------------------------------------------------
+ StrValReader::~StrValReader()
+ {}
+
+ //------------------------------------------------------------------------------
+ bool StrValReader::IsValue(const char_type *a_pszExpr, int &a_iPos, Value &a_Val)
+ {
+ const char_type *szExpr = a_pszExpr + a_iPos;
+
+
+ if (szExpr[0]!='"')
+ return false;
+
+ string_type sBuf(&szExpr[1]);
+ std::size_t iEnd(0), iSkip(0);
+
+ // parser over escaped '\"' end replace them with '"'
+ for(iEnd=sBuf.find(_T("\"")); iEnd!=string_type::npos; iEnd=sBuf.find(_T("\""), iEnd))
+ {
+ if (sBuf[iEnd-1]!='\\') break;
+ sBuf.replace(iEnd-1, 2, _T("\""));
+ iSkip++;
+ }
+
+ if (iEnd==string_type::npos)
+ throw ParserError( ErrorContext(ecUNTERMINATED_STRING, a_iPos) );
+
+ string_type sTok(sBuf.begin(), sBuf.begin()+iEnd);
+ a_Val = sTok;
+ a_iPos += (int)(sTok.length() + 2 + iSkip); // +2 wg Anführungszeichen; +iSkip für entfernte escape zeichen
+ return true;
+ }
+
+ //------------------------------------------------------------------------------
+ IValueReader* StrValReader::Clone(TokenReader *pTokenReader) const
+ {
+ IValueReader *pReader = new StrValReader(*this);
+ pReader->SetParent(pTokenReader);
+
+ return pReader;
+ }
+} // namespace mu
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpValReader.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpValReader.h Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,129 @@
+/** \file
+ \brief Definition of classes that interpret values in a string.
+
+<pre>
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+ </pre>
+*/
+#ifndef MU_PARSER_IMPL_READER_H
+#define MU_PARSER_IMPL_READER_H
+
+#include "mpIValReader.h"
+
+
+
+MUP_NAMESPACE_START
+
+ //------------------------------------------------------------------------------
+ //
+ // Reader for double values
+ //
+ //------------------------------------------------------------------------------
+
+ /** \brief A class for reading floating point values from an expression string.
+ \ingroup valreader
+ */
+ class DblValReader : public IValueReader
+ {
+ public:
+ DblValReader();
+ virtual ~DblValReader();
+ virtual bool IsValue(const char_type *a_szExpr, int &a_iPos, Value &a_fVal);
+ virtual IValueReader* Clone(TokenReader *pTokenReader) const;
+ };
+
+ //------------------------------------------------------------------------------
+ //
+ // Reader for boolean values
+ //
+ //------------------------------------------------------------------------------
+
+ /** \brief A class for reading boolean values from an expression string.
+ \ingroup valreader
+ */
+ class BoolValReader : public IValueReader
+ {
+ public:
+ BoolValReader();
+ virtual ~BoolValReader();
+ virtual bool IsValue(const char_type *a_szExpr, int &a_iPos, Value &a_fVal);
+ virtual IValueReader* Clone(TokenReader *pTokenReader) const;
+ };
+
+ //------------------------------------------------------------------------------
+ //
+ // Reader for hex values
+ //
+ //------------------------------------------------------------------------------
+
+ /** \brief A class for reading hex values from an expression string.
+ \ingroup valreader
+ */
+ class HexValReader : public IValueReader
+ {
+ public:
+ HexValReader();
+ virtual bool IsValue(const char_type *a_szExpr, int &a_iPos, Value &a_fVal);
+ virtual IValueReader* Clone(TokenReader *pTokenReader) const;
+ };
+
+ //------------------------------------------------------------------------------
+ //
+ // Reader for binary values
+ //
+ //------------------------------------------------------------------------------
+
+ /** \brief A class for reading binary values from an expression string.
+ \ingroup valreader
+ */
+ class BinValReader : public IValueReader
+ {
+ public:
+ BinValReader();
+ virtual ~BinValReader();
+ virtual bool IsValue(const char_type *a_szExpr, int &a_iPos, Value &a_fVal);
+ virtual IValueReader* Clone(TokenReader *pTokenReader) const;
+ };
+
+ //------------------------------------------------------------------------------
+ //
+ // Reader for string values
+ //
+ //------------------------------------------------------------------------------
+
+ /** \brief A class for reading strings from an expression string.
+ \ingroup valreader
+ */
+ class StrValReader : public IValueReader
+ {
+ public:
+ StrValReader();
+ virtual ~StrValReader();
+ virtual bool IsValue(const char_type *a_szExpr, int &a_iPos, Value &a_fVal);
+ virtual IValueReader* Clone(TokenReader *pTokenReader) const;
+ };
+
+MUP_NAMESPACE_END
+
+#endif
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpValue.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpValue.cpp Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,795 @@
+/*
+<pre>
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+</pre>
+*/
+#include "mpValue.h"
+#include "mpError.h"
+#include "mpValueCache.h"
+
+
+MUP_NAMESPACE_START
+
+ //------------------------------------------------------------------------------
+ /** \brief Construct an empty value object of a given type.
+ \param cType The type of the value to construct (default='v').
+ */
+ Value::Value(char_type cType)
+ :IValue(cmVAL)
+ ,m_val(0,0)
+ ,m_psVal(NULL)
+ ,m_pvVal(NULL)
+ ,m_cType(cType)
+ ,m_iFlags(flNONE)
+ ,m_pCache(NULL)
+ {
+ // strings and arrays must allocate their memory
+ switch (cType)
+ {
+ case 's': m_psVal = new string_type(); break;
+ case 'm': m_pvVal = new matrix_type(0, Value(0)); break;
+ }
+ }
+
+ //---------------------------------------------------------------------------
+ Value::Value(int_type a_iVal)
+ :IValue(cmVAL)
+ ,m_val((float_type)a_iVal, 0)
+ ,m_psVal(NULL)
+ ,m_pvVal(NULL)
+ ,m_cType('i')
+ ,m_iFlags(flNONE)
+ ,m_pCache(NULL)
+ {}
+
+ //---------------------------------------------------------------------------
+ Value::Value(bool_type a_bVal)
+ :IValue(cmVAL)
+ ,m_val((float_type)a_bVal, 0)
+ ,m_psVal(NULL)
+ ,m_pvVal(NULL)
+ ,m_cType('b')
+ ,m_iFlags(flNONE)
+ ,m_pCache(NULL)
+ {}
+
+ //---------------------------------------------------------------------------
+ Value::Value(string_type a_sVal)
+ :IValue(cmVAL)
+ ,m_val()
+ ,m_psVal(new string_type(a_sVal))
+ ,m_pvVal(NULL)
+ ,m_cType('s')
+ ,m_iFlags(flNONE)
+ ,m_pCache(NULL)
+ {}
+
+ //---------------------------------------------------------------------------
+ Value::Value(int_type array_size, float_type v)
+ :IValue(cmVAL)
+ ,m_val()
+ ,m_psVal(NULL)
+ ,m_pvVal(new matrix_type(array_size, Value(v)))
+ ,m_cType('m')
+ ,m_iFlags(flNONE)
+ ,m_pCache(NULL)
+ {}
+
+ //---------------------------------------------------------------------------
+ /** \brief Create a m x n matrix
+ */
+ Value::Value(int_type m, int_type n, float_type v)
+ :IValue(cmVAL)
+ ,m_val()
+ ,m_psVal(NULL)
+ ,m_pvVal(new matrix_type(m, n, Value(v)))
+ ,m_cType('m')
+ ,m_iFlags(flNONE)
+ ,m_pCache(NULL)
+ {}
+
+ //---------------------------------------------------------------------------
+ Value::Value(const char_type *a_szVal)
+ :IValue(cmVAL)
+ ,m_val()
+ ,m_psVal(new string_type(a_szVal))
+ ,m_pvVal(NULL)
+ ,m_cType('s')
+ ,m_iFlags(flNONE)
+ ,m_pCache(NULL)
+ {}
+
+ //---------------------------------------------------------------------------
+ Value::Value(const cmplx_type &v)
+ :IValue(cmVAL)
+ ,m_val(v)
+ ,m_psVal(NULL)
+ ,m_pvVal(NULL)
+ ,m_cType('c')
+ ,m_iFlags(flNONE)
+ ,m_pCache(NULL)
+ {
+ if ( (m_val.real()==(int_type)m_val.real()) && (m_val.imag()==0) )
+ m_cType = 'i';
+ else
+ m_cType = (m_val.imag()==0) ? 'f' : 'c';
+ }
+
+ //---------------------------------------------------------------------------
+ Value::Value(float_type val)
+ :IValue(cmVAL)
+ ,m_val(val, 0)
+ ,m_psVal(NULL)
+ ,m_pvVal(NULL)
+ ,m_cType((val==(int_type)val) ? 'i' : 'f')
+ ,m_iFlags(flNONE)
+ ,m_pCache(NULL)
+ {}
+
+ //---------------------------------------------------------------------------
+ Value::Value(const matrix_type &val)
+ :IValue(cmVAL)
+ ,m_val()
+ ,m_psVal(NULL)
+ ,m_pvVal(new matrix_type(val))
+ ,m_cType('m')
+ ,m_iFlags(flNONE)
+ ,m_pCache(NULL)
+ {}
+
+ //---------------------------------------------------------------------------
+ Value::Value(const Value &a_Val)
+ :IValue(cmVAL)
+ ,m_psVal(NULL)
+ ,m_pvVal(NULL)
+ ,m_pCache(NULL)
+ {
+ Assign(a_Val);
+ }
+
+ //---------------------------------------------------------------------------
+ Value::Value(const IValue &a_Val)
+ :IValue(cmVAL)
+ ,m_psVal(NULL)
+ ,m_pvVal(NULL)
+ ,m_pCache(NULL)
+ {
+ Reset();
+
+ switch(a_Val.GetType())
+ {
+ case 'i':
+ case 'f':
+ case 'b': m_val = cmplx_type(a_Val.GetFloat(), 0);
+ break;
+
+
+ case 'c': m_val = cmplx_type(a_Val.GetFloat(), a_Val.GetImag());
+ break;
+
+ case 's': if (!m_psVal)
+ m_psVal = new string_type(a_Val.GetString());
+ else
+ *m_psVal = a_Val.GetString();
+ break;
+
+ case 'm': if (!m_pvVal)
+ m_pvVal = new matrix_type(a_Val.GetArray());
+ else
+ *m_pvVal = a_Val.GetArray();
+ break;
+
+ case 'v': break;
+ default: MUP_FAIL(INVALID_TYPE_CODE);
+ }
+
+ m_cType = a_Val.GetType();
+ }
+
+ //---------------------------------------------------------------------------
+ Value& Value::operator=(const Value &a_Val)
+ {
+ Assign(a_Val);
+ return *this;
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Return the matrix element at row col.
+
+ Row and col are the indices of the matrix. If this element does not
+ represent a matrix row and col must be 0 otherwise an index out of bound error
+ is thrown.
+ */
+ IValue& Value::At(const IValue &row, const IValue &col)
+ {
+ if (!row.IsInteger() || !col.IsInteger())
+ {
+ ErrorContext errc(ecTYPE_CONFLICT_IDX, GetExprPos());
+ errc.Hint = _T("Array index must be an integer value.");
+ errc.Type1 = (!row.IsInteger()) ? row.GetType() : col.GetType();
+ errc.Type2 = 'i';
+ throw ParserError(errc);
+ }
+
+ int nRow = row.GetInteger(),
+ nCol = col.GetInteger();
+ return At(nRow, nCol);
+ }
+
+ //---------------------------------------------------------------------------
+ IValue& Value::At(int nRow, int nCol)
+ {
+ if (IsMatrix())
+ {
+ if (nRow>=m_pvVal->GetRows() || nCol>=m_pvVal->GetCols() || nRow<0 || nCol<0)
+ throw ParserError( ErrorContext(ecINDEX_OUT_OF_BOUNDS, -1, GetIdent()) );
+
+ return m_pvVal->At(nRow, nCol);
+ }
+ else if (nRow==0 && nCol==0)
+ {
+ return *this;
+ }
+ else
+ throw ParserError( ErrorContext(ecINDEX_OUT_OF_BOUNDS) );
+ }
+
+ //---------------------------------------------------------------------------
+ Value::~Value()
+ {
+ delete m_psVal;
+ delete m_pvVal;
+ }
+
+ //---------------------------------------------------------------------------
+ IToken* Value::Clone() const
+ {
+ return new Value(*this);
+ }
+
+ //---------------------------------------------------------------------------
+ Value* Value::AsValue()
+ {
+ return this;
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Copy constructor. */
+ void Value::Assign(const Value &ref)
+ {
+ if (this==&ref)
+ return;
+
+ m_val = ref.m_val;
+ m_cType = ref.m_cType;
+ m_iFlags = ref.m_iFlags;
+
+ // allocate room for a string
+ if (ref.m_psVal)
+ {
+ if (!m_psVal)
+ m_psVal = new string_type(*ref.m_psVal);
+ else
+ *m_psVal = *ref.m_psVal;
+ }
+ else
+ {
+ delete m_psVal;
+ m_psVal = NULL;
+ }
+
+ // allocate room for a vector
+ if (ref.m_pvVal)
+ {
+ if (m_pvVal==NULL)
+ m_pvVal = new matrix_type(*ref.m_pvVal);
+ else
+ *m_pvVal = *ref.m_pvVal;
+ }
+ else
+ {
+ delete m_pvVal;
+ m_pvVal = NULL;
+ }
+
+ // Do NOT access ref beyound this point! If you do, "unboxing" of
+ // a 1 x 1 matrix using:
+ //
+ // this->Assign(m_pvVal->At(0,0));
+ //
+ // will blow up in your face since ref will become invalid at them very
+ // moment you delete m_pvVal!
+ }
+
+ //---------------------------------------------------------------------------
+ void Value::Reset()
+ {
+ m_val = cmplx_type(0,0);
+
+ delete m_psVal;
+ m_psVal = NULL;
+
+ delete m_pvVal;
+ m_pvVal = NULL;
+
+ m_cType = 'f';
+ m_iFlags = flNONE;
+ }
+
+ //---------------------------------------------------------------------------
+ IValue& Value::operator=(bool val)
+ {
+ m_val = cmplx_type((float_type)val,0);
+
+ delete m_psVal;
+ m_psVal = NULL;
+
+ delete m_pvVal;
+ m_pvVal = NULL;
+
+ m_cType = 'b';
+ m_iFlags = flNONE;
+ return *this;
+ }
+
+ //---------------------------------------------------------------------------
+ IValue& Value::operator=(int_type a_iVal)
+ {
+ m_val = cmplx_type(a_iVal,0);
+
+ delete m_psVal;
+ m_psVal = NULL;
+
+ delete m_pvVal;
+ m_pvVal = NULL;
+
+ m_cType = 'i';
+ m_iFlags = flNONE;
+ return *this;
+ }
+
+ //---------------------------------------------------------------------------
+ IValue& Value::operator=(float_type val)
+ {
+ m_val = cmplx_type(val, 0);
+
+ delete m_psVal;
+ m_psVal = NULL;
+
+ delete m_pvVal;
+ m_pvVal = NULL;
+
+ m_cType = (val==(int_type)val) ? 'i' : 'f';
+ m_iFlags = flNONE;
+ return *this;
+ }
+
+ //---------------------------------------------------------------------------
+ IValue& Value::operator=(string_type a_sVal)
+ {
+ m_val = cmplx_type();
+
+ if (!m_psVal)
+ m_psVal = new string_type(a_sVal);
+ else
+ *m_psVal = a_sVal;
+
+ delete m_pvVal;
+ m_pvVal = NULL;
+
+ m_cType = 's';
+ m_iFlags = flNONE;
+ return *this;
+ }
+
+ //---------------------------------------------------------------------------
+ IValue& Value::operator=(const char_type *a_szVal)
+ {
+ m_val = cmplx_type();
+
+ if (!m_psVal)
+ m_psVal = new string_type(a_szVal);
+ else
+ *m_psVal = a_szVal;
+
+ delete m_pvVal;
+ m_pvVal = NULL;
+
+ m_cType = 's';
+ m_iFlags = flNONE;
+ return *this;
+ }
+
+ //---------------------------------------------------------------------------
+ IValue& Value::operator=(const matrix_type &a_vVal)
+ {
+ m_val = cmplx_type(0,0);
+
+ delete m_psVal;
+ m_psVal = NULL;
+
+ if (m_pvVal==NULL)
+ m_pvVal = new matrix_type(a_vVal);
+ else
+ *m_pvVal = a_vVal;
+
+ m_cType = 'm';
+ m_iFlags = flNONE;
+
+ return *this;
+ }
+
+ //---------------------------------------------------------------------------
+ IValue& Value::operator=(const cmplx_type &val)
+ {
+ m_val = val;
+
+ delete m_psVal;
+ m_psVal = NULL;
+
+ delete m_pvVal;
+ m_pvVal = NULL;
+
+ m_cType = (m_val.imag()==0) ? ( (m_val.real()==(int)m_val.real()) ? 'i' : 'f' ) : 'c';
+ m_iFlags = flNONE;
+
+ return *this;
+ }
+
+ //---------------------------------------------------------------------------
+ IValue& Value::operator+=(const IValue &val)
+ {
+ if (IsScalar() && val.IsScalar())
+ {
+ // Scalar/Scalar addition
+ m_val += val.GetComplex();
+ }
+ else if (IsMatrix() && val.IsMatrix())
+ {
+ // Matrix/Matrix addition
+ assert(m_pvVal);
+ *m_pvVal += val.GetArray();
+ }
+ else if (IsString() && val.IsString())
+ {
+ // string/string addition
+ assert(m_psVal);
+ *m_psVal += val.GetString();
+ }
+ else
+ {
+ // Type conflict
+ throw ParserError(ErrorContext(ecTYPE_CONFLICT_FUN, -1, _T("+"), GetType(), val.GetType(), 2));
+ }
+
+ return *this;
+ }
+
+ //---------------------------------------------------------------------------
+ IValue& Value::operator-=(const IValue &val)
+ {
+ if (IsScalar() && val.IsScalar())
+ {
+ // Scalar/Scalar addition
+ m_val -= val.GetComplex();
+ }
+ else if (IsMatrix() && val.IsMatrix())
+ {
+ // Matrix/Matrix addition
+ assert(m_pvVal);
+ *m_pvVal -= val.GetArray();
+ }
+ else
+ {
+ // There is a typeconflict:
+ throw ParserError(ErrorContext(ecTYPE_CONFLICT_FUN, -1, _T("-"), GetType(), val.GetType(), 2));
+ }
+
+ return *this;
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Assign a value with multiplication
+ \param val The value to multiply to this
+
+ When multiplying to values with each value representing a matrix type
+ the result is checked whether it is a 1 x 1 matrix. If so the value is
+ "unboxed" and stored directly in this value object. It is no longer
+ treated as a matrix internally.
+ */
+ IValue& Value::operator*=(const IValue &val)
+ {
+ if (IsScalar() && val.IsScalar())
+ {
+ // Scalar/Scalar multiplication
+ m_val *= val.GetComplex();
+
+ // Check whether we're dealing with a complex or integer result, if so set the
+ // type flag accordingly
+ if (m_val.imag()!=0)
+ m_cType = 'c';
+ else if ((double)(int)m_val.real()==m_val.real())
+ m_cType = 'i';
+ }
+ else if (IsMatrix() && val.IsMatrix())
+ {
+ // Matrix/Matrix addition
+ assert(m_pvVal);
+ *m_pvVal *= val.GetArray();
+
+ // The result may actually be a scalar value, i.e. the scalar product of
+ // two vectors.
+ if (m_pvVal->GetCols()==1 && m_pvVal->GetRows()==1)
+ {
+ Assign(m_pvVal->At(0,0));
+ }
+ }
+ else if ( IsMatrix() && val.IsScalar() )
+ {
+ *m_pvVal *= val;
+ }
+ else if ( IsScalar() * val.IsMatrix() )
+ {
+ // transform this into a matrix and multiply with rhs
+ Value prod = val * (*this);
+ Assign(prod);
+ }
+ else
+ {
+ // Type conflict
+ ErrorContext errc(ecTYPE_CONFLICT_FUN, -1, _T("*"));
+ errc.Type1 = GetType();
+ errc.Type2 = 'm'; //val.GetType();
+ errc.Arg = 2;
+ throw ParserError(errc);
+ }
+
+ return *this;
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Returns a character representing the type of this value instance.
+ \return m_cType Either one of 'c' for comlex, 'i' for integer,
+ 'f' for floating point, 'b' for boolean, 's' for string or
+ 'm' for matrix values.
+ */
+ char_type Value::GetType() const
+ {
+ return m_cType;
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Return the value as an integer.
+
+ This function should only be called if you really need an integer value and
+ want to make sure your either get one or throw an exception if the value
+ can not be implicitely converted into an integer.
+ */
+ int_type Value::GetInteger() const
+ {
+ float_type v = m_val.real();
+
+ if (m_cType!='i') //!IsScalar() || (int_type)v-v!=0)
+ {
+ ErrorContext err;
+ err.Errc = ecTYPE_CONFLICT;
+ err.Type1 = m_cType;
+ err.Type2 = 'i';
+
+ if (GetIdent().length())
+ {
+ err.Ident = GetIdent();
+ }
+ else
+ {
+ stringstream_type ss;
+ ss << *this;
+ err.Ident = ss.str();
+ }
+
+ throw ParserError(err);
+ }
+
+ return (int_type)v;
+ }
+
+ //---------------------------------------------------------------------------
+ float_type Value::GetFloat() const
+ {
+/*
+ if (!IsScalar() && m_cType!='b')
+ {
+ ErrorContext err;
+ err.Errc = ecTYPE_CONFLICT;
+ err.Type1 = m_cType;
+ err.Type2 = 'c';
+
+ if (GetIdent().length())
+ {
+ err.Ident = GetIdent();
+ }
+ else
+ {
+ stringstream_type ss;
+ ss << *this;
+ err.Ident = ss.str();
+ }
+
+ throw ParserError(err);
+ }
+*/
+ return m_val.real();
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Get the imaginary part of the value.
+ \throw ParserError in case this value represents a string or a matrix
+ */
+ float_type Value::GetImag() const
+ {
+ if (!IsScalar())
+ {
+ ErrorContext err;
+ err.Errc = ecTYPE_CONFLICT;
+ err.Type1 = m_cType;
+ err.Type2 = 'c';
+
+ if (GetIdent().length())
+ {
+ err.Ident = GetIdent();
+ }
+ else
+ {
+ stringstream_type ss;
+ ss << *this;
+ err.Ident = ss.str();
+ }
+
+ throw ParserError(err);
+ }
+
+ return m_val.imag();
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Returns this value as a complex number.
+ \throw nothrow
+
+ If the value instance does not represent a complex value the returned value
+ is undefined. No exception is triggered. If you are unsure about the type
+ use IsComplex() or GetType() to verify the type.
+ */
+ const cmplx_type& Value::GetComplex() const
+ {
+ return m_val;
+ }
+
+ //---------------------------------------------------------------------------
+ const string_type& Value::GetString() const
+ {
+ CheckType('s');
+ assert(m_psVal!=NULL);
+ return *m_psVal;
+ }
+
+ //---------------------------------------------------------------------------
+ bool Value::GetBool() const
+ {
+ CheckType('b');
+ return m_val.real()==1;
+ }
+
+ //---------------------------------------------------------------------------
+ const matrix_type& Value::GetArray() const
+ {
+ CheckType('m');
+ assert(m_pvVal!=NULL);
+ return *m_pvVal;
+ }
+
+ //---------------------------------------------------------------------------
+ int Value::GetRows() const
+ {
+ return (GetType()!='m') ? 1 : GetArray().GetRows();
+ }
+
+ //---------------------------------------------------------------------------
+ int Value::GetCols() const
+ {
+ return 1;
+ }
+
+ //---------------------------------------------------------------------------
+ void Value::CheckType(char_type a_cType) const
+ {
+ if (m_cType!=a_cType)
+ {
+ ErrorContext err;
+ err.Errc = ecTYPE_CONFLICT;
+ err.Type1 = m_cType;
+ err.Type2 = a_cType;
+
+ if (GetIdent().length())
+ {
+ err.Ident = GetIdent();
+ }
+ else
+ {
+ stringstream_type ss;
+ ss << *this;
+ err.Ident = ss.str();
+ }
+
+ throw ParserError(err);
+ }
+ }
+
+ //---------------------------------------------------------------------------
+ bool Value::IsVolatile() const
+ {
+ return IsFlagSet(IValue::flVOLATILE);
+// return true;
+ }
+
+ //---------------------------------------------------------------------------
+ string_type Value::AsciiDump() const
+ {
+ stringstream_type ss;
+
+ ss << g_sCmdCode[ GetCode() ];
+ ss << _T(" [addr=0x") << std::hex << this << std::dec;
+ ss << _T("; type=\"") << GetType() << _T("\"");
+ ss << _T("; val=");
+
+ switch(m_cType)
+ {
+ case 'i': ss << (int_type)m_val.real(); break;
+ case 'f': ss << m_val.real(); break;
+ case 'm': ss << _T("(matrix)"); break;
+ case 's':
+ assert(m_psVal!=NULL);
+ ss << _T("\"") << m_psVal << _T("\""); break;
+ }
+
+ ss << ((IsFlagSet(IToken::flVOLATILE)) ? _T("; ") : _T("; not ")) << _T("volatile");
+ ss << _T("]");
+
+ return ss.str();
+ }
+
+ //---------------------------------------------------------------------------
+ void Value::Release()
+ {
+ if (m_pCache)
+ m_pCache->ReleaseToCache(this);
+ else
+ delete this;
+ }
+
+ //---------------------------------------------------------------------------
+ void Value::BindToCache(ValueCache *pCache)
+ {
+ m_pCache = pCache;
+ }
+} // namespace mu
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpValue.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpValue.h Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,128 @@
+/** \file
+ \brief Definition of basic types used by muParserX
+
+<pre>
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+ </pre>
+*/
+#ifndef MUP_VALUE_H
+#define MUP_VALUE_H
+
+//--- Standard includes ------------------------------------------------------------
+#include <complex>
+#include <list>
+
+//--- Parser framework -------------------------------------------------------------
+#include "mpIValue.h"
+#include "mpTypes.h"
+
+
+MUP_NAMESPACE_START
+
+ //------------------------------------------------------------------------------
+ /** \brief Value class of muParserX
+
+ This class represents a value to be used with muParserX. It's a Variant like
+ class able to store a variety of types.
+ */
+ class Value : public IValue
+ {
+ public:
+
+ explicit Value(char_type cType = 'v');
+ Value(int_type val);
+ Value(bool_type val);
+ Value(float_type val);
+ Value(string_type val);
+ Value(const char_type *val);
+ Value(const cmplx_type &v);
+ Value(const matrix_type &val);
+
+ // Array and Matrix constructors
+ Value(int_type m, float_type v);
+ Value(int_type m, int_type n, float_type v);
+
+ Value(const Value &a_Val );
+ Value(const IValue &a_Val);
+ Value& operator=(const Value &a_Val);
+
+ virtual ~Value();
+
+ virtual IValue& At(int nRow, int nCol = 0);
+ virtual IValue& At(const IValue &row, const IValue &col);
+
+ virtual IValue& operator=(int_type a_iVal);
+ virtual IValue& operator=(float_type a_fVal);
+ virtual IValue& operator=(string_type a_sVal);
+ virtual IValue& operator=(bool val);
+ virtual IValue& operator=(const matrix_type &a_vVal);
+ virtual IValue& operator=(const cmplx_type &val);
+ virtual IValue& operator=(const char_type *a_szVal);
+ virtual IValue& operator+=(const IValue &val);
+ virtual IValue& operator-=(const IValue &val);
+ virtual IValue& operator*=(const IValue &val);
+
+ virtual char_type GetType() const;
+ virtual int_type GetInteger() const;
+ virtual float_type GetFloat() const;
+ virtual float_type GetImag() const;
+ virtual bool GetBool() const;
+ virtual const cmplx_type& GetComplex() const;
+ virtual const string_type& GetString() const;
+ virtual const matrix_type& GetArray() const;
+ virtual int GetRows() const;
+ virtual int GetCols() const;
+
+ virtual bool IsVolatile() const;
+ virtual IToken* Clone() const;
+ virtual Value* AsValue();
+
+ virtual string_type AsciiDump() const;
+ void BindToCache(ValueCache *pCache);
+
+ private:
+
+ cmplx_type m_val; ///< Member variable for storing the value of complex, float, int and boolean values
+ string_type *m_psVal; ///< Variable for storing a string value
+ matrix_type *m_pvVal; ///< A Vector for storing array variable content
+ char_type m_cType; ///< A byte indicating the type os the represented value
+ EFlags m_iFlags; ///< Additional flags
+ ValueCache *m_pCache; ///< Pointer to the Value Cache
+
+ int m_nCols; ///< Number of columns in this value (for matrices)
+ int m_nRows; ///< Number of Rows in this value (for matrices)
+
+ void CheckType(char_type a_cType) const;
+ void Assign(const Value &a_Val);
+ void Reset();
+
+ virtual void Release();
+ }; // class Value
+
+
+MUP_NAMESPACE_END
+
+#endif
+
+
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpValueCache.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpValueCache.cpp Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,99 @@
+/** \file
+ \brief Definition of a class for caching unused value items and recycling them.
+
+<pre>
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+</pre>
+*/
+#include "mpValueCache.h"
+
+#include "mpValue.h"
+
+
+MUP_NAMESPACE_START
+
+ //------------------------------------------------------------------------------
+ ValueCache::ValueCache(int size)
+ :m_nIdx(-1)
+ ,m_vCache(size, (mup::Value*)0) // hint to myself: don't use NULL gcc will go postal...
+ {}
+
+ //------------------------------------------------------------------------------
+ ValueCache::~ValueCache()
+ {
+ ReleaseAll();
+ }
+
+ //------------------------------------------------------------------------------
+ void ValueCache::ReleaseAll()
+ {
+ for (std::size_t i=0; i<m_vCache.size(); ++i)
+ {
+ delete m_vCache[i];
+ m_vCache[i] = NULL;
+ }
+
+ m_nIdx = -1;
+ }
+
+ //------------------------------------------------------------------------------
+ void ValueCache::ReleaseToCache(Value *pValue)
+ {
+// std::cout << "dbg: " << ct << " ptr: " << this << " void ValueCache::ReleaseToCache(Value *pValue) \n";
+ if (pValue==NULL)
+ return;
+
+ assert(pValue->GetRef()==0);
+
+ // Add the value to the cache if the cache has room for it
+ // otherwise release the value item instantly
+ if ( m_nIdx < ((int)m_vCache.size()-1) )
+ {
+ m_nIdx++;
+ m_vCache[m_nIdx] = pValue;
+ }
+ else
+ delete pValue;
+ }
+
+ //------------------------------------------------------------------------------
+ Value* ValueCache::CreateFromCache()
+ {
+ Value *pValue = NULL;
+ if (m_nIdx>=0)
+ {
+ pValue = m_vCache[m_nIdx];
+ m_vCache[m_nIdx] = NULL;
+ m_nIdx--;
+ }
+ else
+ {
+ pValue = new Value();
+ pValue->BindToCache(this);
+ }
+
+ return pValue;
+ }
+
+MUP_NAMESPACE_END
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpValueCache.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpValueCache.h Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,67 @@
+#ifndef MUP_VALUE_CACHE_H
+#define MUP_VALUE_CACHE_H
+
+/** \file
+ \brief Implementation of a cache for recycling unused value items.
+
+<pre>
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+</pre>
+*/
+#include <vector>
+
+#include "mpFwdDecl.h"
+
+
+MUP_NAMESPACE_START
+
+ /** \brief The ValueCache class provides a simple mechanism to recycle
+ unused value items.
+
+ This class serves as a factory for value items. It allows skipping
+ unnecessary and slow new/delete calls by storing unused value
+ objects in an internal buffer for later reuse. By eliminating new/delete
+ calls the parser is sped up approximately by factor 3-4.
+ */
+ class ValueCache
+ {
+ public:
+ ValueCache(int size=10);
+ ~ValueCache();
+
+ void ReleaseAll();
+ void ReleaseToCache(Value *pValue);
+ Value* CreateFromCache();
+
+ private:
+ ValueCache(const ValueCache &ref);
+ ValueCache& operator=(const ValueCache &ref);
+
+ int m_nIdx;
+ std::vector<Value*> m_vCache;
+ };
+
+MUP_NAMESPACE_END
+
+#endif // include guard
\ No newline at end of file
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpVariable.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpVariable.cpp Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,315 @@
+/** \file
+ \brief Implementation of the muParserX variable class.
+
+<pre>
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+</pre>
+*/
+#include "mpVariable.h"
+#include "mpError.h"
+
+#include "mpValue.h"
+
+
+MUP_NAMESPACE_START
+
+ //-----------------------------------------------------------------------------------------------
+ /** \brief Create a variable and bind a value to it.
+ \param pVal Pointer of the value to bind to this variable.
+
+ It is possible to create an empty variable object by setting pVal to null.
+ Such variable objects must be bound later in order to be of any use.
+ */
+ Variable::Variable(IValue *pVal)
+ :IValue(cmVAR)
+ ,m_pVal(pVal)
+ {
+ AddFlags(IToken::flVOLATILE);
+ }
+
+ //-----------------------------------------------------------------------------------------------
+ Variable::Variable(const Variable &obj)
+ :IValue(cmVAR)
+ {
+ Assign(obj);
+ AddFlags(IToken::flVOLATILE);
+ }
+
+ //-----------------------------------------------------------------------------------------------
+ Variable& Variable::operator=(const Variable &obj)
+ {
+ Assign(obj);
+ return *this;
+ }
+
+ //-----------------------------------------------------------------------------------------------
+ /** \brief Assign a value to the variable.
+ \param ref Reference to the value to be assigned
+ */
+ IValue& Variable::operator=(const Value &ref)
+ {
+ assert(m_pVal);
+ *m_pVal = ref;
+ return *this;
+ }
+
+ //-----------------------------------------------------------------------------------------------
+ IValue& Variable::operator=(int_type val)
+ {
+ assert(m_pVal);
+ return m_pVal->operator=(val);
+ }
+
+ //-----------------------------------------------------------------------------------------------
+ IValue& Variable::operator=(float_type val)
+ {
+ assert(m_pVal);
+ return m_pVal->operator=(val);
+ }
+
+ //-----------------------------------------------------------------------------------------------
+ IValue& Variable::operator=(string_type val)
+ {
+ assert(m_pVal);
+ return m_pVal->operator=(val);
+ }
+
+ //-----------------------------------------------------------------------------------------------
+ IValue& Variable::operator=(bool_type val)
+ {
+ assert(m_pVal);
+ return m_pVal->operator=(val);
+ }
+
+ //-----------------------------------------------------------------------------------------------
+ IValue& Variable::operator=(const matrix_type &val)
+ {
+ assert(m_pVal);
+ return m_pVal->operator=(val);
+ }
+
+ //-----------------------------------------------------------------------------------------------
+ IValue& Variable::operator=(const cmplx_type &val)
+ {
+ assert(m_pVal);
+ return m_pVal->operator=(val);
+ }
+
+ //-----------------------------------------------------------------------------------------------
+ IValue& Variable::operator+=(const IValue &val)
+ {
+ assert(m_pVal);
+ return m_pVal->operator+=(val);
+ }
+
+ //-----------------------------------------------------------------------------------------------
+ IValue& Variable::operator-=(const IValue &val)
+ {
+ assert(m_pVal);
+ return m_pVal->operator-=(val);
+ }
+
+ //-----------------------------------------------------------------------------------------------
+ IValue& Variable::operator*=(const IValue &val)
+ {
+ assert(m_pVal);
+ return m_pVal->operator*=(val);
+ }
+
+ //-----------------------------------------------------------------------------------------------
+ IValue& Variable::At(int nRow, int nCol)
+ {
+ return m_pVal->At(nRow, nCol);
+ }
+
+ //-----------------------------------------------------------------------------------------------
+ IValue& Variable::At(const IValue &row, const IValue &col)
+ {
+ try
+ {
+ return m_pVal->At(row, col);
+ }
+ catch(ParserError &exc)
+ {
+ // add the identifier to the error context
+ exc.GetContext().Ident = GetIdent();
+ throw exc;
+ }
+ }
+
+ //-----------------------------------------------------------------------------------------------
+ Variable::~Variable()
+ {}
+
+ //-----------------------------------------------------------------------------------------------
+ void Variable::Assign(const Variable &ref)
+ {
+ if (this==&ref)
+ return;
+
+ m_pVal = ref.m_pVal;
+ }
+
+ //-----------------------------------------------------------------------------------------------
+ /** \brief Returns a character representing the type of the variable.
+ \throw nothrow
+ */
+ char_type Variable::GetType() const
+ {
+ return (m_pVal) ? m_pVal->GetType() : 'v';
+ }
+
+ //-----------------------------------------------------------------------------------------------
+ /** \brief Returns the Value pointer bound to this variable.
+ \throw nothrow
+ */
+ IValue* Variable::GetPtr() const
+ {
+ return m_pVal;
+ }
+
+ //-----------------------------------------------------------------------------------------------
+ int_type Variable::GetInteger() const
+ {
+ return m_pVal->GetInteger();
+ }
+
+ //-----------------------------------------------------------------------------------------------
+ float_type Variable::GetFloat() const
+ {
+ return m_pVal->GetFloat();
+ }
+
+ //-----------------------------------------------------------------------------------------------
+ float_type Variable::GetImag() const
+ {
+ return m_pVal->GetImag();
+ }
+
+ //-----------------------------------------------------------------------------------------------
+ const cmplx_type& Variable::GetComplex() const
+ {
+ return m_pVal->GetComplex();
+ }
+
+ //-----------------------------------------------------------------------------------------------
+ const string_type& Variable::GetString() const
+ {
+ return m_pVal->GetString();
+ }
+
+ //-----------------------------------------------------------------------------------------------
+ bool Variable::GetBool() const
+ {
+ return m_pVal->GetBool();
+ }
+
+ //-----------------------------------------------------------------------------------------------
+ const matrix_type& Variable::GetArray() const
+ {
+ return m_pVal->GetArray();
+ }
+
+ //-----------------------------------------------------------------------------------------------
+ int Variable::GetRows() const
+ {
+ return m_pVal->GetRows();
+ }
+
+ //-----------------------------------------------------------------------------------------------
+ int Variable::GetCols() const
+ {
+ return m_pVal->GetCols();
+ }
+
+ //-----------------------------------------------------------------------------------------------
+ void Variable::SetFloat(float_type a_fVal)
+ {
+ assert(m_pVal);
+ *m_pVal = a_fVal;
+ }
+
+ //-----------------------------------------------------------------------------------------------
+ void Variable::SetString(const string_type &a_sVal)
+ {
+ assert(m_pVal);
+ *m_pVal = a_sVal;
+ }
+
+ //-----------------------------------------------------------------------------------------------
+ void Variable::SetBool(bool a_bVal)
+ {
+ assert(m_pVal);
+ *m_pVal = a_bVal;
+ }
+
+ //-----------------------------------------------------------------------------------------------
+ void Variable::Bind(IValue *pValue)
+ {
+ m_pVal = pValue;
+ }
+
+ //-----------------------------------------------------------------------------------------------
+ bool Variable::IsVolatile() const
+ {
+ return true;
+ }
+
+ //-----------------------------------------------------------------------------------------------
+ IToken* Variable::Clone() const
+ {
+ return new Variable(*this);
+ }
+
+ //-----------------------------------------------------------------------------------------------
+ Value* Variable::AsValue()
+ {
+ return NULL;
+ }
+
+ //-----------------------------------------------------------------------------------------------
+ string_type Variable::AsciiDump() const
+ {
+ stringstream_type ss;
+
+ ss << g_sCmdCode[ GetCode() ];
+ ss << _T(" [addr=0x") << std::hex << this << std::dec;
+ ss << _T("; id=\"") << GetIdent() << _T("\"");
+ ss << _T("; type=\"") << GetType() << _T("\"");
+ ss << _T("; val=");
+
+ switch(GetType())
+ {
+ case 'i': ss << (int_type)GetFloat(); break;
+ case 'f': ss << GetFloat(); break;
+ case 'm': ss << _T("(array)"); break;
+ case 's': ss << _T("\"") << GetString() << _T("\""); break;
+ }
+
+ ss << ((IsFlagSet(IToken::flVOLATILE)) ? _T("; ") : _T("; not ")) << _T("volatile");
+ ss << _T("]");
+
+ return ss.str();
+ }
+MUP_NAMESPACE_END
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/mpVariable.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/mpVariable.h Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,108 @@
+/** \file
+ \brief Definition of the muParserX variable class.
+
+<pre>
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+</pre>
+*/
+
+#ifndef MP_VARIABLE_H
+#define MP_VARIABLE_H
+
+#include "mpIValue.h"
+#include "mpTypes.h"
+
+
+MUP_NAMESPACE_START
+
+ //------------------------------------------------------------------------------
+ /** \brief The variable class represents a parser variable.
+
+ This class stores a pointer to a value object and refers all
+ operations to this value object.
+ */
+ class Variable : public IValue
+ {
+ public:
+
+ Variable(IValue *pVal);
+
+ Variable(const Variable &a_Var);
+ Variable& operator=(const Variable &a_Var);
+
+ virtual IValue& At(int nRow, int nCol);
+ virtual IValue& At(const IValue &nRows, const IValue &nCols);
+
+ virtual IValue& operator=(const Value &val);
+ virtual IValue& operator=(const matrix_type &val);
+ virtual IValue& operator=(const cmplx_type &val);
+ virtual IValue& operator=(int_type val);
+ virtual IValue& operator=(float_type val);
+ virtual IValue& operator=(string_type val);
+ virtual IValue& operator=(bool_type val);
+ virtual IValue& operator+=(const IValue &ref);
+ virtual IValue& operator-=(const IValue &ref);
+ virtual IValue& operator*=(const IValue &val);
+
+ virtual ~Variable();
+
+ virtual char_type GetType() const;
+
+ virtual int_type GetInteger() const;
+ virtual float_type GetFloat() const;
+ virtual float_type GetImag() const;
+ virtual bool GetBool() const;
+ virtual const cmplx_type& GetComplex() const;
+ virtual const string_type& GetString() const;
+ virtual const matrix_type& GetArray() const;
+ virtual int GetRows() const;
+ virtual int GetCols() const;
+
+ virtual bool IsVolatile() const;
+ virtual IToken* Clone() const;
+ virtual Value* AsValue();
+
+ //void Set(Value &val);
+ void SetFloat(float_type a_fVal);
+ void SetString(const string_type &a_sVal);
+ void SetBool(bool a_bVal);
+
+ void Bind(IValue *pValue);
+
+ IValue* GetPtr() const;
+ string_type AsciiDump() const;
+
+ private:
+
+ IValue *m_pVal; ///< Pointer to the value object bound to this variable
+
+ void Assign(const Variable &a_Var);
+ void CheckType(char_type a_cType) const;
+ }; // class Variable
+
+MUP_NAMESPACE_END
+
+#endif
+
+
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/muParser.suo
Binary file muparserx/parser/muParser.suo has changed
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/suSortPred.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/suSortPred.h Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,58 @@
+/*
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+*/
+#ifndef SU_PRED_H
+#define SU_PRED_H
+
+#include <functional>
+
+
+/** \brief Namespace containing utility functions and classes for string processing. */
+namespace su
+{
+ namespace pred
+ {
+ /** \brief Sort two strings based on their length.
+ */
+ template<class TString>
+ struct SortByLength
+ :public std::binary_function<TString, TString, bool>
+ {
+ bool operator()(const TString& a_sLeft, const TString& a_sRight) const
+ {
+ if (a_sLeft.length() == a_sRight.length())
+ {
+ return a_sLeft < a_sRight;
+ }
+ else
+ {
+ return a_sLeft.length() < a_sRight.length();
+ }
+ }
+ };
+ } // namespace pred
+} // end of namespace
+
+
+#endif
diff -r 458e51062300 -r 5a4d909d9533 muparserx/parser/utGeneric.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/parser/utGeneric.h Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,53 @@
+/*
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+*/
+#ifndef _UT_GENERIC_H
+#define _UT_GENERIC_H
+
+namespace utils
+{
+ template<typename T>
+ class scoped_setter
+ {
+ public:
+
+ scoped_setter(T &ref, T new_val)
+ :m_ref(ref)
+ ,m_buf(ref)
+ {
+ ref = new_val;
+ }
+
+ ~scoped_setter()
+ {
+ m_ref = m_buf;
+ }
+
+ private:
+ T &m_ref;
+ T m_buf;
+ };
+}
+
+#endif
\ No newline at end of file
diff -r 458e51062300 -r 5a4d909d9533 muparserx/sample/example.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/sample/example.cpp Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,911 @@
+/** \example example.cpp
+
+<pre>
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+ </pre>
+
+ This is example code showing you how to use muParserX.
+*/
+
+//---------------------------------------------------------------------------
+//
+// muParserX
+//
+// example.cpp - Demonstrates how to use muParserX
+//
+//---------------------------------------------------------------------------
+
+/** \brief This macro will enable mathematical constants like M_PI. */
+#define _USE_MATH_DEFINES
+
+//--- Standard include ------------------------------------------------------
+#if defined(_WIN32) && defined(_DEBUG)
+ #define _CRTDBG_MAP_ALLOC
+ #include <stdlib.h>
+ #include <crtdbg.h>
+ #define CREATE_LEAKAGE_REPORT
+#endif
+
+#include <cstdlib>
+#include <cstring>
+#include <ctime>
+#include <cstdio>
+#include <cmath>
+#include <string>
+#include <iostream>
+
+//--- muParserX framework ---------------------------------------------------
+#include "mpParser.h"
+#include "mpDefines.h"
+#include "mpTest.h"
+
+//--- other includes --------------------------------------------------------
+#include "timer.h"
+
+using namespace std;
+using namespace mup;
+
+#if defined(CREATE_LEAKAGE_REPORT)
+
+// Dumping memory leaks in the destructor of the static guard
+// guarantees i won't get false positives from the ParserErrorMsg
+// class wich is a singleton with a static instance.
+struct DumpLeaks
+{
+ ~DumpLeaks()
+ {
+ _CrtDumpMemoryLeaks();
+ }
+} static LeakDumper;
+
+#endif
+
+const string_type sPrompt = _T("muParserX> ");
+
+//-------------------------------------------------------------------------------------------------
+// The following classes will be used to list muParserX variables, constants
+// from this console application
+//-------------------------------------------------------------------------------------------------
+
+//-------------------------------------------------------------------------------------------------
+class FunPrint : public ICallback
+{
+public:
+ FunPrint() : ICallback(cmFUNC, _T("print"), 1)
+ {}
+
+ virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc)
+ {
+ ParserXBase &parser = *GetParent();
+ console() << a_pArg[0].Get()->ToString() << _T("\n");
+ *ret = 0;
+ }
+
+ virtual const char_type* GetDesc() const
+ {
+ return _T("");
+ }
+
+ virtual IToken* Clone() const
+ {
+ return new FunPrint();
+ }
+}; // class FunPrint
+
+//-------------------------------------------------------------------------------------------------
+class FunTest0 : public ICallback
+{
+public:
+ FunTest0() : ICallback(cmFUNC, _T("test0"), 0)
+ {}
+
+ virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc)
+ {
+ ParserXBase &parser = *GetParent();
+ *ret = 0;
+ }
+
+ virtual const char_type* GetDesc() const
+ {
+ return _T("");
+ }
+
+ virtual IToken* Clone() const
+ {
+ return new FunTest0();
+ }
+}; // class FunTest0
+
+//-------------------------------------------------------------------------------------------------
+class FunListVar : public ICallback
+{
+public:
+
+ FunListVar() : ICallback(cmFUNC, _T("list_var"), 0)
+ {}
+
+ virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc)
+ {
+ ParserXBase &parser = *GetParent();
+
+ console() << _T("\nParser variables:\n");
+ console() << _T( "-----------------\n");
+
+ // Query the used variables (must be done after calc)
+ var_maptype vmap = parser.GetVar();
+ if (!vmap.size())
+ {
+ console() << _T("Expression does not contain variables\n");
+ }
+ else
+ {
+ var_maptype::iterator item = vmap.begin();
+ for (; item!=vmap.end(); ++item)
+ {
+ // You can dump the token into a stream via the "<<" operator
+ console() << _T(" ") << item->first << _T(" = ") << *(item->second)/* << _T("\n")*/;
+
+ // If you need more specific information cast the token to a variable object
+ Variable &v = (Variable&)(*(item->second));
+ console() << _T(" (type=\"") << v.GetType() << _T("\"; ptr=0x") << hex << v.GetPtr() << _T(")\n");
+ }
+ }
+
+ *ret = (int)vmap.size();
+ }
+
+ virtual const char_type* GetDesc() const
+ {
+ return _T("list_var() - List all variables of the parser bound to this function and returns the number of defined variables.");
+ }
+
+ virtual IToken* Clone() const
+ {
+ return new FunListVar();
+ }
+}; // class FunListVar
+
+
+//-------------------------------------------------------------------------------------------------
+class FunListConst : public ICallback
+{
+public:
+
+ FunListConst() : ICallback(cmFUNC, _T("list_const"), 0)
+ {}
+
+ virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc)
+ {
+ ParserXBase &parser = *GetParent();
+
+ console() << _T("\nParser constants:\n");
+ console() << _T( "-----------------\n");
+
+ val_maptype cmap = parser.GetConst();
+ if (!cmap.size())
+ {
+ console() << _T("No constants defined\n");
+ }
+ else
+ {
+ val_maptype::iterator item = cmap.begin();
+ for (; item!=cmap.end(); ++item)
+ console() << _T(" ") << item->first << _T(" = ") << (Value&)(*(item->second)) << _T("\n");
+ }
+
+ *ret = (int)cmap.size();
+ }
+
+ virtual const char_type* GetDesc() const
+ {
+ return _T("list_const() - List all constants of the parser bound to this function and returns the number of defined constants.");
+ }
+
+ virtual IToken* Clone() const
+ {
+ return new FunListConst();
+ }
+}; // class FunListConst
+
+
+//-------------------------------------------------------------------------------------------------
+class FunBenchmark : public ICallback
+{
+public:
+ FunBenchmark() : ICallback(cmFUNC, _T("bench"), 0)
+ {}
+
+ virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc)
+ {
+ char outstr[200];
+ time_t t = time(NULL);
+
+ #ifdef _DEBUG
+ strftime(outstr, sizeof(outstr), "Result_%Y%m%d_%H%M%S_dbg.txt", localtime(&t));
+ #else
+ strftime(outstr, sizeof(outstr), "Result_%Y%m%d_%H%M%S_release.txt", localtime(&t));
+ #endif
+
+ const char_type* sExpr[] = {
+ _T("sin(a)"),
+ _T("cos(a)"),
+ _T("tan(a)"),
+ _T("sqrt(a)"),
+ _T("(a+b)*3"),
+ _T("a^2+b^2"),
+ _T("a^3+b^3"),
+ _T("a^4+b^4"),
+ _T("a^5+b^5"),
+ _T("a*2+b*2"),
+ _T("-(b^1.1)"),
+ _T("a + b * c"),
+ _T("a * b + c"),
+ _T("a+b*(a+b)"),
+ _T("(1+b)*(-3)"),
+ _T("e^log(7*a)"),
+ _T("10^log(3+b)"),
+ _T("a+b-e*pi/5^6"),
+ _T("a^b/e*pi-5+6"),
+ _T("sin(a)+sin(b)"),
+ _T("(cos(2.41)/b)"),
+ _T("-(sin(pi+a)+1)"),
+ _T("a-(e^(log(7+b)))"),
+ _T("sin(((a-a)+b)+a)"),
+ _T("((0.09/a)+2.58)-1.67"),
+ _T("abs(sin(sqrt(a^2+b^2))*255)"),
+ _T("abs(sin(sqrt(a*a+b*b))*255)"),
+ _T("cos(0.90-((cos(b)/2.89)/e)/a)"),
+ _T("(1*(2*(3*(4*(5*(6*(a+b)))))))"),
+ _T("abs(sin(sqrt(a^2.1+b^2.1))*255)"),
+ _T("(1*(2*(3*(4*(5*(6*(7*(a+b))))))))"),
+ _T("1/(a*sqrt(2*pi))*e^(-0.5*((b-a)/a)^2)"),
+ _T("1+2-3*4/5^6*(2*(1-5+(3*7^9)*(4+6*7-3)))+12"),
+ _T("1+b-3*4/5^6*(2*(1-5+(3*7^9)*(4+6*7-3)))+12*a"),
+ _T("(b+1)*(b+2)*(b+3)*(b+4)*(b+5)*(b+6)*(b+7)*(b+8)*(b+9)*(b+10)*(b+11)*(b+12)"),
+ _T("(a/((((b+(((e*(((((pi*((((3.45*((pi+a)+pi))+b)+b)*a))+0.68)+e)+a)/a))+a)+b))+b)*a)-pi))"),
+ _T("(((-9))-e/(((((((pi-(((-7)+(-3)/4/e))))/(((-5))-2)-((pi+(-0))*(sqrt((e+e))*(-8))*(((-pi)+(-pi)-(-9)*(6*5))/(-e)-e))/2)/((((sqrt(2/(-e)+6)-(4-2))+((5/(-2))/(1*(-pi)+3))/8)*pi*((pi/((-2)/(-6)*1*(-1))*(-6)+(-e)))))/((e+(-2)+(-e)*((((-3)*9+(-e)))+(-9)))))))-((((e-7+(((5/pi-(3/1+pi)))))/e)/(-5))/(sqrt((((((1+(-7))))+((((-e)*(-e)))-8))*(-5)/((-e)))*(-6)-((((((-2)-(-9)-(-e)-1)/3))))/(sqrt((8+(e-((-6))+(9*(-9))))*(((3+2-8))*(7+6+(-5))+((0/(-e)*(-pi))+7)))+(((((-e)/e/e)+((-6)*5)*e+(3+(-5)/pi))))+pi))/sqrt((((9))+((((pi))-8+2))+pi))/e*4)*((-5)/(((-pi))*(sqrt(e)))))-(((((((-e)*(e)-pi))/4+(pi)*(-9)))))))+(-pi)"),
+ 0 };
+
+
+
+ ParserX parser;
+ Value a((float_type)1.0);
+ Value b((float_type)2.0);
+ Value c((float_type)3.0);
+
+ parser.DefineVar(_T("a"), Variable(&a));
+ parser.DefineVar(_T("b"), Variable(&b));
+ parser.DefineVar(_T("c"), Variable(&c));
+ parser.DefineConst(_T("pi"), (float_type)M_PI);
+ parser.DefineConst(_T("e"), (float_type)M_E);
+
+ FILE *pFile = fopen(outstr, "w");
+ int iCount = 400000;
+
+ #ifdef _DEBUG
+ string_type sMode = _T("# debug mode\n");
+ #else
+ string_type sMode = _T("# release mode\n");
+ #endif
+
+ fprintf(pFile, "%s; muParserX V%s\n", sMode.c_str(), ParserXBase::GetVersion().c_str());
+ fprintf(pFile, "\"Eqn no.\", \"number\", \"result\", \"time in ms\", \"eval per second\", \"expr\"\n");
+
+ printf("%s", sMode.c_str());
+ printf("\"Eqn no.\", \"number\", \"result\", \"time in ms\", \"eval per second\", \"expr\"\n");
+
+ double avg_eval_per_sec = 0;
+ int ct=0;
+ for (int i=0; sExpr[i]; ++i)
+ {
+ ct++;
+ StartTimer();
+ Value val;
+ parser.SetExpr(sExpr[i]);
+
+ // implicitely create reverse polish notation
+ parser.Eval();
+
+ for (int n=0; n<iCount; ++n)
+ {
+ val = parser.Eval();
+ }
+
+ double diff = StopTimer();
+
+ float_type eval_per_sec = (float_type)iCount*1000.0/diff;
+ avg_eval_per_sec += eval_per_sec;
+
+ #if !defined _UNICODE
+ fprintf(pFile, "Eqn_%d, %d, %lf, %lf, %lf, %s\n", i, iCount, val.GetFloat(), diff, eval_per_sec, sExpr[i]);
+ printf("Eqn_%d, %d, %lf, %lf, %lf, %s\n" , i, iCount, val.GetFloat(), diff, eval_per_sec, sExpr[i]);
+ #else
+ fwprintf(pFile, _T("Eqn_%d, %d, %lf, %lf, %lf, %s\n"), i, iCount, val.GetFloat(), diff, eval_per_sec, sExpr[i]);
+ wprintf(_T("Eqn_%d, %d, %lf, %lf, %lf, %s\n") , i, iCount, val.GetFloat(), diff, eval_per_sec, sExpr[i]);
+ #endif
+ }
+
+ avg_eval_per_sec /= (float_type)ct;
+
+ fprintf(pFile, "# Eval per s: %d", (long)avg_eval_per_sec);
+
+ fflush(pFile);
+ *ret = (float_type)avg_eval_per_sec;
+ }
+
+ virtual const char_type* GetDesc() const
+ {
+ return _T("bench() - Perform a benchmark with a set of standard functions.");
+ }
+
+ virtual IToken* Clone() const
+ {
+ return new FunBenchmark();
+ }
+}; // class FunBenchmark
+
+
+//-------------------------------------------------------------------------------------------------
+class FunListFunctions : public ICallback
+{
+public:
+ FunListFunctions() : ICallback(cmFUNC, _T("list_fun"), 0)
+ {}
+
+ virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc)
+ {
+ ParserXBase &parser = *GetParent();
+
+ console() << _T("\nParser functions:\n");
+ console() << _T( "----------------\n");
+
+ fun_maptype fmap = parser.GetFunDef();
+ if (!fmap.size())
+ {
+ console() << _T("No functions defined\n");
+ }
+ else
+ {
+ val_maptype::iterator item = fmap.begin();
+ for (; item!=fmap.end(); ++item)
+ {
+ ICallback *pFun = (ICallback*)item->second.Get();
+ console() << pFun->GetDesc() << _T("\n");
+ }
+ }
+
+ *ret = (int)fmap.size();
+ }
+
+ virtual const char_type* GetDesc() const
+ {
+ return _T("list_fun() - List all parser functions and returns the total number of defined functions.");
+ }
+
+ virtual IToken* Clone() const
+ {
+ return new FunListFunctions();
+ }
+}; // class FunListFunctions
+
+
+//-------------------------------------------------------------------------------------------------
+class FunEnableOptimizer : public ICallback
+{
+public:
+ FunEnableOptimizer() : ICallback(cmFUNC, _T("enable_optimizer"), 1)
+ {}
+
+ virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc)
+ {
+ ParserXBase &parser = *GetParent();
+ parser.EnableOptimizer(a_pArg[0]->GetBool());
+ *ret = a_pArg[0]->GetBool();
+ }
+ virtual const char_type* GetDesc() const
+ {
+ return _T("enable_optimizer(bool) - Enables the parsers built in expression optimizer.");
+ }
+
+ virtual IToken* Clone() const
+ {
+ return new FunEnableOptimizer();
+ }
+}; // class FunListFunctions
+
+
+//-------------------------------------------------------------------------------------------------
+class FunSelfTest : public ICallback
+{
+public:
+ FunSelfTest() : ICallback(cmFUNC, _T("test"), 0)
+ {}
+
+ virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc)
+ {
+ ParserXBase::EnableDebugDump(0, 0);
+ ParserTester pt;
+ pt.Run();
+ *ret = 0;
+ }
+ virtual const char_type* GetDesc() const
+ {
+ return _T("test() - Runs the unit test of muparserx.");
+ }
+
+ virtual IToken* Clone() const
+ {
+ return new FunSelfTest();
+ }
+}; // class FunSelfTest
+
+//-------------------------------------------------------------------------------------------------
+class FunEnableDebugDump : public ICallback
+{
+public:
+ FunEnableDebugDump() : ICallback(cmFUNC, _T("dump"), 2)
+ {}
+
+ virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc)
+ {
+ ParserXBase::EnableDebugDump(a_pArg[0]->GetBool(), a_pArg[1]->GetBool());
+ *ret = 0;
+ }
+ virtual const char_type* GetDesc() const
+ {
+ return _T("dump(bDumpRPN, bDumpStack) - Enable dumping of RPN and stack content.");
+ }
+
+ virtual IToken* Clone() const
+ {
+ return new FunEnableDebugDump();
+ }
+}; // class FunEnableDebugDump
+
+
+
+/*
+//-------------------------------------------------------------------------------------------------
+class FunGeneric : public ICallback
+{
+public:
+
+ FunGeneric(string_type sIdent, string_type sFunction)
+ :ICallback(cmFUNC, sIdent.c_str())
+ ,m_parser()
+ ,m_vars()
+ ,m_val()
+ {
+ m_parser.SetExpr(sFunction);
+ m_vars = m_parser.GetExprVar();
+ SetArgc(m_vars.size());
+
+ // Create values for the undefined variables and bind them
+ // to the variables
+ var_maptype::iterator item = m_vars.begin();
+ for (; item!=m_vars.end(); ++item)
+ {
+ ptr_val_type val(new Value());
+ m_val.push_back(val);
+
+ // assign a parser variable
+ m_parser.DefineVar(item->second->GetIdent(), Variable(val.Get()));
+ }
+ }
+
+ virtual ~FunGeneric()
+ {}
+
+ virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc)
+ {
+ // Set the variables
+ for (std::size_t i=0; i<(std::size_t)a_iArgc; ++i)
+ {
+ *m_val[i] = *a_pArg[i];
+ }
+
+ *ret = m_parser.Eval();
+ }
+
+ virtual const char_type* GetDesc() const
+ {
+ return _T("xxx(...) - Dynamically defined function");
+ }
+
+ virtual IToken* Clone() const
+ {
+ return new FunGeneric(*this);
+ }
+
+private:
+
+ ParserX m_parser;
+ mup::var_maptype m_vars;
+ val_vec_type m_val;
+}; // class FunGeneric
+
+//---------------------------------------------------------------------------
+class FunDefine : public ICallback
+{
+public:
+ FunDefine() : ICallback(cmFUNC, _T("define"), 2)
+ {}
+
+ virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc)
+ {
+ string_type sFun = a_pArg[0]->GetString();
+ string_type sDef = a_pArg[1]->GetString();
+
+ ParserXBase &parser = *GetParent();
+ parser.DefineFun(new FunGeneric(sFun, sDef));
+
+ *ret = 0;
+ }
+
+ virtual const char_type* GetDesc() const
+ {
+ return _T("define(Function, Definition) - Define a new parser function.");
+ }
+
+ virtual IToken* Clone() const
+ {
+ return new FunDefine();
+ }
+}; // class FunDefine
+
+//---------------------------------------------------------------------------
+class FunDerive : public ICallback
+{
+public:
+ FunDerive() : ICallback(cmFUNC, _T("derive"))
+ {}
+
+ virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc)
+ {
+ *ret = 0;
+ }
+
+ virtual const char_type* GetDesc() const
+ {
+ return _T("...");
+ }
+
+ void Compile(const string_type &sArg)
+ {
+ }
+
+ virtual IToken* Clone() const
+ {
+ return new FunDerive();
+ }
+}; // class FunDerive
+*/
+
+
+//---------------------------------------------------------------------------
+void SelfTest()
+{
+ console() << _T("-------------------------------------------------------------------------\n\n");
+ console() << _T(" __________ ____ ___\n");
+ console() << _T(" _____ __ _\\______ \\_____ _______ ______ __________\\ \\/ /\n");
+ console() << _T(" / \\| | \\ ___/\\__ \\\\_ __ \\/ ___// __ \\_ __ \\ / \n");
+ console() << _T(" | Y Y \\ | / | / __ \\| | \\/\\___ \\\\ ___/| | \\/ \\ \n");
+ console() << _T(" |__|_| /____/|____| (____ /__| /____ >\\___ >__| /___/\\ \\\n");
+ console() << _T(" \\/ \\/ \\/ \\/ \\_/\n");
+
+
+ console() << _T(" Version ") << ParserXBase::GetVersion() << _T("\n");
+ console() << _T(" Copyright (C) 2011 Ingo Berg");
+ console() << _T("\n");
+
+ console() << _T("-------------------------------------------------------------------------\n\n");
+ console() << _T( "Configuration:\n\n");
+
+#if defined(_DEBUG)
+ console() << _T( "- DEBUG build\n");
+#else
+ console() << _T( "- RELEASE build\n");
+#endif
+
+ console() << _T( "- ") << sizeof(void*)*8 << _T(" bit\n");
+
+#if defined(_UNICODE)
+ console() << _T( "- UNICODE build\n");
+#else
+ console() << _T( "- ASCII build\n");
+#endif
+
+ console() << _T("-------------------------------------------------------------------------\n\n");
+ console() << _T( "Running test suite:\n\n");
+
+ ParserTester pt;
+ pt.Run();
+
+ console() << _T("-------------------------------------------------------------------------\n\n");
+ console() << _T("Special parser functions:\n");
+ console() << _T(" list_var() - list parser variables and return the number of variables.\n");
+ console() << _T(" list_fun() - list parser functions and return the number of functions\n");
+ console() << _T(" list_const() - list all numeric parser constants\n");
+ console() << _T("Command line commands:\n");
+ console() << _T(" exprvar - list all variables found in the last expression\n");
+ console() << _T(" rpn - Dump reverse polish notation of the current expression\n");
+ console() << _T(" quit - exits the parser\n");
+ console() << _T("Constants:\n");
+ console() << _T(" \"e\" 2.718281828459045235360287\n");
+ console() << _T(" \"pi\" 3.141592653589793238462643\n");
+ console() << _T("-------------------------------------------------------------------------\n\n");
+}
+
+//---------------------------------------------------------------------------
+void ListExprVar(ParserXBase &parser)
+{
+ console() << _T("\nVariables found in : \"") << parser.GetExpr() << _T("\"\n");
+ console() << _T( "-----------------------------\n");
+
+ // Query the used variables (must be done after calc)
+ var_maptype vmap = parser.GetExprVar();
+ if (!vmap.size())
+ {
+ console() << _T("Expression does not contain variables\n");
+ }
+ else
+ {
+ var_maptype::iterator item = vmap.begin();
+ for (; item!=vmap.end(); ++item)
+ console() << _T(" ") << item->first << _T(" = ") << (Variable&)(*(item->second)) << _T("\n");
+ }
+}
+
+//---------------------------------------------------------------------------
+/** \brief Check for external keywords.
+*/
+int CheckKeywords(const char_type *a_szLine, ParserXBase &a_Parser)
+{
+ string_type sLine(a_szLine);
+
+ if (sLine==_T("quit"))
+ {
+ return -1;
+ }
+ else if (sLine==_T("exprvar"))
+ {
+ ListExprVar(a_Parser);
+ return 1;
+ }
+ else if (sLine==_T("rpn"))
+ {
+ a_Parser.DumpRPN();
+ return 1;
+ }
+
+ return 0;
+}
+
+//---------------------------------------------------------------------------
+void Calc()
+{
+// ParserX parser(pckALL_NON_COMPLEX);
+ ParserX parser(pckALL_COMPLEX);
+
+ // Create an array variable
+ Value arr1(3, 0);
+ arr1.At(0) = (float_type)1.0;
+ arr1.At(1) = (float_type)2.0;
+ arr1.At(2) = (float_type)3.0;
+
+ Value arr2(3, 0);
+ arr2.At(0) = (float_type)4.0;
+ arr2.At(1) = (float_type)3.0;
+ arr2.At(2) = (float_type)2.0;
+
+ Value arr3(4, 0);
+ arr3.At(0) = (float_type)1.0;
+ arr3.At(1) = (float_type)2.0;
+ arr3.At(2) = (float_type)3.0;
+ arr3.At(3) = (float_type)4.0;
+
+ Value arr4(3, 0);
+ arr4.At(0) = (float_type)4.0;
+ arr4.At(1) = false;
+ arr4.At(2) = _T("hallo");
+
+ // Create a 3x3 matrix with zero elements
+ Value m1(3, 3, 0);
+ m1.At(0, 0) = 1;
+ m1.At(1, 1) = 1;
+ m1.At(2, 2) = 1;
+
+ Value m2(3, 3, 0);
+ m2.At(0, 0) = 1;
+ m2.At(0, 1) = 2;
+ m2.At(0, 2) = 3;
+ m2.At(1, 0) = 4;
+ m2.At(1, 1) = 5;
+ m2.At(1, 2) = 6;
+ m2.At(2, 0) = 7;
+ m2.At(2, 1) = 8;
+ m2.At(2, 2) = 9;
+
+ Value val[5];
+ val[0] = (float_type)1.1;
+ val[1] = 1;
+ val[2] = false;
+ val[3] = _T("Hello");
+ val[4] = _T("World");
+
+ Value fVal[3];
+ fVal[0] = (float_type)1.11;
+ fVal[1] = (float_type)2.22;
+ fVal[2] = (float_type)3.33;
+
+ Value iVal[3];
+ iVal[0] = 1;
+ iVal[1] = 2;
+ iVal[2] = 3;
+
+ Value sVal[3];
+ sVal[0] = _T("hello");
+ sVal[1] = _T("world");
+ sVal[2] = _T("test");
+
+ Value cVal[3];
+ cVal[0] = mup::cmplx_type(1, 1);
+ cVal[1] = mup::cmplx_type(2, 2);
+ cVal[2] = mup::cmplx_type(3, 3);
+
+ Value ans;
+ parser.DefineVar(_T("ans"), Variable(&ans));
+
+ // some tests for vectors
+ parser.DefineVar(_T("va"), Variable(&arr1));
+ parser.DefineVar(_T("vb"), Variable(&arr2));
+ parser.DefineVar(_T("vc"), Variable(&arr3));
+ parser.DefineVar(_T("vd"), Variable(&arr4));
+ parser.DefineVar(_T("m1"), Variable(&m1));
+ parser.DefineVar(_T("m2"), Variable(&m2));
+
+ parser.DefineVar(_T("a"), Variable(&fVal[0]));
+ parser.DefineVar(_T("b"), Variable(&fVal[1]));
+ parser.DefineVar(_T("c"), Variable(&fVal[2]));
+
+ parser.DefineVar(_T("ia"), Variable(&iVal[0]));
+ parser.DefineVar(_T("ib"), Variable(&iVal[1]));
+ parser.DefineVar(_T("ic"), Variable(&iVal[2]));
+
+ parser.DefineVar(_T("ca"), Variable(&cVal[0]));
+ parser.DefineVar(_T("cb"), Variable(&cVal[1]));
+ parser.DefineVar(_T("cc"), Variable(&cVal[2]));
+
+ parser.DefineVar(_T("sa"), Variable(&sVal[0]));
+ parser.DefineVar(_T("sb"), Variable(&sVal[1]));
+
+ // Add functions for inspecting the parser properties
+ parser.DefineFun(new FunListVar);
+ parser.DefineFun(new FunListFunctions);
+ parser.DefineFun(new FunListConst);
+ parser.DefineFun(new FunBenchmark);
+ parser.DefineFun(new FunEnableOptimizer);
+ parser.DefineFun(new FunSelfTest);
+ parser.DefineFun(new FunEnableDebugDump);
+ parser.DefineFun(new FunTest0);
+ parser.DefineFun(new FunPrint);
+
+ parser.EnableAutoCreateVar(true);
+
+//#ifdef _DEBUG
+// ParserXBase::EnableDebugDump(1, 0);
+//#endif
+
+ for(;;)
+ {
+ try
+ {
+ console() << sPrompt;
+
+ string_type sLine;
+ std::getline(mup::console_in(), sLine);
+ if (sLine.length()==0)
+ continue;
+
+ if (sLine==_T("dbg"))
+ {
+ sLine = _T("sum(3)/sum(3,4,5)");
+ mup::console() << sLine << endl;
+ }
+
+ switch(CheckKeywords(sLine.c_str(), parser))
+ {
+ case 0: break;
+ case 1: continue;
+ case -1: return;
+ }
+
+ parser.SetExpr(sLine);
+
+ // The returned result is of type Value, value is a Variant like
+ // type that can be either a boolean an integer or a floating point value
+ ans = parser.Eval();
+// ans = parser.Eval();
+
+ // Value supports C++ streaming like this:
+ //console() << _T("Result (type: '" << ans.GetType() << "'):\n");
+ console() << _T("ans = ") << ans << _T("\n");
+
+ // Or if you need the specific type use this:
+ //switch (result.GetType())
+ //{
+ //case 's': cout << result.GetString() << " (string)" << "\n"; break;
+ //case 'i': cout << result.GetInt() << " (int)" << "\n"; break;
+ //case 'f': cout << result.GetFloat() << " (float)" << "\n"; break;
+ //case 'c': cout << result.GetFloat() << "+" << result.GetImag() << "i (complex)" << "\n"; break;
+ //case 'b': break;
+ //}
+ }
+ catch(ParserError &e)
+ {
+ if (e.GetPos()!=-1)
+ {
+ string_type sMarker;
+ sMarker.insert(0, sPrompt.size() + e.GetPos(), ' ');
+ sMarker += _T("^\n");
+ console() << sMarker;
+ }
+
+ console() << e.GetMsg() << _T(" (Errc: ") << e.GetCode() << _T(")") << _T("\n\n");
+
+ //if (e.GetContext().Ident.length())
+ // console() << _T("Ident.: ") << e.GetContext().Ident << _T("\n");
+
+ //if (e.GetToken().length())
+ // console() << _T("Token: \"") << e.GetToken() << _T("\"\n");
+ } // try / catch
+ } // for (;;)
+}
+
+//---------------------------------------------------------------------------
+int main(int argc, char* argv[])
+{
+ SelfTest();
+
+ try
+ {
+ Calc();
+ }
+ catch(ParserError &e)
+ {
+ // Only erros raised during the initialization will end up here
+ // expression related errors are treated in Calc()
+ console() << _T("Initialization error: ") << e.GetMsg() << endl;
+ }
+ catch(std::runtime_error &)
+ {
+ console() << _T("aborting...") << endl;
+ }
+
+#ifdef MUP_LEAKAGE_REPORT
+ IToken::LeakageReport();
+#endif
+
+ return 0;
+}
diff -r 458e51062300 -r 5a4d909d9533 muparserx/sample/timer.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/sample/timer.cpp Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,52 @@
+
+#include "timer.h"
+
+#include <stdio.h>
+#include <time.h>
+
+#if defined(__WIN32__) || defined(WIN32)
+#include <Windows.h>
+DWORD tvs, tve;
+#else
+#include <sys/time.h>
+struct timeval tvs, tve;
+#endif
+
+
+void StartTimer(void)
+{
+#if defined(__WIN32__) || defined(WIN32)
+ tvs = GetTickCount();
+#else
+ if (gettimeofday(&tvs,0)) fprintf(stderr,"cant get time!\n");
+#endif
+}
+
+double StopTimer(void)
+{
+#if defined(__WIN32__) || defined(WIN32)
+ tve = GetTickCount();
+ return tve - tvs;
+#else
+ if (gettimeofday(&tve,0)) fprintf(stderr,"cant get time!\n");
+ return 1000 * (tve.tv_sec - tvs.tv_sec + (double)(tve.tv_usec - tvs.tv_usec) / 1000000.0);
+#endif
+}
+
+double PrintTimer(void)
+{
+ double t;
+
+#if defined(__WIN32__) || defined(WIN32)
+ tve = GetTickCount();
+ t = (double)(tve - tvs) / 1000.0;
+ printf("%.3f ",t);
+ return t;
+#else
+ if (gettimeofday(&tve,0)) fprintf(stderr,"cant get time!\n");
+ t = 1000 * (tve.tv_sec - tvs.tv_sec + (double)(tve.tv_usec - tvs.tv_usec)/1000000.0);
+ printf("%.3f ",t);
+ return t;
+#endif
+}
+
diff -r 458e51062300 -r 5a4d909d9533 muparserx/sample/timer.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/sample/timer.h Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,9 @@
+
+#ifndef timer_H
+#define timer_H
+
+void StartTimer(void);
+double StopTimer(void);
+double PrintTimer(void);
+
+#endif
diff -r 458e51062300 -r 5a4d909d9533 muparserx/value_test/AssemblyInfo.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/value_test/AssemblyInfo.cpp Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,40 @@
+#include "stdafx.h"
+
+using namespace System;
+using namespace System::Reflection;
+using namespace System::Runtime::CompilerServices;
+using namespace System::Runtime::InteropServices;
+using namespace System::Security::Permissions;
+
+//
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+//
+[assembly:AssemblyTitleAttribute("value_test")];
+[assembly:AssemblyDescriptionAttribute("")];
+[assembly:AssemblyConfigurationAttribute("")];
+[assembly:AssemblyCompanyAttribute("")];
+[assembly:AssemblyProductAttribute("value_test")];
+[assembly:AssemblyCopyrightAttribute("Copyright (c) 2011")];
+[assembly:AssemblyTrademarkAttribute("")];
+[assembly:AssemblyCultureAttribute("")];
+
+//
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the value or you can default the Revision and Build Numbers
+// by using the '*' as shown below:
+
+[assembly:AssemblyVersionAttribute("1.0.*")];
+
+[assembly:ComVisible(false)];
+
+[assembly:CLSCompliantAttribute(true)];
+
+[assembly:SecurityPermission(SecurityAction::RequestMinimum, UnmanagedCode = true)];
diff -r 458e51062300 -r 5a4d909d9533 muparserx/value_test/ReadMe.txt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/value_test/ReadMe.txt Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,28 @@
+========================================================================
+ APPLICATION : value_test Project Overview
+========================================================================
+
+AppWizard has created this value_test Application for you.
+
+This file contains a summary of what you will find in each of the files that
+make up your value_test application.
+
+value_test.vcproj
+ This is the main project file for VC++ projects generated using an Application Wizard.
+ It contains information about the version of Visual C++ that generated the file, and
+ information about the platforms, configurations, and project features selected with the
+ Application Wizard.
+
+value_test.cpp
+ This is the main application source file.
+
+AssemblyInfo.cpp
+ Contains custom attributes for modifying assembly metadata.
+
+/////////////////////////////////////////////////////////////////////////////
+Other notes:
+
+AppWizard uses "TODO:" to indicate parts of the source code you
+should add to or customize.
+
+/////////////////////////////////////////////////////////////////////////////
diff -r 458e51062300 -r 5a4d909d9533 muparserx/value_test/UpgradeLog.XML
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/value_test/UpgradeLog.XML Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet type='text/xsl' href='_UpgradeReport_Files/UpgradeReport.xslt'?><UpgradeLog>
+<Properties><Property Name="Solution" Value="value_test">
+</Property><Property Name="Solution File" Value="C:\Projekte\muparser_sf\branches\muParserX\value_test\value_test.sln">
+</Property><Property Name="User Options File" Value="C:\Projekte\muparser_sf\branches\muParserX\value_test\value_test.suo">
+</Property><Property Name="Date" Value="Montag, 22. August 2011">
+</Property><Property Name="Time" Value="18:49">
+</Property></Properties><Event ErrorLevel="0" Project="" Source="value_test.sln" Description="File successfully backed up as C:\Projekte\muparser_sf\branches\muParserX\value_test\value_test.sln.old">
+</Event><Event ErrorLevel="0" Project="" Source="value_test.suo" Description="File successfully backed up as C:\Projekte\muparser_sf\branches\muParserX\value_test\value_test.suo.old">
+</Event><Event ErrorLevel="0" Project="value_test" Source="value_test.vcproj" Description="Converting project file 'C:\Projekte\muparser_sf\branches\muParserX\value_test\value_test.vcproj'.">
+</Event><Event ErrorLevel="1" Project="value_test" Source="value_test.vcproj" Description="VCWebServiceProxyGeneratorTool is no longer supported. The tool has been removed from your project settings.">
+</Event><Event ErrorLevel="1" Project="value_test" Source="value_test.vcproj" Description="Attribute 'CopyLocalDependencies' of 'AssemblyReference' is not supported in this version and has been removed during conversion.">
+</Event><Event ErrorLevel="1" Project="value_test" Source="value_test.vcproj" Description="Attribute 'UseDependenciesInBuild' of 'AssemblyReference' is not supported in this version and has been removed during conversion.">
+</Event><Event ErrorLevel="1" Project="value_test" Source="value_test.vcproj" Description="Attribute 'CopyLocalDependencies' of 'AssemblyReference' is not supported in this version and has been removed during conversion.">
+</Event><Event ErrorLevel="1" Project="value_test" Source="value_test.vcproj" Description="Attribute 'UseDependenciesInBuild' of 'AssemblyReference' is not supported in this version and has been removed during conversion.">
+</Event><Event ErrorLevel="1" Project="value_test" Source="value_test.vcproj" Description="Attribute 'CopyLocalDependencies' of 'AssemblyReference' is not supported in this version and has been removed during conversion.">
+</Event><Event ErrorLevel="1" Project="value_test" Source="value_test.vcproj" Description="Attribute 'UseDependenciesInBuild' of 'AssemblyReference' is not supported in this version and has been removed during conversion.">
+</Event><Event ErrorLevel="0" Project="value_test" Source="value_test.vcproj" Description="Done converting to new project file 'C:\Projekte\muparser_sf\branches\muParserX\value_test\value_test.vcxproj'.">
+</Event><Event ErrorLevel="3" Project="value_test" Source="value_test.vcproj" Description="Converted">
+</Event><Event ErrorLevel="0" Project="" Source="value_test.sln" Description="Solution converted successfully">
+</Event><Event ErrorLevel="3" Project="" Source="value_test.sln" Description="Converted">
+</Event></UpgradeLog>
\ No newline at end of file
diff -r 458e51062300 -r 5a4d909d9533 muparserx/value_test/app.ico
Binary file muparserx/value_test/app.ico has changed
diff -r 458e51062300 -r 5a4d909d9533 muparserx/value_test/app.rc
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/value_test/app.rc Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,63 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon placed first or with lowest ID value becomes application icon
+
+LANGUAGE 7, 1
+#pragma code_page(1252)
+1 ICON "app.ico"
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+ "\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff -r 458e51062300 -r 5a4d909d9533 muparserx/value_test/mpDefines.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/value_test/mpDefines.h Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,106 @@
+/** \file
+ \brief A file containing macros used by muParserX
+
+<pre>
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+</pre>
+*/
+#ifndef MUP_DEFINES_H
+#define MUP_DEFINES_H
+
+#include <cassert>
+
+
+#if defined(_UNICODE)
+ #if !defined(_T)
+ #define _T(x) L##x
+ #endif // not defined _T
+ #define MUP_STRING_TYPE std::wstring
+#else
+ #ifndef _T
+ /** \brief Macro needed for the "unicodification" of strings.
+ */
+ #define _T(x) x
+ #endif
+
+ /** \brief The string type used by muParserX.
+
+ This macro is needed for UNICODE support.
+ */
+ #define MUP_STRING_TYPE std::string
+#endif
+
+/** \brief A macro containing the version of muParserX. */
+#define MUP_PARSER_VERSION _T("1.10.1 (20110709)")
+
+/** \brief A macro for setting the parser namespace. */
+#define MUP_NAMESPACE_START namespace mup {
+
+/** \brief Closing bracket for the parser namespace macro. */
+#define MUP_NAMESPACE_END }
+
+/** \brief A macro for casting between different token types.
+ \param TYPE The token type
+ \param POINTER Pointer to the token object
+
+ This macro uses a dynamic_cast in debugbuilds and a static_cast
+ in release builds for doing the cast operation.
+*/
+#define MUP_TOK_CAST(TYPE, POINTER) static_cast<TYPE>(POINTER);
+
+#if defined(_DEBUG)
+
+ /** \brief Debug macro to force an abortion of the programm with a certain message.
+ */
+ #define MUP_FAIL(MSG) \
+ bool MSG=false; \
+ assert(MSG);
+
+ /** \brief An assertion that does not kill the program.
+
+ This macro is neutralised in UNICODE builds. It's
+ too difficult to translate.
+ */
+ #define MUP_ASSERT(COND) \
+ if (!(COND)) \
+ { \
+ stringstream_type ss; \
+ ss << _T("Assertion \"") _T(#COND) _T("\" failed: ") \
+ << __FILE__ << _T(" line ") \
+ << __LINE__ << _T("."); \
+ throw ParserError( ss.str() ); \
+ }
+ #define MUP_LEAKAGE_REPORT
+#else
+ #define MUP_FAIL(MSG)
+ #define MUP_ASSERT(COND)
+#endif
+
+ /** \brief Include tests for features about to be implemented in
+ the future in the unit test.
+ */
+ //#define MUP_NICE_TO_HAVE
+#endif
+
+
diff -r 458e51062300 -r 5a4d909d9533 muparserx/value_test/mpError.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/value_test/mpError.cpp Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,307 @@
+/*
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+*/
+#include "mpError.h"
+#include "mpIToken.h"
+
+
+MUP_NAMESPACE_START
+
+ 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 \"$IDENT$\" 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[ecINVALID_VAR_PTR] = _T("Invalid pointer to variable");
+ m_vErrMsg[ecUNEXPECTED_OPERATOR] = _T("Unexpected operator \"$IDENT$\" found at position $POS$");
+ m_vErrMsg[ecUNEXPECTED_EOF] = _T("Unexpected end of expression at position $POS$");
+ m_vErrMsg[ecUNEXPECTED_COMMA] = _T("Unexpected comma at position $POS$");
+ m_vErrMsg[ecUNEXPECTED_PARENS ] = _T("Unexpected parenthesis \"$IDENT$\" at position $POS$");
+ m_vErrMsg[ecUNEXPECTED_FUN] = _T("Unexpected function \"$IDENT$\" at position $POS$");
+ m_vErrMsg[ecUNEXPECTED_VAL] = _T("Unexpected value \"$IDENT$\" found at position $POS$");
+ m_vErrMsg[ecUNEXPECTED_VAR] = _T("Unexpected variable \"$IDENT$\" found at position $POS$");
+ m_vErrMsg[ecUNEXPECTED_STR] = _T("Unexpected string token found at position $POS$");
+ m_vErrMsg[ecUNEXPECTED_CONDITIONAL] = _T("The \"$IDENT$\" operator must be preceeded by a closing bracket");
+ m_vErrMsg[ecUNEXPECTED_NEWLINE] = _T("Unexprected newline");
+ m_vErrMsg[ecMISSING_PARENS] = _T("Missing parenthesis");
+ m_vErrMsg[ecMISSING_ELSE_CLAUSE] = _T("If-then-else operator is missing an else clause");
+ m_vErrMsg[ecMISPLACED_COLON] = _T("Misplaced colon at position $POS$");
+ m_vErrMsg[ecTOO_MANY_PARAMS] = _T("Too many parameters for function \"$IDENT$\"");
+ m_vErrMsg[ecTOO_FEW_PARAMS] = _T("Too few parameters for function \"$IDENT$\"");
+ 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("Binary operator identifier conflicts with a built in operator");
+ 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("Numerical function called with a non value type of argument");
+ m_vErrMsg[ecTYPE_CONFLICT] = _T("Value \"$IDENT$\" is of type '$TYPE1$'. There is no implicit conversion to type '$TYPE2$'");
+ m_vErrMsg[ecTYPE_CONFLICT_FUN] = _T("Argument $ARG$ of function/operator \"$IDENT$\" is of type '$TYPE1$' whereas type '$TYPE2$' was expected");
+ m_vErrMsg[ecTYPE_CONFLICT_IDX] = _T("Index to variable \"$IDENT$\" must be a positive integer value");
+ m_vErrMsg[ecGENERIC] = _T("Parser error");
+ m_vErrMsg[ecINVALID_TYPE] = _T("Invalid argument type");
+ m_vErrMsg[ecINVALID_TYPECAST] = _T("Value type conversion from type '$TYPE1$' to '$TYPE2$' is not supported!");
+ m_vErrMsg[ecARRAY_SIZE_MISMATCH] = _T("Array size mismatch");
+ m_vErrMsg[ecNOT_AN_ARRAY] = _T("Using the index operator on the scalar variable \"$IDENT$\" is not allowed");
+ m_vErrMsg[ecUNEXPECTED_SQR_BRACKET] = _T("Unexpected \"]\"");
+ m_vErrMsg[ecAPI_INVALID_PROTOTYPE] = _T("Invalid prototype (use something like: \"f:fff\")");
+ m_vErrMsg[ecAPI_NOT_AN_ARRAY] = _T("Not an array");
+ m_vErrMsg[ecAPI_INVALID_DIMENSION] = _T("Invalid matrix dimensions");
+ m_vErrMsg[ecINDEX_OUT_OF_BOUNDS] = _T("Index to variable \"$IDENT$\" is out of bounds");
+ m_vErrMsg[ecMISSING_SQR_BRACKET] = _T("Missing \"]\"");
+ m_vErrMsg[ecASSIGNEMENT_TO_VALUE] = _T("Assignment operator \"$IDENT$\" can't be used in this context");
+ m_vErrMsg[ecEVAL] = _T("Can't evaluate function/operator \"$IDENT$\": $HINT$");
+
+ #if defined(_DEBUG)
+ for (int i=0; i<ecCOUNT; ++i)
+ if (!m_vErrMsg[i].length())
+ assert(false);
+ #endif
+ }
+
+ //---------------------------------------------------------------------------
+ //
+ // Error context
+ //
+ //---------------------------------------------------------------------------
+
+ /** \brief Constructs an empty Error context structure. */
+ ErrorContext::ErrorContext(EErrorCodes a_iErrc,
+ int a_iPos,
+ string_type a_sIdent)
+ :Expr()
+ ,Ident(a_sIdent)
+ ,Hint()
+ ,Errc(a_iErrc)
+ ,Type1(0)
+ ,Type2(0)
+ ,Arg(-1)
+ ,Pos(a_iPos)
+ {}
+
+ //---------------------------------------------------------------------------
+ ErrorContext::ErrorContext(EErrorCodes iErrc,
+ int iPos,
+ string_type sIdent,
+ char_type cType1,
+ char_type cType2,
+ int nArg)
+ :Expr()
+ ,Ident(sIdent)
+ ,Hint()
+ ,Errc(iErrc)
+ ,Type1(cType1)
+ ,Type2(cType2)
+ ,Arg(nArg)
+ ,Pos(iPos)
+ {}
+
+ //---------------------------------------------------------------------------
+ //
+ // ParserError class
+ //
+ //---------------------------------------------------------------------------
+
+ ParserError::ParserError()
+ :m_Err()
+ ,m_sMsg()
+ ,m_ErrMsg(ParserErrorMsg::Instance())
+ {}
+
+ //------------------------------------------------------------------------------
+ ParserError::ParserError(const string_type &sMsg)
+ :m_Err()
+ ,m_sMsg(sMsg)
+ ,m_ErrMsg(ParserErrorMsg::Instance())
+ {}
+
+ //------------------------------------------------------------------------------
+ ParserError::ParserError(const ErrorContext &a_Err)
+ :m_Err(a_Err)
+ ,m_sMsg()
+ ,m_ErrMsg(ParserErrorMsg::Instance())
+ {
+ m_sMsg = m_ErrMsg[a_Err.Errc];
+ }
+
+ //------------------------------------------------------------------------------
+ ParserError::ParserError(const ParserError &a_Obj)
+ :m_Err(a_Obj.m_Err)
+ ,m_sMsg(a_Obj.m_sMsg)
+ ,m_ErrMsg(ParserErrorMsg::Instance())
+ {}
+
+ //------------------------------------------------------------------------------
+ ParserError& ParserError::operator=(const ParserError &a_Obj)
+ {
+ if (this==&a_Obj)
+ return *this;
+
+ m_sMsg = a_Obj.m_sMsg;
+ m_Err = a_Obj.m_Err;
+ return *this;
+ }
+
+ //------------------------------------------------------------------------------
+ /** \brief Replace all occurences of a substring with another string. */
+ void ParserError::ReplaceSubString( string_type &sSource,
+ const string_type &sFind,
+ const string_type &sReplaceWith) const
+ {
+ string_type sResult;
+ string_type::size_type iPos(0), iNext(0);
+
+ for(;;)
+ {
+ iNext = sSource.find(sFind, iPos);
+ sResult.append(sSource, iPos, iNext-iPos);
+
+ if( iNext==string_type::npos )
+ break;
+
+ sResult.append(sReplaceWith);
+ iPos = iNext + sFind.length();
+ }
+
+ sSource.swap(sResult);
+ }
+
+
+ //------------------------------------------------------------------------------
+ /** \brief Replace all occurences of a substring with another string. */
+ void ParserError::ReplaceSubString( string_type &sSource,
+ const string_type &sFind,
+ int iReplaceWith) const
+ {
+ stringstream_type stream;
+ stream << iReplaceWith;
+ ReplaceSubString(sSource, sFind, stream.str());
+ }
+
+ //------------------------------------------------------------------------------
+ /** \brief Replace all occurences of a substring with another string. */
+ void ParserError::ReplaceSubString( string_type &sSource,
+ const string_type &sFind,
+ char_type cReplaceWith) const
+ {
+ stringstream_type stream;
+ stream << cReplaceWith;
+ ReplaceSubString(sSource, sFind, stream.str());
+ }
+
+ //------------------------------------------------------------------------------
+ void ParserError::Reset()
+ {
+ m_sMsg = _T("");
+ m_Err = ErrorContext();
+ }
+
+ //------------------------------------------------------------------------------
+ const string_type& ParserError::GetExpr() const
+ {
+ return m_Err.Expr;
+ }
+
+ //------------------------------------------------------------------------------
+ string_type ParserError::GetMsg() const
+ {
+ string_type sMsg(m_sMsg);
+ ReplaceSubString(sMsg, _T("$EXPR$"), m_Err.Expr);
+ ReplaceSubString(sMsg, _T("$IDENT$"), m_Err.Ident);
+ ReplaceSubString(sMsg, _T("$POS$"), m_Err.Pos);
+ ReplaceSubString(sMsg, _T("$ARG$"), m_Err.Arg);
+ ReplaceSubString(sMsg, _T("$TYPE1$"), m_Err.Type1);
+ ReplaceSubString(sMsg, _T("$TYPE2$"), m_Err.Type2);
+ ReplaceSubString(sMsg, _T("$HINT$"), m_Err.Hint);
+ return sMsg;
+ }
+
+ //------------------------------------------------------------------------------
+ ErrorContext& ParserError::GetContext()
+ {
+ return m_Err;
+ }
+
+ //------------------------------------------------------------------------------
+ /** \brief Return the expression position related to the error.
+
+ If the error is not related to a distinct position this will return -1
+ */
+ int ParserError::GetPos() const
+ {
+ return m_Err.Pos;
+ }
+
+ //------------------------------------------------------------------------------
+ /** \brief Return string related with this token (if available). */
+ const string_type& ParserError::GetToken() const
+ {
+ return m_Err.Ident;
+ }
+
+ //------------------------------------------------------------------------------
+ /** \brief Return the error code. */
+ EErrorCodes ParserError::GetCode() const
+ {
+ return m_Err.Errc;
+ }
+} // namespace mu
diff -r 458e51062300 -r 5a4d909d9533 muparserx/value_test/mpError.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/value_test/mpError.h Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,201 @@
+/*
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+*/
+#ifndef MUP_ERROR_H
+#define MUP_ERROR_H
+
+#include <cassert>
+#include <stdexcept>
+#include <string>
+#include <sstream>
+#include <vector>
+#include <memory>
+
+#include "mpTypes.h"
+
+
+MUP_NAMESPACE_START
+
+ /** \brief Error codes.
+
+ This is the complete list of all error codes used by muParserX
+ */
+ enum EErrorCodes
+ {
+ // Expression syntax errors
+ ecUNEXPECTED_OPERATOR = 0, ///< Unexpected binary operator found
+ ecUNASSIGNABLE_TOKEN = 1, ///< Token cant be identified.
+ ecUNEXPECTED_EOF = 2, ///< Unexpected end of expression. (Example: "2+sin(")
+ ecUNEXPECTED_COMMA = 3, ///< An unexpected comma has been found. (Example: "1,23")
+ ecUNEXPECTED_VAL = 4, ///< An unexpected value token has been found
+ ecUNEXPECTED_VAR = 5, ///< An unexpected variable token has been found
+ ecUNEXPECTED_PARENS = 6, ///< Unexpected Parenthesis, opening or closing
+ ecUNEXPECTED_STR = 7, ///< A string has been found at an inapropriate position
+ ecUNEXPECTED_CONDITIONAL = 8,
+ ecUNEXPECTED_NEWLINE = 9,
+ ecSTRING_EXPECTED = 10, ///< A string function has been called with a different type of argument
+ ecVAL_EXPECTED = 11, ///< A numerical function has been called with a non value type of argument
+ ecMISSING_PARENS = 12, ///< Missing parens. (Example: "3*sin(3")
+ ecMISSING_ELSE_CLAUSE = 13,
+ ecMISPLACED_COLON = 14,
+ ecUNEXPECTED_FUN = 15, ///< Unexpected function found. (Example: "sin(8)cos(9)")
+ ecUNTERMINATED_STRING = 16, ///< unterminated string constant. (Example: "3*valueof("hello)")
+ ecTOO_MANY_PARAMS = 17, ///< Too many function parameters
+ ecTOO_FEW_PARAMS = 18, ///< Too few function parameters. (Example: "ite(1<2,2)")
+ ecTYPE_CONFLICT = 19, ///< Generic type conflict
+ ecTYPE_CONFLICT_FUN = 20, ///< Function argument type conflict.
+ ecTYPE_CONFLICT_IDX = 21, ///< Function argument type conflict.
+ ecINVALID_TYPE = 22,
+ ecINVALID_TYPECAST = 23, ///< Invalid Value token cast.
+ ecARRAY_SIZE_MISMATCH = 24, ///< Array size mismatch during a vector operation
+ ecNOT_AN_ARRAY = 25, ///< Using the index operator on a scalar variable
+ ecUNEXPECTED_SQR_BRACKET = 26, ///< Invalid use of the index operator
+
+ // Invalid Parser input Parameters
+ ecINVALID_NAME = 27, ///< Invalid function, variable or constant name.
+ ecBUILTIN_OVERLOAD = 28, ///< Trying to overload builtin operator
+ ecINVALID_FUN_PTR = 29, ///< Invalid callback function pointer
+ ecINVALID_VAR_PTR = 30, ///< Invalid variable pointer
+
+ ecNAME_CONFLICT = 31, ///< Name conflict
+ ecOPT_PRI = 32, ///< Invalid operator priority
+ ecASSIGNEMENT_TO_VALUE = 33, ///< Assignment to operator (3=4 instead of a=4)
+
+ //
+ ecDOMAIN_ERROR = 34, ///< catch division by zero, sqrt(-1), log(0) (currently unused)
+ ecDIV_BY_ZERO = 35, ///< Division by zero (currently unused)
+ ecGENERIC = 36, ///< Generic error
+
+ ecAPI_INVALID_PROTOTYPE = 37, ///< API error: tried to create a callback with an invalid prototype definition
+ ecAPI_NOT_AN_ARRAY = 38, ///< Trying to access a non array type as an array
+ ecAPI_INVALID_DIMENSION = 39, ///< Trying to access a non array type as an array
+ ecINDEX_OUT_OF_BOUNDS = 40, ///< Array index is out of bounds
+ ecMISSING_SQR_BRACKET = 41, ///< The index operator was not closed properly (i.e. "v[3")
+ ecEVAL = 42, ///< Error while evaluating function / operator
+
+ // internal errors
+ ecINTERNAL_ERROR = 43, ///< 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
+ };
+
+ //---------------------------------------------------------------------------
+ class ParserErrorMsg
+ {
+ public:
+ typedef ParserErrorMsg self_type;
+
+ ~ParserErrorMsg();
+
+ static const ParserErrorMsg& Instance();
+ string_type operator[](unsigned a_iIdx) const;
+
+ private:
+ std::vector<string_type> m_vErrMsg;
+ static const self_type m_Instance;
+
+ ParserErrorMsg& operator=(const ParserErrorMsg &);
+ ParserErrorMsg(const ParserErrorMsg&);
+ ParserErrorMsg();
+ };
+
+ //---------------------------------------------------------------------------
+ /** \brief Error context class.
+
+ This struct contains the data associated with parser erros.
+ */
+ struct ErrorContext
+ {
+ /** \brief Creates an empty ErrorContext object.
+
+ All Members are initialised to an invalid state.
+ */
+ ErrorContext(EErrorCodes a_iErrc = ecUNDEFINED,
+ int a_iPos = -1,
+ string_type a_sIdent = string_type() );
+
+ ErrorContext(EErrorCodes a_iErrc,
+ int a_iPos,
+ string_type a_sIdent,
+ char_type cType1,
+ char_type cType2,
+ int nArg);
+
+ string_type Expr; ///> The expression string.
+ string_type Ident; ///> The identifier of the token that caused the error.
+ string_type Hint; ///> Additional message
+ EErrorCodes Errc; ///> The error code
+ char_type Type1; ///> For type conflicts only! This is the type that was expected.
+ char_type Type2; ///> For type conflicts only! This is the type that was actually found.
+ int Arg; ///> The number of arguments that were expected.
+ int Pos; ///> Position inside the expression where the error occured.
+ };
+
+ //---------------------------------------------------------------------------
+ /** \brief Error class of the parser.
+ \author Ingo Berg
+
+ Part of the math parser package.
+ */
+ class ParserError
+ {
+ private:
+ //------------------------------------------------------------------------------
+ /** \brief Replace all ocuurences of a substring with another string. */
+ void ReplaceSubString(string_type &strSource,
+ const string_type &strFind,
+ const string_type &strReplaceWith) const;
+ void ReplaceSubString(string_type &sSource,
+ const string_type &sFind,
+ int iReplaceWith) const;
+ void ReplaceSubString(string_type &sSource,
+ const string_type &sFind,
+ char_type cReplaceWith) const;
+ void Reset();
+
+ public:
+ ParserError();
+ ParserError(const string_type &sMsg);
+ ParserError(const ErrorContext &a_Err);
+ ParserError(const ParserError &a_Obj);
+ ParserError& operator=(const ParserError &a_Obj);
+
+ const string_type& GetExpr() const;
+ string_type GetMsg() const;
+ int GetPos() const;
+ const string_type& GetToken() const;
+ EErrorCodes GetCode() const;
+ ErrorContext& GetContext();
+
+ private:
+ ErrorContext m_Err; ///< Error context data
+ string_type m_sMsg; ///< The message string with all wildcards still in place.
+ const ParserErrorMsg &m_ErrMsg;
+ };
+} // namespace mu
+
+#endif
+
diff -r 458e51062300 -r 5a4d909d9533 muparserx/value_test/mpFwdDecl.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/value_test/mpFwdDecl.h Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,48 @@
+/*
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+*/
+#ifndef MUP_FWD_DECL_H
+#define MUP_FWD_DECL_H
+
+#include "mpDefines.h"
+
+
+MUP_NAMESPACE_START
+
+ class ParserXBase;
+
+ class ICallback;
+ class IToken;
+ class IValue;
+ class IValueReader;
+ class IPrecedence;
+ class Value;
+ class ValueCache;
+
+ template<typename T>
+ class TokenPtr;
+
+MUP_NAMESPACE_END
+
+#endif
\ No newline at end of file
diff -r 458e51062300 -r 5a4d909d9533 muparserx/value_test/mpIPrecedence.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/value_test/mpIPrecedence.h Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,50 @@
+/** \file mpIPrecedence.h
+ \brief Definition of base classes needed for parser operator definitions.
+
+<pre>
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+</pre>
+*/
+#ifndef MUP_IPRECEDENCE_H
+#define MUP_IPRECEDENCE_H
+
+#include "mpTypes.h"
+
+
+MUP_NAMESPACE_START
+
+ //------------------------------------------------------------------------------
+ /** \brief Interface for binary and ternary operators
+ \ingroup binop
+ */
+ class IPrecedence
+ {
+ public:
+ virtual int GetPri() const = 0;
+ virtual EOprtAsct GetAssociativity() const = 0;
+ };
+} // namespace mu
+
+#endif
+
diff -r 458e51062300 -r 5a4d909d9533 muparserx/value_test/mpIToken.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/value_test/mpIToken.cpp Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,315 @@
+/*
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+*/
+#include "mpIToken.h"
+#include <iostream>
+#include <algorithm>
+#include <vector>
+#include <list>
+#include <cassert>
+
+#include "mpIPrecedence.h"
+
+MUP_NAMESPACE_START
+
+#ifdef MUP_LEAKAGE_REPORT
+ std::list<IToken*> IToken::s_Tokens;
+#endif
+
+#ifndef _UNICODE
+
+ //---------------------------------------------------------------------------
+ /** \brief Overloaded streaming operator for outputting the value type
+ into an std::ostream.
+ \param a_Stream The stream object
+ \param a_Val The value object to be streamed
+
+ This function is only present if _UNICODE is not defined.
+ */
+ std::ostream& operator<<(std::ostream &a_Stream, const IToken &tok)
+ {
+ return a_Stream << tok.ToString();
+ }
+
+#else
+
+ //---------------------------------------------------------------------------
+ /** \brief Overloaded streaming operator for outputting the value type
+ into an std::ostream.
+ \param a_Stream The stream object
+ \param a_Val The value object to be streamed
+
+ This function is only present if _UNICODE is defined.
+ */
+ std::wostream& operator<<(std::wostream &a_Stream, const IToken &tok)
+ {
+ return a_Stream << tok.ToString();
+ }
+#endif
+
+#ifdef MUP_LEAKAGE_REPORT
+
+ void IToken::LeakageReport()
+ {
+ using namespace std;
+
+ console() << "\n";
+ console() << "Memory leakage report:\n\n";
+ if (IToken::s_Tokens.size())
+ {
+ list<IToken*>::const_iterator item = IToken::s_Tokens.begin();
+ std::vector<int> stat(cmCOUNT, 0);
+ for (; item!=IToken::s_Tokens.end(); ++item)
+ {
+ console() << "Addr: 0x" << hex << *item << " Ident: \"" << (*item)->GetIdent() << "\"";
+ console() << "\tCode: " << g_sCmdCode[(*item)->GetCode()] << "\n";
+ stat[(*item)->GetCode()]++;
+ }
+ console() << "Leaked tokens: " << dec << (int)IToken::s_Tokens.size() << std::endl;
+
+ for (int i=0; i<cmCOUNT; ++i)
+ console() << g_sCmdCode[i] << ":" << stat[i] << "\n";
+
+ console() << endl;
+ }
+ else
+ {
+ console() << "No tokens leaked!\n";
+ }
+ }
+
+#endif
+
+ //------------------------------------------------------------------------------
+ IToken::IToken(ECmdCode a_iCode)
+ :m_eCode(a_iCode)
+ ,m_sIdent()
+ ,m_nPosExpr(-1)
+ ,m_nRefCount(0)
+ ,m_flags(0)
+ {
+#ifdef MUP_LEAKAGE_REPORT
+ IToken::s_Tokens.push_back(this);
+#endif
+ }
+
+ //------------------------------------------------------------------------------
+ IToken::IToken(ECmdCode a_iCode, string_type a_sIdent)
+ :m_eCode(a_iCode)
+ ,m_sIdent(a_sIdent)
+ ,m_nPosExpr(-1)
+ ,m_nRefCount(0)
+ ,m_flags(0)
+ {
+#ifdef MUP_LEAKAGE_REPORT
+ IToken::s_Tokens.push_back(this);
+#endif
+ }
+
+ /** \brief Destructor (trivial). */
+ IToken::~IToken()
+ {
+#ifdef MUP_LEAKAGE_REPORT
+ std::list<IToken*>::iterator it = std::find(IToken::s_Tokens.begin(), IToken::s_Tokens.end(), this);
+ IToken::s_Tokens.remove(this);
+#endif
+ }
+
+ //------------------------------------------------------------------------------
+ /** \brief Copy constructor.
+ \param ref The token to copy basic state information from.
+
+ The copy constructor must be implemented in order not to screw up
+ the reference count of the created object. CC's are used in the
+ Clone function and they would start with a reference count != 0
+ introducing memory leaks if the default CC where used.
+ */
+ IToken::IToken(const IToken &ref)
+ {
+ m_eCode = ref.m_eCode;
+ m_sIdent = ref.m_sIdent;
+ m_flags = ref.m_flags;
+ m_nPosExpr = ref.m_nPosExpr;
+
+ // The following items must be initialised
+ // (rather than just beeing copied)
+ m_nRefCount = 0;
+ }
+
+ //------------------------------------------------------------------------------
+ void IToken::ResetRef()
+ {
+ m_nRefCount = 0;
+ }
+
+ //------------------------------------------------------------------------------
+ void IToken::Release()
+ {
+ delete this;
+ }
+
+ //------------------------------------------------------------------------------
+ string_type IToken::ToString() const
+ {
+ return AsciiDump();
+ }
+
+ //------------------------------------------------------------------------------
+ int IToken::GetExprPos() const
+ {
+ return m_nPosExpr;
+ }
+
+ //------------------------------------------------------------------------------
+ void IToken::SetExprPos(int nPos)
+ {
+ m_nPosExpr = nPos;
+ }
+
+ //------------------------------------------------------------------------------
+ /** \brief return the token code.
+
+ \sa ECmdCode
+ */
+ ECmdCode IToken::GetCode() const
+ {
+ return m_eCode;
+ }
+
+ //------------------------------------------------------------------------------
+ /** \brief Return the token identifier string. */
+ const string_type& IToken::GetIdent() const
+ {
+ return m_sIdent;
+ }
+
+ //------------------------------------------------------------------------------
+ void IToken::SetIdent(const string_type &a_sIdent)
+ {
+ m_sIdent = a_sIdent;
+ }
+
+ //------------------------------------------------------------------------------
+ string_type IToken::AsciiDump() const
+ {
+ stringstream_type ss;
+ ss << g_sCmdCode[m_eCode];
+ return ss.str().c_str();
+ }
+
+ //------------------------------------------------------------------------------
+ void IToken::IncRef() const
+ {
+ ++m_nRefCount;
+ }
+
+ //------------------------------------------------------------------------------
+ long IToken::DecRef() const
+ {
+ return --m_nRefCount;
+ }
+
+ //------------------------------------------------------------------------------
+ long IToken::GetRef() const
+ {
+ return m_nRefCount;
+ }
+
+ //---------------------------------------------------------------------------
+ void IToken::AddFlags(int flags)
+ {
+ m_flags |= flags;
+ }
+
+ //---------------------------------------------------------------------------
+ bool IToken::IsFlagSet(int flags) const
+ {
+ return (m_flags & flags)==flags;
+ }
+
+ //---------------------------------------------------------------------------
+ ICallback* IToken::AsICallback()
+ {
+ return NULL;
+ }
+
+ //---------------------------------------------------------------------------
+ IValue* IToken::AsIValue()
+ {
+ return NULL;
+ }
+
+ //---------------------------------------------------------------------------
+ IPrecedence* IToken::AsIPrecedence()
+ {
+ return NULL;
+ }
+
+ //------------------------------------------------------------------------------
+ void IToken::Compile(const string_type &sArg)
+ {
+ }
+
+ //---------------------------------------------------------------------------
+ //
+ // Generic token implementation
+ //
+ //---------------------------------------------------------------------------
+
+ GenericToken::GenericToken(ECmdCode a_iCode, string_type a_sIdent)
+ :IToken(a_iCode, a_sIdent)
+ {}
+
+ //---------------------------------------------------------------------------
+ GenericToken::GenericToken(ECmdCode a_iCode)
+ :IToken(a_iCode, _T(""))
+ {}
+
+ //---------------------------------------------------------------------------
+ GenericToken::~GenericToken()
+ {}
+
+ //---------------------------------------------------------------------------
+ GenericToken::GenericToken(const GenericToken &a_Tok)
+ :IToken(a_Tok)
+ {}
+
+ //---------------------------------------------------------------------------
+ IToken* GenericToken::Clone() const
+ {
+ return new GenericToken(*this);
+ }
+
+ //------------------------------------------------------------------------------
+ string_type GenericToken::AsciiDump() const
+ {
+ stringstream_type ss;
+
+ ss << g_sCmdCode[ GetCode() ];
+ ss << _T(" [addr=0x") << std::hex << this << _T("]");
+
+ return ss.str();
+ }
+
+MUP_NAMESPACE_END
diff -r 458e51062300 -r 5a4d909d9533 muparserx/value_test/mpIToken.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/value_test/mpIToken.h Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,222 @@
+/*
+<pre>
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+</pre>
+*/
+#ifndef MUP_ITOKEN_H
+#define MUP_ITOKEN_H
+
+#include <list>
+#include "mpTypes.h"
+#include "mpFwdDecl.h"
+
+MUP_NAMESPACE_START
+
+ //------------------------------------------------------------------------------
+ /** \brief Generic token interface for expression tokens.
+ \author (C) 2010 Ingo Berg
+
+ Tokens can either be Functions, operators, values, variables or necessary
+ base tokens like brackets. ´The IToken baseclass implements reference
+ counting. Only TokenPtr<...> templates may be used as pointers to tokens.
+ */
+ class IToken
+ {
+ friend std::ostream& operator<<(std::ostream &a_Stream, const IToken &a_Val);
+ friend std::wostream& operator<<(std::wostream &a_Stream, const IToken &a_Val);
+
+ friend class TokenPtr<IToken>;
+ friend class TokenPtr<IValue>;
+ friend class TokenPtr<IOprtBin>;
+ friend class TokenPtr<IFunction>;
+ friend class TokenPtr<Value>;
+ friend class TokenPtr<Variable>;
+
+ public:
+
+ enum EFlags
+ {
+ flNONE = 0,
+ flVOLATILE = 1
+ };
+
+ virtual IToken* Clone() const = 0;
+ virtual string_type ToString() const;
+ virtual string_type AsciiDump() const;
+
+ virtual ICallback* AsICallback();
+ virtual IValue* AsIValue();
+ virtual IPrecedence* AsIPrecedence();
+
+ virtual void Compile(const string_type &sArg);
+
+ ECmdCode GetCode() const;
+ int GetExprPos() const;
+
+ const string_type& GetIdent() const;
+ long GetRef() const;
+ void SetIdent(const string_type &a_sIdent);
+ void SetExprPos(int nPos);
+
+ void AddFlags(int flags);
+ bool IsFlagSet(int flags) const;
+
+ protected:
+
+ explicit IToken(ECmdCode a_iCode);
+ virtual ~IToken();
+ IToken(ECmdCode a_iCode, string_type a_sIdent);
+ IToken(const IToken &ref);
+
+ void ResetRef();
+
+ private:
+
+ /** \brief Release the token.
+
+ This Function either deletes the token or releases it to
+ the value cache for reuse without deletion.
+ */
+ virtual void Release();
+
+ void IncRef() const;
+ long DecRef() const;
+
+ ECmdCode m_eCode;
+ string_type m_sIdent;
+ int m_nPosExpr; ///< Original position of the token in the expression
+ mutable long m_nRefCount; ///< Reference counter.
+ int m_flags;
+
+#ifdef MUP_LEAKAGE_REPORT
+ static std::list<IToken*> s_Tokens;
+
+ public:
+ static void LeakageReport();
+#endif
+ };
+
+
+ //---------------------------------------------------------------------------
+ /** \brief Default token implentation.
+ */
+ class GenericToken : public IToken
+ {
+ public:
+ GenericToken(ECmdCode a_iCode, string_type a_sIdent);
+ explicit GenericToken(ECmdCode a_iCode);
+ GenericToken(const GenericToken &a_Tok);
+ virtual ~GenericToken();
+ virtual IToken* Clone() const;
+ virtual string_type AsciiDump() const;
+ };
+
+ //------------------------------------------------------------------------------
+ template<typename T>
+ class TokenPtr
+ {
+ public:
+
+ typedef T* token_type;
+
+ //---------------------------------------------------------------------------
+ explicit TokenPtr(token_type p = 0)
+ :m_pTok(p)
+ {
+ if (m_pTok)
+ m_pTok->IncRef();
+ }
+
+ //---------------------------------------------------------------------------
+ TokenPtr(const TokenPtr &p)
+ :m_pTok(p.m_pTok)
+ {
+ if (m_pTok)
+ m_pTok->IncRef();
+ }
+
+ //---------------------------------------------------------------------------
+ ~TokenPtr()
+ {
+ if (m_pTok && m_pTok->DecRef()==0)
+ m_pTok->Release();
+ }
+
+ //---------------------------------------------------------------------------
+ token_type operator->() const
+ {
+ return static_cast<token_type>(m_pTok);
+ }
+
+ //---------------------------------------------------------------------------
+ T& operator*() const
+ {
+ assert(m_pTok);
+ return *(static_cast<token_type>(m_pTok));
+ }
+
+ //---------------------------------------------------------------------------
+ token_type Get() const
+ {
+ return static_cast<token_type>(m_pTok);
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Release the managed pointer and assign a new pointer. */
+ void Reset(token_type tok)
+ {
+ if (m_pTok && m_pTok->DecRef()==0)
+ {
+ m_pTok->Release();
+ //delete m_pTok;
+ }
+
+ tok->IncRef();
+ m_pTok = tok;
+ }
+
+ //---------------------------------------------------------------------------
+ TokenPtr& operator=(const TokenPtr &p)
+ {
+ if (p.m_pTok)
+ p.m_pTok->IncRef();
+
+ if (m_pTok && m_pTok->DecRef()==0)
+ {
+ m_pTok->Release();
+ //delete m_pTok;
+ }
+
+ m_pTok = p.m_pTok;
+
+ return *this;
+ }
+
+ private:
+ IToken *m_pTok;
+ };
+
+MUP_NAMESPACE_END
+
+#endif // include guard
diff -r 458e51062300 -r 5a4d909d9533 muparserx/value_test/mpIValReader.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/value_test/mpIValReader.h Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,85 @@
+/*
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+*/
+#ifndef MU_IPARSER_VALUE_READER_H
+#define MU_IPARSER_VALUE_READER_H
+
+#include "mpValue.h"
+#include "mpIToken.h"
+#include "mpTokenReader.h"
+
+
+MUP_NAMESPACE_START
+
+ class TokenReader;
+
+ /** \brief Interface for custom value reader objects.
+
+ Value readers are objects used for identifying values
+ in an expression.
+ */
+ class IValueReader
+ {
+ public:
+
+ IValueReader();
+ IValueReader(const IValueReader &ref);
+
+ virtual ~IValueReader();
+
+ /** \brief Check a certain position in an expression for the presence of a value.
+ \param a_iPos [in/out] Reference to an integer value representing the current
+ position of the parser in the expression.
+ \param a_Val If a value is found it is stored in a_Val
+ \return true if a value was found
+ */
+ virtual bool IsValue(const char_type *a_szExpr,
+ int &a_iPos,
+ Value &a_Val ) = 0;
+
+ /** \brief Clone this ValueReader object.
+ \return Pointer to the cloned value reader object.
+ */
+ virtual IValueReader* Clone(TokenReader *pParent) const = 0;
+
+ /** \brief Assign this value reader object to a token
+ reader object.
+
+ The token reader does the tokenization of the expression.
+ It uses this value reader to detect values.
+ */
+ virtual void SetParent(TokenReader *pTokenReader);
+
+ protected:
+
+ const IToken* TokenHistory(std::size_t pos) const;
+
+ private:
+
+ TokenReader *m_pTokenReader; ///< Pointer to the TokenReader class used for token recognition
+ }; // class IValueReader
+
+MUP_NAMESPACE_END
+
+#endif
diff -r 458e51062300 -r 5a4d909d9533 muparserx/value_test/mpIValue.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/value_test/mpIValue.cpp Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,415 @@
+/** \file
+ \brief Implementation of the virtual base class used for all parser values.
+
+<pre>
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+</pre>
+*/
+#include "mpIValue.h"
+
+//--- Standard includes ---------------------------------------------------------------------------
+#include <cassert>
+
+//--- muParserX framework -------------------------------------------------------------------------
+#include "mpError.h"
+#include "mpValue.h"
+
+
+MUP_NAMESPACE_START
+
+#ifndef _UNICODE
+
+ //-----------------------------------------------------------------------------------------------
+ /** \brief Overloaded streaming operator for outputting the value type
+ into an std::ostream.
+ \param a_Stream The stream object
+ \param a_Val The value object to be streamed
+
+ This function is only present if _UNICODE is not defined.
+ */
+ std::ostream& operator<<(std::ostream &a_Stream, const IValue &a_Val)
+ {
+ return a_Stream << a_Val.ToString();
+ }
+
+#else
+
+ //-----------------------------------------------------------------------------------------------
+ /** \brief Overloaded streaming operator for outputting the value type
+ into an std::ostream.
+ \param a_Stream The stream object
+ \param a_Val The value object to be streamed
+
+ This function is only present if _UNICODE is defined.
+ */
+ std::wostream& operator<<(std::wostream &a_Stream, const IValue &a_Val)
+ {
+ return a_Stream << a_Val.ToString();
+ }
+#endif
+
+ //-----------------------------------------------------------------------------------------------
+ IValue::IValue(ECmdCode a_iCode)
+ :IToken(a_iCode)
+ {
+ assert(a_iCode==cmVAL || a_iCode==cmVAR);
+ }
+
+ //-----------------------------------------------------------------------------------------------
+ IValue::IValue(ECmdCode a_iCode, const string_type &a_sIdent)
+ :IToken(a_iCode, a_sIdent)
+ {
+ assert(a_iCode==cmVAL || a_iCode==cmVAR);
+ }
+
+ //-----------------------------------------------------------------------------------------------
+ IValue::~IValue()
+ {}
+
+ //-----------------------------------------------------------------------------------------------
+ ICallback* IValue::AsICallback()
+ {
+ return NULL;
+ }
+
+ //-----------------------------------------------------------------------------------------------
+ IValue* IValue::AsIValue()
+ {
+ return this;
+ }
+
+ //-----------------------------------------------------------------------------------------------
+ string_type IValue::ToString() const
+ {
+ stringstream_type ss;
+ switch (GetType())
+ {
+ case 'a':
+ {
+ const array_type &arr(GetArray());
+ ss << _T("[");
+ for (std::size_t i=0; i<arr.size(); ++i)
+ {
+ ss << arr[i];
+ if (i!=arr.size()-1)
+ {
+ if (arr[i].GetType()!='a')
+ ss << _T("; ");
+ else
+ ss << _T("\n ");
+ }
+ }
+ ss << _T("]");
+ }
+ break;
+ case 'c':
+ {
+ float_type re = GetFloat(),
+ im = GetImag();
+
+ // realteil nicht ausgeben, wenn es eine rein imaginäre Zahl ist
+ if (im==0 || re!=0 || (im==0 && re==0))
+ ss << re;
+
+ if (im!=0)
+ {
+ if (im>0 && re!=0)
+ ss << _T("+");
+
+ if (im!=1)
+ ss << im;
+
+ ss << _T("i");
+ }
+ }
+ break;
+
+ case 'i':
+ case 'f': ss << GetFloat(); break;
+ case 's': ss << _T("\"") << GetString() << _T("\""); break;
+ case 'b': ss << ((GetBool()==true) ? _T("true"):_T("false")); break;
+ case 'v': ss << _T("void"); break;
+ default: ss << _T("internal error: unknown value type."); break;
+ }
+
+ return ss.str();
+ }
+
+ //-----------------------------------------------------------------------------------------------
+ bool IValue::operator==(const IValue &a_Val) const
+ {
+ char_type type1 = GetType(),
+ type2 = a_Val.GetType();
+
+ if (type1==type2 || IsScalar() && a_Val.IsScalar())
+ {
+ switch(GetType())
+ {
+ case 'i':
+ case 'f': return GetFloat() == a_Val.GetFloat();
+ case 'c': return GetComplex() == a_Val.GetComplex();
+ case 's': return GetString() == a_Val.GetString();
+ case 'b': return GetBool() == a_Val.GetBool();
+ case 'v': return false;
+ case 'a': if (GetDim()!=a_Val.GetDim())
+ {
+ return false;
+ }
+ else
+ {
+ for (std::size_t i=0; i<GetDim(); ++i)
+ {
+ if (const_cast<IValue*>(this)->operator[](i)!=const_cast<IValue&>(a_Val)[i])
+ return false;
+ }
+
+ return true;
+ }
+ default:
+ ErrorContext err;
+ err.Errc = ecINTERNAL_ERROR;
+ err.Pos = -1;
+ err.Type1 = GetType();
+ err.Type2 = a_Val.GetType();
+ throw ParserError(err);
+ } // switch this type
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ //-----------------------------------------------------------------------------------------------
+ bool IValue::operator!=(const IValue &a_Val) const
+ {
+ char_type type1 = GetType(),
+ type2 = a_Val.GetType();
+
+ if (type1==type2 || IsScalar() && a_Val.IsScalar())
+ {
+ switch(GetType())
+ {
+ case 's': return GetString() != a_Val.GetString();
+ case 'i':
+ case 'f': return GetFloat() != a_Val.GetFloat();
+ case 'c': return (GetFloat() != a_Val.GetFloat()) || (GetImag() != a_Val.GetImag());
+ case 'b': return GetBool() != a_Val.GetBool();
+ case 'v': return true;
+ case 'a': if (GetDim()!=a_Val.GetDim())
+ {
+ return true;
+ }
+ else
+ {
+ for (std::size_t i=0; i<GetDim(); ++i)
+ {
+ if (const_cast<IValue*>(this)->operator[](i)!=const_cast<IValue&>(a_Val)[i])
+ return true;
+ }
+
+ return false;
+ }
+ default:
+ ErrorContext err;
+ err.Errc = ecINTERNAL_ERROR;
+ err.Pos = -1;
+ err.Type2 = GetType();
+ err.Type1 = a_Val.GetType();
+ throw ParserError(err);
+ } // switch this type
+ }
+ else
+ {
+ return true;
+ }
+ }
+
+ //-----------------------------------------------------------------------------------------------
+ bool IValue::operator<(const IValue &a_Val) const
+ {
+ char_type type1 = GetType(),
+ type2 = a_Val.GetType();
+
+ if (type1==type2 || IsScalar() && a_Val.IsScalar())
+ {
+ switch(GetType())
+ {
+ case 's': return GetString() < a_Val.GetString();
+ case 'i':
+ case 'f':
+ case 'c': return GetFloat() < a_Val.GetFloat();
+ case 'b': return GetBool() < a_Val.GetBool();
+
+ default:
+ ErrorContext err;
+ err.Errc = ecINTERNAL_ERROR;
+ err.Pos = -1;
+ err.Type1 = GetType();
+ err.Type2 = a_Val.GetType();
+ throw ParserError(err);
+ } // switch this type
+ }
+ else
+ {
+ ErrorContext err;
+ err.Errc = ecTYPE_CONFLICT_FUN;
+ err.Arg = (type1!='f' && type1!='i') ? 1 : 2;
+ err.Type1 = type2;
+ err.Type2 = type1;
+ throw ParserError(err);
+ }
+ }
+
+ //-----------------------------------------------------------------------------------------------
+ bool IValue::operator> (const IValue &a_Val) const
+ {
+ char_type type1 = GetType(),
+ type2 = a_Val.GetType();
+
+ if (type1==type2 || IsScalar() && a_Val.IsScalar())
+ {
+ switch(GetType())
+ {
+ case 's': return GetString() > a_Val.GetString();
+ case 'i':
+ case 'f':
+ case 'c': return GetFloat() > a_Val.GetFloat();
+ case 'b': return GetBool() > a_Val.GetBool();
+ default:
+ ErrorContext err;
+ err.Errc = ecINTERNAL_ERROR;
+ err.Pos = -1;
+ err.Type1 = GetType();
+ err.Type2 = a_Val.GetType();
+ throw ParserError(err);
+
+ } // switch this type
+ }
+ else
+ {
+ ErrorContext err;
+ err.Errc = ecTYPE_CONFLICT_FUN;
+ err.Arg = (type1!='f' && type1!='i') ? 1 : 2;
+ err.Type1 = type2;
+ err.Type2 = type1;
+ throw ParserError(err);
+ }
+ }
+
+ //-----------------------------------------------------------------------------------------------
+ bool IValue::operator>=(const IValue &a_Val) const
+ {
+ char_type type1 = GetType(),
+ type2 = a_Val.GetType();
+
+ if (type1==type2 || IsScalar() && a_Val.IsScalar())
+ {
+ switch(GetType())
+ {
+ case 's': return GetString() >= a_Val.GetString();
+ case 'i':
+ case 'f':
+ case 'c': return GetFloat() >= a_Val.GetFloat();
+ case 'b': return GetBool() >= a_Val.GetBool();
+ default:
+ ErrorContext err;
+ err.Errc = ecINTERNAL_ERROR;
+ err.Pos = -1;
+ err.Type1 = GetType();
+ err.Type2 = a_Val.GetType();
+ throw ParserError(err);
+
+ } // switch this type
+ }
+ else
+ {
+ ErrorContext err;
+ err.Errc = ecTYPE_CONFLICT_FUN;
+ err.Arg = (type1!='f' && type1!='i') ? 1 : 2;
+ err.Type1 = type2;
+ err.Type2 = type1;
+ throw ParserError(err);
+ }
+ }
+
+ //-----------------------------------------------------------------------------------------------
+ bool IValue::operator<=(const IValue &a_Val) const
+ {
+ char_type type1 = GetType(),
+ type2 = a_Val.GetType();
+
+ if (type1==type2 || IsScalar() && a_Val.IsScalar())
+ {
+ switch(GetType())
+ {
+ case 's': return GetString() <= a_Val.GetString();
+ case 'i':
+ case 'f':
+ case 'c': return GetFloat() <= a_Val.GetFloat();
+ case 'b': return GetBool() <= a_Val.GetBool();
+ default:
+ ErrorContext err;
+ err.Errc = ecINTERNAL_ERROR;
+ err.Pos = -1;
+ err.Type1 = GetType();
+ err.Type2 = a_Val.GetType();
+ throw ParserError(err);
+
+ } // switch this type
+ }
+ else
+ {
+ ErrorContext err;
+ err.Errc = ecTYPE_CONFLICT_FUN;
+ err.Arg = (type1!='f' && type1!='i') ? 1 : 2;
+ err.Type1 = type2;
+ err.Type2 = type1;
+ throw ParserError(err);
+ }
+ }
+
+ //-----------------------------------------------------------------------------------------------
+ IValue& IValue::operator=(const IValue &ref)
+ {
+ if (this==&ref)
+ return *this;
+
+ switch(ref.GetType())
+ {
+ case 'i':
+ case 'f':
+ case 'c': return *this = cmplx_type(ref.GetFloat(), ref.GetImag());
+ case 's': return *this = ref.GetString();
+ case 'a': return *this = ref.GetArray();
+ case 'b': return *this = ref.GetBool();
+ case 'v':
+ throw ParserError(_T("Assignment from void type is not possible"));
+
+ default:
+ throw ParserError(_T("Internal error: unexpected data type identifier in IValue& operator=(const IValue &ref)"));
+ }
+ }
+
+MUP_NAMESPACE_END
diff -r 458e51062300 -r 5a4d909d9533 muparserx/value_test/mpIValue.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/value_test/mpIValue.h Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,155 @@
+/** \file
+ \brief Definition of the virtual base class used for all parser values.
+
+<pre>
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+</pre>
+*/
+#ifndef MUP_IVALUE_H
+#define MUP_IVALUE_H
+
+#include "mpIToken.h"
+#include "mpFwdDecl.h"
+
+MUP_NAMESPACE_START
+
+ //-----------------------------------------------------------------------------------------------
+ /** \brief Interface to be implemented by all classes representing values.
+
+ IValue is the common base class of both the Value and Variable classes.
+ */
+ class IValue : public IToken
+ {
+ friend std::ostream& operator<<(std::ostream &a_Stream, const IValue &a_Val);
+ friend std::wostream& operator<<(std::wostream &a_Stream, const IValue &a_Val);
+
+ public:
+
+ explicit IValue(ECmdCode a_iCode);
+ IValue(ECmdCode a_iCode, const string_type &a_sIdent);
+
+ bool operator==(const IValue &a_Val) const;
+ bool operator!=(const IValue &a_Val) const;
+ bool operator< (const IValue &a_Val) const;
+ bool operator> (const IValue &a_Val) const;
+ bool operator<=(const IValue &a_Val) const;
+ bool operator>=(const IValue &a_Val) const;
+
+ virtual ICallback* AsICallback();
+ virtual IValue* AsIValue();
+ virtual Value* AsValue() = 0;
+
+ virtual IValue& operator=(int_type val) = 0;
+ virtual IValue& operator=(float_type val) = 0;
+ virtual IValue& operator=(string_type val) = 0;
+ virtual IValue& operator=(bool_type val) = 0;
+ virtual IValue& operator=(const cmplx_type &val) = 0;
+ virtual IValue& operator=(const array_type &val) = 0;
+ IValue& operator=(const IValue &ref);
+
+ virtual IValue& operator[](std::size_t idx) = 0;
+ virtual int_type GetInteger() const = 0;
+ virtual float_type GetFloat() const = 0;
+ virtual float_type GetImag() const = 0;
+ virtual bool GetBool() const = 0;
+ virtual const cmplx_type& GetComplex() const = 0;
+ virtual const string_type& GetString() const = 0;
+ virtual const array_type& GetArray() const = 0;
+ virtual char_type GetType() const = 0;
+
+ virtual bool IsVolatile() const = 0;
+ virtual string_type ToString() const;
+
+ //---------------------------------------------------------------------------
+ inline std::size_t GetDim() const
+ {
+ return (GetType()!='a') ? 1 : GetArray().size();
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Returns true if the type is either floating point or interger.
+ \throw nothrow
+ */
+ inline bool IsNonComplexScalar() const
+ {
+ char_type t = GetType();
+ return t=='f' || t=='i';
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Returns true if the type is not a vector and not a string.
+ \throw nothrow
+ */
+ inline bool IsScalar() const
+ {
+ char_type t = GetType();
+ return t=='f' || t=='i' || t=='c';
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Returns true if this value is a noncomplex integer.
+ \throw nothrow
+ */
+ inline bool IsInteger() const
+ {
+ // checking the type is is insufficient. The integer could be disguised
+ // as a float or a complex value
+ return IsScalar() && GetImag()==0 && GetFloat()==(int_type)GetFloat();
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Returns true if this value is an array.
+ \throw nothrow
+ */
+ inline bool IsArray() const
+ {
+ return GetType() == 'a';
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Returns true if this value is a complex value.
+ \throw nothrow
+ */
+ inline bool IsComplex() const
+ {
+ return GetType() == 'c' && GetImag()!=0;
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Returns true if this value is a string value.
+ \throw nothrow
+ */
+ inline bool IsString() const
+ {
+ return GetType() == 's';
+ }
+
+ protected:
+ virtual ~IValue();
+ }; // class IValue
+} // namespace mu
+
+#endif
+
+
diff -r 458e51062300 -r 5a4d909d9533 muparserx/value_test/mpTypes.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/value_test/mpTypes.h Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,309 @@
+/** \file
+ \brief Definition of basic types used by muParserX
+
+<pre>
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+</pre>
+*/
+#ifndef MUP_TYPES_H
+#define MUP_TYPES_H
+
+//--- Standard include ------------------------------------------------------
+#include <string>
+#include <iostream>
+#include <sstream>
+#include <vector>
+#include <map>
+#include <complex>
+
+//--- muParserX framework ---------------------------------------------------
+#include "suSortPred.h" // We need the string utils sorting predicates
+#include "mpDefines.h"
+
+
+MUP_NAMESPACE_START
+
+// Forward declarations
+ class IValueReader;
+ class IOprtBin;
+ class IOprtPostfix;
+ class IOprtInfix;
+ class IFunction;
+ class IToken;
+ class IValue;
+ class ParserXBase;
+ class Value;
+ class Variable;
+ class TokenReader;
+
+ // smart pointer types
+ template<typename T>
+ class TokenPtr;
+
+ /** \brief Type of a managed pointer storing parser tokens. */
+ typedef TokenPtr<IToken> ptr_tok_type;
+
+ /** \brief Type of a managed pointer storing value tokens. */
+ typedef TokenPtr<IValue> ptr_val_type;
+
+ /** \brief Type of a managed pointer storing binary operator tokens. */
+ typedef TokenPtr<IOprtBin> ptr_binop_type;
+
+ /** \brief Type for a vector of tokens. */
+ typedef std::vector<ptr_tok_type> token_vec_type;
+
+ /** \brief Type for a vector of value items. */
+ typedef std::vector<ptr_val_type> val_vec_type;
+
+ // parser type definitions
+
+ /** \brief Parser datatype for floating point value. */
+ typedef /*long*/ double float_type;
+
+ /** \brief Parser datatype for integer valuse. */
+ typedef int int_type;
+
+ /** \brief The basic type used for representing complex numbers. */
+ typedef std::complex<float_type> cmplx_type;
+
+ /** \brief Parser boolean datatype.
+
+ This must be bool! The only reason for this typedef is that I need the name bool_type
+ for a preprocessor macro definition to avoid inconsistent naming of the macro parameters.
+ */
+ typedef bool bool_type;
+
+ /** \brief The parsers array type. */
+ typedef std::vector<Value> array_type;
+
+ /** \brief Parser datatype for strings. */
+ typedef MUP_STRING_TYPE string_type;
+
+ /** \brief Character type of the parser. */
+ typedef string_type::value_type char_type;
+
+ typedef std::basic_stringstream<char_type,
+ std::char_traits<char_type>,
+ std::allocator<char_type> > stringstream_type;
+
+ /** \brief Type of a vector holding pointers to value reader objects. */
+ typedef std::vector<IValueReader*> readervec_type;
+
+ /** \brief type for the parser variable storage. */
+ typedef std::map<string_type, ptr_tok_type> var_maptype;
+
+ /** \brief type of a container used to store parser values. */
+ typedef std::map<string_type, ptr_tok_type> val_maptype;
+
+ /** \brief Type of a container that binds Callback object pointer
+ to operator identifiers. */
+ typedef std::map<string_type, ptr_tok_type> fun_maptype;
+
+ /** \brief Type of a container that binds Callback object pointer
+ to operator identifiers. */
+ typedef std::map<string_type, ptr_tok_type, su::pred::SortByLength<string_type> > oprt_bin_maptype;
+
+ typedef std::multimap<string_type, ptr_tok_type, su::pred::SortByLength<string_type> > oprt_bin_multimap;
+
+ /** \brief Type of a map for storing postfix operators by their name. */
+ typedef std::map<string_type, ptr_tok_type> oprt_pfx_maptype;
+
+ /** \brief Type of a map for storing infix operators by their name. */
+ typedef std::map<string_type, ptr_tok_type> oprt_ifx_maptype;
+
+ //------------------------------------------------------------------------------
+ /** \brief Bytecode values.
+ \attention The order of the operator entries must match the order in
+ ParserXBase::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.
+ cmBO = 0, ///< Operator item: opening bracket
+ cmBC = 1, ///< Operator item: closing bracket
+ cmIO = 2, ///< Operator item: index operator opening
+ cmIC = 3, ///< Operator item: index operator closing
+ cmARG_SEP = 4, ///< Operator item: comma
+ cmIF = 5, ///< Ternary if then else operator
+ cmELSE = 6, ///< Ternary if then else operator
+ cmENDIF = 7, ///< Ternary if then else operator
+ cmJMP = 8, ///< Reserved for future use
+ cmVAR = 9, ///< variable item
+ cmVAL = 10, ///< value item
+ cmFUNC = 11, ///< Code for a function item
+ cmOPRT_BIN = 12, ///< Binary operator
+ cmOPRT_INFIX = 13, ///< Infix operator
+ cmOPRT_POSTFIX = 14, ///< Postfix operator
+ cmEOE = 15, ///< End of expression
+
+ // The following codes are reserved in case i will ever turn this
+ // into a scripting language
+ cmSCRIPT_GOTO = 16, ///< Reserved for future use
+ cmSCRIPT_LABEL = 17, ///< Reserved for future use
+ cmSCRIPT_FOR = 18, ///< Reserved for future use
+ cmSCRIPT_IF = 19, ///< Reserved for future use
+ cmSCRIPT_ELSE = 20, ///< Reserved for future use
+ cmSCRIPT_ELSEIF = 21, ///< Reserved for future use
+ cnSCRIPT_ENDIF = 22, ///< Reserved for future use
+ cmSCRIPT_NEWLINE = 23, ///< Newline
+ cmSCRIPT_FUNCTION = 24, ///< Reserved for future use
+
+ // misc codes
+ cmUNKNOWN = 25, ///< uninitialized item
+ cmCOUNT = 26 ///< Dummy entry for counting the enum values
+ }; // ECmdCode
+
+
+ //------------------------------------------------------------------------------
+ /** \brief Strings assigned to the enum codes of ECmdCode.
+
+ Used for debugging purposes only.
+ */
+ extern const char_type *g_sCmdCode[];
+
+ //------------------------------------------------------------------------------
+ enum EPackages
+ {
+ pckCOMMON = 1 << 0,
+ pckUNIT = 1 << 1,
+ pckCOMPLEX = 1 << 2,
+ pckNON_COMPLEX = 1 << 3,
+ pckSTRING = 1 << 4,
+ pckALL_COMPLEX = pckCOMMON | pckCOMPLEX | pckSTRING | pckUNIT,
+ pckALL_NON_COMPLEX = pckCOMMON | pckNON_COMPLEX | pckSTRING | pckUNIT
+ };
+
+ //------------------------------------------------------------------------------
+ /** \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 "()"
+ noIO = 1 << 2, ///< No opening bracket "["
+ noIC = 1 << 3, ///< No closing bracket "]"
+ noVAL = 1 << 4, ///< to avoid i.e. "tan 2" or "sin(8)3.14"
+ noVAR = 1 << 5, ///< to avoid i.e. "sin a" or "sin(8)a"
+ noCOMMA = 1 << 6, ///< to avoid i.e. ",," or "+," ...
+ noFUN = 1 << 7, ///< to avoid i.e. "sqrt cos" or "(1)sin"
+ noOPT = 1 << 8, ///< to avoid i.e. "(+)"
+ noPFX = 1 << 9, ///< to avoid i.e. "(5!!)" "sin!"
+ noIFX = 1 << 10, ///< to avoid i.e. "++4" "!!4"
+ noEND = 1 << 11, ///< to avoid unexpected end of expression
+ noIF = 1 << 12,
+ noELSE = 1 << 13,
+ noNEWLINE = 1 << 14, ///< to avoid i.e. "a+\nb" or "sin(\na)"
+
+ sfSTART_OF_LINE = noOPT | noBC | noPFX | noCOMMA | noIO | noIC | noIF | noELSE,
+ sfALLOW_NONE = ~0 ///< All of he above flags set
+ };
+
+ //------------------------------------------------------------------------------
+ /** \brief Binary operator associativity values. */
+ enum EOprtAsct
+ {
+ oaNONE = 0,
+ oaLEFT = 1,
+ oaRIGHT = 2,
+ };
+
+ //------------------------------------------------------------------------------
+ /** \brief Parser operator precedence values.
+
+ These are predefined values for the operator precedence.
+ */
+ enum EOprtPrecedence
+ {
+ // assignment operators
+ prASSIGN = -1,
+
+ // if-then-else
+ prIF_THEN_ELSE = 0,
+
+ // binary operators
+ prLOGIC_OR = 1,
+ prLOGIC_AND = 2,
+ prBIT_OR = 3,
+ prBIT_AND = 4,
+
+ prRELATIONAL1 = 5, ///< For "==", "!="
+ prRELATIONAL2 = 6, ///< Relational operators "<", "<=", ">", ">="
+ prSHIFT = 7, ///< Shift operators "<<", ">>"
+
+ prADD_SUB = 8, ///< addition
+ prMUL_DIV = 9, ///< multiplication/division
+ prPOW = 10, ///< power operator priority (highest)
+
+ // infix operators
+ prINFIX = 9, ///< Signs have a higher priority than ADD_SUB, but lower than power operator
+ prPOSTFIX = 9 ///< Postfix operator priority (currently unused)
+ };
+
+#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 // _UNICODE
+
+} // namespace mu
+
+#endif
diff -r 458e51062300 -r 5a4d909d9533 muparserx/value_test/mpValue.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/value_test/mpValue.cpp Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,640 @@
+/*
+<pre>
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+</pre>
+*/
+#include "mpValue.h"
+#include "mpError.h"
+#include "mpValueCache.h"
+
+
+MUP_NAMESPACE_START
+
+ //------------------------------------------------------------------------------
+ /** \brief Construct an empty value object of a given type.
+ \param cType The type of the value to construct (default='v').
+ */
+ Value::Value(char_type cType)
+ :IValue(cmVAL)
+ ,m_val(0,0)
+ ,m_psVal(NULL)
+ ,m_pvVal(NULL)
+ ,m_cType(cType)
+ ,m_iFlags(flNONE)
+ ,m_pCache(NULL)
+ {
+ // strings and arrays must allocate their memory
+ switch (cType)
+ {
+ case 's': m_psVal = new string_type(); break;
+ case 'a': m_pvVal = new array_type(0, Value(0)); break;
+ }
+ }
+
+ //---------------------------------------------------------------------------
+ Value::Value(int_type a_iVal)
+ :IValue(cmVAL)
+ ,m_val((float_type)a_iVal, 0)
+ ,m_psVal(NULL)
+ ,m_pvVal(NULL)
+ ,m_cType('i')
+ ,m_iFlags(flNONE)
+ ,m_pCache(NULL)
+ {}
+
+ //---------------------------------------------------------------------------
+ Value::Value(bool_type a_bVal)
+ :IValue(cmVAL)
+ ,m_val((float_type)a_bVal, 0)
+ ,m_psVal(NULL)
+ ,m_pvVal(NULL)
+ ,m_cType('b')
+ ,m_iFlags(flNONE)
+ ,m_pCache(NULL)
+ {}
+
+ //---------------------------------------------------------------------------
+ Value::Value(string_type a_sVal)
+ :IValue(cmVAL)
+ ,m_val()
+ ,m_psVal(new string_type(a_sVal))
+ ,m_pvVal(NULL)
+ ,m_cType('s')
+ ,m_iFlags(flNONE)
+ ,m_pCache(NULL)
+ {}
+
+ //---------------------------------------------------------------------------
+ Value::Value(int_type array_size, float_type val)
+ :IValue(cmVAL)
+ ,m_val()
+ ,m_psVal(NULL)
+ ,m_pvVal(new array_type(array_size, Value(val)))
+ ,m_cType('a')
+ ,m_iFlags(flNONE)
+ ,m_pCache(NULL)
+ {}
+
+ //---------------------------------------------------------------------------
+ Value::Value(int_type m, int_type n, float_type val)
+ :IValue(cmVAL)
+ ,m_val()
+ ,m_psVal(NULL)
+ ,m_pvVal(NULL)
+ ,m_cType('a')
+ ,m_iFlags(flNONE)
+ ,m_pCache(NULL)
+ {
+/*
+ <ibg 20110808> Neuer Code für zukünftige Matriximplementierung
+ if (m<=0 || n<=0)
+ throw ParserError( ErrorContext(ecAPI_INVALID_DIMENSIONS) );
+
+ m_pVal = new array_type(m*n, Value());
+ for (int_type i=0; i<n; ++i)
+ {
+ (*m_pvVal)[i] = Value(val);
+ }
+*/
+ m_pvVal = new array_type(n, Value());
+ for (int_type i=0; i<n; ++i)
+ {
+ (*m_pvVal)[i] = Value(m, val);
+ }
+ }
+
+ //---------------------------------------------------------------------------
+ Value::Value(const char_type *a_szVal)
+ :IValue(cmVAL)
+ ,m_val()
+ ,m_psVal(new string_type(a_szVal))
+ ,m_pvVal(NULL)
+ ,m_cType('s')
+ ,m_iFlags(flNONE)
+ ,m_pCache(NULL)
+ {}
+
+ //---------------------------------------------------------------------------
+ Value::Value(const cmplx_type &v)
+ :IValue(cmVAL)
+ ,m_val(v)
+ ,m_psVal(NULL)
+ ,m_pvVal(NULL)
+ ,m_cType('c')
+ ,m_iFlags(flNONE)
+ ,m_pCache(NULL)
+ {
+ if ( (m_val.real()==(int_type)m_val.real()) && (m_val.imag()==0) )
+ m_cType = 'i';
+ else
+ m_cType = (m_val.imag()==0) ? 'f' : 'c';
+ }
+
+ //---------------------------------------------------------------------------
+ Value::Value(float_type val)
+ :IValue(cmVAL)
+ ,m_val(val, 0)
+ ,m_psVal(NULL)
+ ,m_pvVal(NULL)
+ ,m_cType((val==(int_type)val) ? 'i' : 'f')
+ ,m_iFlags(flNONE)
+ ,m_pCache(NULL)
+ {}
+
+ //---------------------------------------------------------------------------
+ Value::Value(const array_type &val)
+ :IValue(cmVAL)
+ ,m_val()
+ ,m_psVal(NULL)
+ ,m_pvVal(new array_type(val))
+ ,m_cType('a')
+ ,m_iFlags(flNONE)
+ ,m_pCache(NULL)
+ {}
+
+ //---------------------------------------------------------------------------
+ Value::Value(const Value &a_Val)
+ :IValue(cmVAL)
+ ,m_psVal(NULL)
+ ,m_pvVal(NULL)
+ ,m_pCache(NULL)
+ {
+ Assign(a_Val);
+ }
+
+ //---------------------------------------------------------------------------
+ Value::Value(const IValue &a_Val)
+ :IValue(cmVAL)
+ ,m_psVal(NULL)
+ ,m_pvVal(NULL)
+ ,m_pCache(NULL)
+ {
+ Reset();
+
+ switch(a_Val.GetType())
+ {
+ case 'i':
+ case 'f':
+ case 'b': m_val = cmplx_type(a_Val.GetFloat(), 0);
+ break;
+
+
+ case 'c': m_val = cmplx_type(a_Val.GetFloat(), a_Val.GetImag());
+ break;
+
+ case 's': if (!m_psVal)
+ m_psVal = new string_type(a_Val.GetString());
+ else
+ *m_psVal = a_Val.GetString();
+ break;
+
+ case 'a': if (!m_pvVal)
+ m_pvVal = new array_type(a_Val.GetArray());
+ else
+ *m_pvVal = a_Val.GetArray();
+ break;
+
+ case 'v': break;
+ default: MUP_FAIL(INVALID_TYPE_CODE);
+ }
+
+ m_cType = a_Val.GetType();
+ }
+
+ //---------------------------------------------------------------------------
+ Value& Value::operator=(const Value &a_Val)
+ {
+ Assign(a_Val);
+ return *this;
+ }
+
+ //---------------------------------------------------------------------------
+ IValue& Value::operator[](std::size_t i)
+ {
+ if (m_cType!='a' || m_pvVal==NULL)
+ throw ParserError( ErrorContext(ecAPI_NOT_AN_ARRAY) );
+
+ if (i>=m_pvVal->size())
+ throw ParserError( ErrorContext(ecINDEX_OUT_OF_BOUNDS) );
+
+ return (*m_pvVal)[i];
+ }
+
+ //---------------------------------------------------------------------------
+ Value::~Value()
+ {
+ delete m_psVal;
+ delete m_pvVal;
+ }
+
+ //---------------------------------------------------------------------------
+ IToken* Value::Clone() const
+ {
+ return new Value(*this);
+ }
+
+ //---------------------------------------------------------------------------
+ Value* Value::AsValue()
+ {
+ return this;
+ }
+
+ //---------------------------------------------------------------------------
+ void Value::Assign(const Value &ref)
+ {
+ if (this==&ref)
+ return;
+
+ m_val = ref.m_val;
+
+ // allocate room for a string
+ if (ref.m_psVal)
+ {
+ if (!m_psVal)
+ m_psVal = new string_type(*ref.m_psVal);
+ else
+ *m_psVal = *ref.m_psVal;
+ }
+ else
+ {
+ delete m_psVal;
+ m_psVal = NULL;
+ }
+
+ // allocate room for a vector
+ if (ref.m_pvVal)
+ {
+ if (m_pvVal==NULL)
+ m_pvVal = new array_type(*ref.m_pvVal);
+ else
+ *m_pvVal = *ref.m_pvVal;
+ }
+ else
+ {
+ delete m_pvVal;
+ m_pvVal = NULL;
+ }
+
+ m_cType = ref.m_cType;
+ m_iFlags = ref.m_iFlags;
+
+ // Do not copy the value cache pointer!
+ // Value cache should be assigned expplicitely and
+ // not implicitely (i.e. when retrieving the final result.)
+ //m_pCache = ref.m_pCache;
+ }
+
+ //---------------------------------------------------------------------------
+ void Value::Reset()
+ {
+ m_val = cmplx_type(0,0);
+
+ delete m_psVal;
+ m_psVal = NULL;
+
+ delete m_pvVal;
+ m_pvVal = NULL;
+
+ m_cType = 'f';
+ m_iFlags = flNONE;
+ }
+
+ //---------------------------------------------------------------------------
+ IValue& Value::operator=(bool val)
+ {
+ m_val = cmplx_type((float_type)val,0);
+
+ delete m_psVal;
+ m_psVal = NULL;
+
+ delete m_pvVal;
+ m_pvVal = NULL;
+
+ m_cType = 'b';
+ m_iFlags = flNONE;
+ return *this;
+ }
+
+ //---------------------------------------------------------------------------
+ IValue& Value::operator=(int_type a_iVal)
+ {
+ m_val = cmplx_type(a_iVal,0);
+
+ delete m_psVal;
+ m_psVal = NULL;
+
+ delete m_pvVal;
+ m_pvVal = NULL;
+
+ m_cType = 'i';
+ m_iFlags = flNONE;
+ return *this;
+ }
+
+ //---------------------------------------------------------------------------
+ IValue& Value::operator=(float_type val)
+ {
+ m_val = cmplx_type(val, 0);
+
+ delete m_psVal;
+ m_psVal = NULL;
+
+ delete m_pvVal;
+ m_pvVal = NULL;
+
+ m_cType = (val==(int_type)val) ? 'i' : 'f';
+ m_iFlags = flNONE;
+ return *this;
+ }
+
+ //---------------------------------------------------------------------------
+ IValue& Value::operator=(string_type a_sVal)
+ {
+ m_val = cmplx_type();
+
+ if (!m_psVal)
+ m_psVal = new string_type(a_sVal);
+ else
+ *m_psVal = a_sVal;
+
+ delete m_pvVal;
+ m_pvVal = NULL;
+
+ m_cType = 's';
+ m_iFlags = flNONE;
+ return *this;
+ }
+
+ //---------------------------------------------------------------------------
+ IValue& Value::operator=(const char_type *a_szVal)
+ {
+ m_val = cmplx_type();
+
+ if (!m_psVal)
+ m_psVal = new string_type(a_szVal);
+ else
+ *m_psVal = a_szVal;
+
+ delete m_pvVal;
+ m_pvVal = NULL;
+
+ m_cType = 's';
+ m_iFlags = flNONE;
+ return *this;
+ }
+
+ //---------------------------------------------------------------------------
+ IValue& Value::operator=(const array_type &a_vVal)
+ {
+ m_val = cmplx_type(0,0);
+
+ delete m_psVal;
+ m_psVal = NULL;
+
+ if (m_pvVal==NULL)
+ m_pvVal = new array_type(a_vVal);
+ else
+ *m_pvVal = a_vVal;
+
+ m_cType = 'a';
+ m_iFlags = flNONE;
+
+ return *this;
+ }
+
+ //---------------------------------------------------------------------------
+ IValue& Value::operator=(const cmplx_type &val)
+ {
+ m_val = val;
+
+ delete m_psVal;
+ m_psVal = NULL;
+
+ delete m_pvVal;
+ m_pvVal = NULL;
+
+ m_cType = (m_val.imag()==0) ? ( (m_val.real()==(int)m_val.real()) ? 'i' : 'f' ) : 'c';
+ m_iFlags = flNONE;
+
+ return *this;
+ }
+
+ //---------------------------------------------------------------------------
+ char_type Value::GetType() const
+ {
+ return m_cType;
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Return the value as an integer.
+
+ This function should only be called if you really need an integer value and
+ want to make sure your either get one or throw an exception if the value
+ can not be implicitely converted into an integer.
+ */
+ int_type Value::GetInteger() const
+ {
+ float_type v = m_val.real();
+
+ if (m_cType!='i') //!IsScalar() || (int_type)v-v!=0)
+ {
+ ErrorContext err;
+ err.Errc = ecTYPE_CONFLICT;
+ err.Type1 = m_cType;
+ err.Type2 = 'i';
+
+ if (GetIdent().length())
+ {
+ err.Ident = GetIdent();
+ }
+ else
+ {
+ stringstream_type ss;
+ ss << *this;
+ err.Ident = ss.str();
+ }
+
+ throw ParserError(err);
+ }
+
+ return (int_type)v;
+ }
+
+ //---------------------------------------------------------------------------
+ float_type Value::GetFloat() const
+ {
+/*
+ if (!IsScalar() && m_cType!='b')
+ {
+ ErrorContext err;
+ err.Errc = ecTYPE_CONFLICT;
+ err.Type1 = m_cType;
+ err.Type2 = 'c';
+
+ if (GetIdent().length())
+ {
+ err.Ident = GetIdent();
+ }
+ else
+ {
+ stringstream_type ss;
+ ss << *this;
+ err.Ident = ss.str();
+ }
+
+ throw ParserError(err);
+ }
+*/
+ return m_val.real();
+ }
+
+ //---------------------------------------------------------------------------
+ float_type Value::GetImag() const
+ {
+ if (!IsScalar())
+ {
+ ErrorContext err;
+ err.Errc = ecTYPE_CONFLICT;
+ err.Type1 = m_cType;
+ err.Type2 = 'c';
+
+ if (GetIdent().length())
+ {
+ err.Ident = GetIdent();
+ }
+ else
+ {
+ stringstream_type ss;
+ ss << *this;
+ err.Ident = ss.str();
+ }
+
+ throw ParserError(err);
+ }
+
+ return m_val.imag();
+ }
+
+ //---------------------------------------------------------------------------
+ const cmplx_type& Value::GetComplex() const
+ {
+ return m_val;
+ }
+
+ //---------------------------------------------------------------------------
+ const string_type& Value::GetString() const
+ {
+ CheckType('s');
+ assert(m_psVal!=NULL);
+ return *m_psVal;
+ }
+
+ //---------------------------------------------------------------------------
+ bool Value::GetBool() const
+ {
+ CheckType('b');
+ return m_val.real()==1;
+ }
+
+ //---------------------------------------------------------------------------
+ const array_type& Value::GetArray() const
+ {
+ CheckType('a');
+ assert(m_pvVal!=NULL);
+ return *m_pvVal;
+ }
+
+ //---------------------------------------------------------------------------
+ void Value::CheckType(char_type a_cType) const
+ {
+ if (m_cType!=a_cType)
+ {
+ ErrorContext err;
+ err.Errc = ecTYPE_CONFLICT;
+ err.Type1 = m_cType;
+ err.Type2 = a_cType;
+
+ if (GetIdent().length())
+ {
+ err.Ident = GetIdent();
+ }
+ else
+ {
+ stringstream_type ss;
+ ss << *this;
+ err.Ident = ss.str();
+ }
+
+ throw ParserError(err);
+ }
+ }
+
+ //---------------------------------------------------------------------------
+ bool Value::IsVolatile() const
+ {
+ return IsFlagSet(IValue::flVOLATILE);
+// return true;
+ }
+
+ //---------------------------------------------------------------------------
+ string_type Value::AsciiDump() const
+ {
+ stringstream_type ss;
+
+ ss << g_sCmdCode[ GetCode() ];
+ ss << _T(" [addr=0x") << std::hex << this << std::dec;
+ ss << _T("; type=\"") << GetType() << _T("\"");
+ ss << _T("; val=");
+
+ switch(m_cType)
+ {
+ case 'i': ss << (int_type)m_val.real(); break;
+ case 'f': ss << m_val.real(); break;
+ case 'a': ss << _T("(array)"); break;
+ case 's':
+ assert(m_psVal!=NULL);
+ ss << _T("\"") << m_psVal << _T("\""); break;
+ }
+
+ ss << ((IsFlagSet(IToken::flVOLATILE)) ? _T("; ") : _T("; not ")) << _T("volatile");
+ ss << _T("]");
+
+ return ss.str();
+ }
+
+ //---------------------------------------------------------------------------
+ void Value::Release()
+ {
+ if (m_pCache)
+ m_pCache->ReleaseToCache(this);
+ else
+ delete this;
+ }
+
+ //---------------------------------------------------------------------------
+ void Value::BindToCache(ValueCache *pCache)
+ {
+ m_pCache = pCache;
+ }
+} // namespace mu
diff -r 458e51062300 -r 5a4d909d9533 muparserx/value_test/mpValue.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/value_test/mpValue.h Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,119 @@
+/** \file
+ \brief Definition of basic types used by muParserX
+
+<pre>
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+ </pre>
+*/
+#ifndef MUP_VALUE_H
+#define MUP_VALUE_H
+
+//--- Standard includes ------------------------------------------------------------
+#include <complex>
+#include <list>
+
+//--- Parser framework -------------------------------------------------------------
+#include "mpIValue.h"
+#include "mpTypes.h"
+
+
+MUP_NAMESPACE_START
+
+ //------------------------------------------------------------------------------
+ /** \brief Value class of muParserX
+
+ This class represents a value to be used with muParserX. It's a Variant like
+ class able to store a variety of types.
+ */
+ class Value : public IValue
+ {
+ public:
+
+ explicit Value(char_type cType = 'v');
+ Value(int_type val);
+ Value(bool_type val);
+ Value(float_type val);
+ Value(string_type val);
+ Value(const char_type *val);
+ Value(const cmplx_type &v);
+ Value(const array_type &val);
+
+ // Array constructor
+ Value(int_type m, float_type v);
+
+ // Matrix constructor
+ Value(int_type m, int_type n, float_type v);
+
+ Value(const Value &a_Val );
+ Value(const IValue &a_Val);
+ Value& operator=(const Value &a_Val);
+
+ virtual ~Value();
+
+ virtual IValue& operator[](std::size_t idx);
+ virtual IValue& operator=(int_type a_iVal);
+ virtual IValue& operator=(float_type a_fVal);
+ virtual IValue& operator=(string_type a_sVal);
+ virtual IValue& operator=(bool val);
+ virtual IValue& operator=(const array_type &a_vVal);
+ virtual IValue& operator=(const cmplx_type &val);
+ virtual IValue& operator=(const char_type *a_szVal);
+
+ virtual char_type GetType() const;
+ virtual int_type GetInteger() const;
+ virtual float_type GetFloat() const;
+ virtual float_type GetImag() const;
+ virtual bool GetBool() const;
+ virtual const cmplx_type& GetComplex() const;
+ virtual const string_type& GetString() const;
+ virtual const array_type& GetArray() const;
+
+ virtual bool IsVolatile() const;
+ virtual IToken* Clone() const;
+ virtual Value* AsValue();
+
+ virtual string_type AsciiDump() const;
+ void BindToCache(ValueCache *pCache);
+
+ private:
+
+ cmplx_type m_val; ///< Member variable for storing the value of complex, float, int and boolean values
+ string_type *m_psVal; ///< Variable for storing a string value
+ array_type *m_pvVal; ///< A Vector for storing array variable content
+ char_type m_cType; ///< A byte indicating the type os the represented value
+ EFlags m_iFlags; ///< Additional flags
+ ValueCache *m_pCache; ///< Pointer to the Value Cache
+
+ void CheckType(char_type a_cType) const;
+ void Assign(const Value &a_Val);
+ void Reset();
+
+ virtual void Release();
+ }; // class Value
+
+MUP_NAMESPACE_END
+
+#endif
+
+
diff -r 458e51062300 -r 5a4d909d9533 muparserx/value_test/mpValueCache.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/value_test/mpValueCache.cpp Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,99 @@
+/** \file
+ \brief Definition of a class for caching unused value items and recycling them.
+
+<pre>
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+</pre>
+*/
+#include "mpValueCache.h"
+
+#include "mpValue.h"
+
+
+MUP_NAMESPACE_START
+
+ //------------------------------------------------------------------------------
+ ValueCache::ValueCache(int size)
+ :m_nIdx(-1)
+ ,m_vCache(size, (mup::Value*)0) // hint to myself: don't use NULL gcc will go postal...
+ {}
+
+ //------------------------------------------------------------------------------
+ ValueCache::~ValueCache()
+ {
+ ReleaseAll();
+ }
+
+ //------------------------------------------------------------------------------
+ void ValueCache::ReleaseAll()
+ {
+ for (std::size_t i=0; i<m_vCache.size(); ++i)
+ {
+ delete m_vCache[i];
+ m_vCache[i] = NULL;
+ }
+
+ m_nIdx = -1;
+ }
+
+ //------------------------------------------------------------------------------
+ void ValueCache::ReleaseToCache(Value *pValue)
+ {
+// std::cout << "dbg: " << ct << " ptr: " << this << " void ValueCache::ReleaseToCache(Value *pValue) \n";
+ if (pValue==NULL)
+ return;
+
+ assert(pValue->GetRef()==0);
+
+ // Add the value to the cache if the cache has room for it
+ // otherwise release the value item instantly
+ if ( m_nIdx < ((int)m_vCache.size()-1) )
+ {
+ m_nIdx++;
+ m_vCache[m_nIdx] = pValue;
+ }
+ else
+ delete pValue;
+ }
+
+ //------------------------------------------------------------------------------
+ Value* ValueCache::CreateFromCache()
+ {
+ Value *pValue = NULL;
+ if (m_nIdx>=0)
+ {
+ pValue = m_vCache[m_nIdx];
+ m_vCache[m_nIdx] = NULL;
+ m_nIdx--;
+ }
+ else
+ {
+ pValue = new Value();
+ pValue->BindToCache(this);
+ }
+
+ return pValue;
+ }
+
+MUP_NAMESPACE_END
diff -r 458e51062300 -r 5a4d909d9533 muparserx/value_test/mpValueCache.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/value_test/mpValueCache.h Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,67 @@
+#ifndef MUP_VALUE_CACHE_H
+#define MUP_VALUE_CACHE_H
+
+/** \file
+ \brief Implementation of a cache for recycling unused value items.
+
+<pre>
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+</pre>
+*/
+#include <vector>
+
+#include "mpFwdDecl.h"
+
+
+MUP_NAMESPACE_START
+
+ /** \brief The ValueCache class provides a simple mechanism to recycle
+ unused value items.
+
+ This class serves as a factory for value items. It allows skipping
+ unnecessary and slow new/delete calls by storing unused value
+ objects in an internal buffer for later reuse. By eliminating new/delete
+ calls the parser is sped up approximately by factor 3-4.
+ */
+ class ValueCache
+ {
+ public:
+ ValueCache(int size=10);
+ ~ValueCache();
+
+ void ReleaseAll();
+ void ReleaseToCache(Value *pValue);
+ Value* CreateFromCache();
+
+ private:
+ ValueCache(const ValueCache &ref);
+ ValueCache& operator=(const ValueCache &ref);
+
+ int m_nIdx;
+ std::vector<Value*> m_vCache;
+ };
+
+MUP_NAMESPACE_END
+
+#endif // include guard
\ No newline at end of file
diff -r 458e51062300 -r 5a4d909d9533 muparserx/value_test/mpVariable.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/value_test/mpVariable.cpp Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,267 @@
+/** \file
+ \brief Implementation of the muParserX variable class.
+
+<pre>
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+</pre>
+*/
+#include "mpVariable.h"
+#include "mpError.h"
+
+#include "mpValue.h"
+
+
+MUP_NAMESPACE_START
+
+ //---------------------------------------------------------------------------
+ /** \brief Create a variable and bind a value to it.
+ \param pVal Pointer of the value to bind to this variable.
+
+ It is possible to create an empty variable object by setting pVal to null.
+ Such variable objects must be bound later in order to be of any use.
+ */
+ Variable::Variable(IValue *pVal)
+ :IValue(cmVAR)
+ ,m_pVal(pVal)
+ {
+ AddFlags(IToken::flVOLATILE);
+ }
+
+ //---------------------------------------------------------------------------
+ Variable::Variable(const Variable &obj)
+ :IValue(cmVAR)
+ {
+ Assign(obj);
+ AddFlags(IToken::flVOLATILE);
+ }
+
+ //---------------------------------------------------------------------------
+ Variable& Variable::operator=(const Variable &obj)
+ {
+ Assign(obj);
+ return *this;
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Assign a value to the variable.
+ \param ref Reference to the value to be assigned
+ */
+ IValue& Variable::operator=(const Value &ref)
+ {
+ assert(m_pVal);
+ *m_pVal = ref;
+ return *this;
+ }
+
+ //---------------------------------------------------------------------------
+ IValue& Variable::operator=(int_type val)
+ {
+ assert(m_pVal);
+ return m_pVal->operator=(val);
+ }
+
+ //---------------------------------------------------------------------------
+ IValue& Variable::operator=(float_type val)
+ {
+ assert(m_pVal);
+ return m_pVal->operator=(val);
+ }
+
+ //---------------------------------------------------------------------------
+ IValue& Variable::operator=(string_type val)
+ {
+ assert(m_pVal);
+ return m_pVal->operator=(val);
+ }
+
+ //---------------------------------------------------------------------------
+ IValue& Variable::operator=(bool_type val)
+ {
+ assert(m_pVal);
+ return m_pVal->operator=(val);
+ }
+
+ //---------------------------------------------------------------------------
+ IValue& Variable::operator=(const array_type &val)
+ {
+ assert(m_pVal);
+ return m_pVal->operator=(val);
+ }
+
+ //---------------------------------------------------------------------------
+ IValue& Variable::operator=(const cmplx_type &val)
+ {
+ assert(m_pVal);
+ return m_pVal->operator=(val);
+ }
+
+ //---------------------------------------------------------------------------
+ IValue& Variable::operator[](std::size_t i)
+ {
+ return m_pVal->operator[](i);
+ }
+
+ //---------------------------------------------------------------------------
+ Variable::~Variable()
+ {}
+
+ //---------------------------------------------------------------------------
+ void Variable::Assign(const Variable &ref)
+ {
+ if (this==&ref)
+ return;
+
+ m_pVal = ref.m_pVal;
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Returns a character representing the type of the variable.
+ \throw nothrow
+ */
+ char_type Variable::GetType() const
+ {
+ return (m_pVal) ? m_pVal->GetType() : 'v';
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Returns the Value pointer bound to this variable.
+ \throw nothrow
+ */
+ IValue* Variable::GetPtr() const
+ {
+ return m_pVal;
+ }
+
+ //---------------------------------------------------------------------------
+ int_type Variable::GetInteger() const
+ {
+ return m_pVal->GetInteger();
+ }
+
+ //---------------------------------------------------------------------------
+ float_type Variable::GetFloat() const
+ {
+ return m_pVal->GetFloat();
+ }
+
+ //---------------------------------------------------------------------------
+ float_type Variable::GetImag() const
+ {
+ return m_pVal->GetImag();
+ }
+
+ //---------------------------------------------------------------------------
+ const cmplx_type& Variable::GetComplex() const
+ {
+ return m_pVal->GetComplex();
+ }
+
+ //---------------------------------------------------------------------------
+ const string_type& Variable::GetString() const
+ {
+ return m_pVal->GetString();
+ }
+
+ //---------------------------------------------------------------------------
+ bool Variable::GetBool() const
+ {
+ return m_pVal->GetBool();
+ }
+
+ //---------------------------------------------------------------------------
+ const array_type& Variable::GetArray() const
+ {
+ return m_pVal->GetArray();
+ }
+
+ //---------------------------------------------------------------------------
+ void Variable::SetFloat(float_type a_fVal)
+ {
+ assert(m_pVal);
+ *m_pVal = a_fVal;
+ }
+
+ //---------------------------------------------------------------------------
+ void Variable::SetString(const string_type &a_sVal)
+ {
+ assert(m_pVal);
+ *m_pVal = a_sVal;
+ }
+
+ //---------------------------------------------------------------------------
+ void Variable::SetBool(bool a_bVal)
+ {
+ assert(m_pVal);
+ *m_pVal = a_bVal;
+ }
+
+ //---------------------------------------------------------------------------
+ void Variable::Bind(IValue *pValue)
+ {
+ m_pVal = pValue;
+ }
+
+ //---------------------------------------------------------------------------
+ bool Variable::IsVolatile() const
+ {
+ return true;
+ }
+
+ //---------------------------------------------------------------------------
+ IToken* Variable::Clone() const
+ {
+ return new Variable(*this);
+ }
+
+ //---------------------------------------------------------------------------
+ Value* Variable::AsValue()
+ {
+ return NULL;
+ }
+
+ //---------------------------------------------------------------------------
+ string_type Variable::AsciiDump() const
+ {
+ stringstream_type ss;
+
+ ss << g_sCmdCode[ GetCode() ];
+ ss << _T(" [addr=0x") << std::hex << this << std::dec;
+ ss << _T("; id=\"") << GetIdent() << _T("\"");
+ ss << _T("; type=\"") << GetType() << _T("\"");
+ ss << _T("; val=");
+
+ switch(GetType())
+ {
+ case 'i': ss << (int_type)GetFloat(); break;
+ case 'f': ss << GetFloat(); break;
+ case 'a': ss << _T("(array)"); break;
+ case 's': ss << _T("\"") << GetString() << _T("\""); break;
+ }
+
+ ss << ((IsFlagSet(IToken::flVOLATILE)) ? _T("; ") : _T("; not ")) << _T("volatile");
+ ss << _T("]");
+
+ return ss.str();
+ }
+MUP_NAMESPACE_END
diff -r 458e51062300 -r 5a4d909d9533 muparserx/value_test/mpVariable.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/value_test/mpVariable.h Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,101 @@
+/** \file
+ \brief Definition of the muParserX variable class.
+
+<pre>
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+</pre>
+*/
+
+#ifndef MP_VARIABLE_H
+#define MP_VARIABLE_H
+
+#include "mpIValue.h"
+#include "mpTypes.h"
+
+
+MUP_NAMESPACE_START
+
+ //------------------------------------------------------------------------------
+ /** \brief The variable class represents a parser variable.
+
+ This class stores a pointer to a value object and refers all
+ operations to this value object.
+ */
+ class Variable : public IValue
+ {
+ public:
+
+ Variable(IValue *pVal);
+
+ Variable(const Variable &a_Var);
+ Variable& operator=(const Variable &a_Var);
+
+ virtual IValue& operator[](std::size_t idx);
+ virtual IValue& operator=(const Value &val);
+ virtual IValue& operator=(const array_type &val);
+ virtual IValue& operator=(const cmplx_type &val);
+ virtual IValue& operator=(int_type val);
+ virtual IValue& operator=(float_type val);
+ virtual IValue& operator=(string_type val);
+ virtual IValue& operator=(bool_type val);
+
+ virtual ~Variable();
+
+ virtual char_type GetType() const;
+
+ virtual int_type GetInteger() const;
+ virtual float_type GetFloat() const;
+ virtual float_type GetImag() const;
+ virtual bool GetBool() const;
+ virtual const cmplx_type& GetComplex() const;
+ virtual const string_type& GetString() const;
+ virtual const array_type& GetArray() const;
+
+ virtual bool IsVolatile() const;
+ virtual IToken* Clone() const;
+ virtual Value* AsValue();
+
+ //void Set(Value &val);
+ void SetFloat(float_type a_fVal);
+ void SetString(const string_type &a_sVal);
+ void SetBool(bool a_bVal);
+
+ void Bind(IValue *pValue);
+
+ IValue* GetPtr() const;
+ string_type AsciiDump() const;
+
+ private:
+
+ IValue *m_pVal; ///< Pointer to the value object bound to this variable
+
+ void Assign(const Variable &a_Var);
+ void CheckType(char_type a_cType) const;
+ }; // class Variable
+
+MUP_NAMESPACE_END
+
+#endif
+
+
diff -r 458e51062300 -r 5a4d909d9533 muparserx/value_test/muMatrix.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/value_test/muMatrix.h Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,397 @@
+#ifndef MU_MATRIX_H
+#define MU_MATRIX_H
+
+#include <vector>
+#include <cassert>
+#include <iostream>
+#include <stdexcept>
+#include <sstream>
+#include <initializer_list>
+#include "muMatrixError.h"
+
+
+namespace mu
+{
+ //-----------------------------------------------------------------------------------------------
+ template<typename T>
+ class Matrix
+ {
+ template<typename T>
+ friend Matrix<T> operator+(const Matrix<T>& lhs, const Matrix<T>& rhs);
+
+ template<typename T>
+ friend Matrix<T> operator-(const Matrix<T>& lhs, const Matrix<T>& rhs);
+
+ public:
+
+ //---------------------------------------------------------------------------------------------
+ enum EMatrixStorageScheme
+ {
+ mssROWS_FIRST,
+ mssCOLS_FIRST
+ };
+
+ //---------------------------------------------------------------------------------------------
+ Matrix()
+ :m_nRows(1)
+ ,m_nCols(1)
+ ,m_eStorageScheme(mssROWS_FIRST)
+ ,m_vData(1)
+ {}
+
+ //---------------------------------------------------------------------------------------------
+ explicit Matrix(int nRows)
+ :m_nRows(nRows)
+ ,m_nCols(1)
+ ,m_eStorageScheme(mssROWS_FIRST)
+ ,m_vData(m_nRows)
+ {}
+
+ //---------------------------------------------------------------------------------------------
+ /* Constructs a Matrix object representing a scalar value
+ */
+ Matrix(const T &v)
+ :m_nRows(1)
+ ,m_nCols(1)
+ ,m_eStorageScheme(mssROWS_FIRST)
+ ,m_vData(1, v)
+ {}
+
+ //---------------------------------------------------------------------------------------------
+ /* \brief Constructs a Matrix object representing a vector
+ */
+ Matrix(const std::vector<T> &v)
+ :m_nRows(v.size())
+ ,m_nCols(1)
+ ,m_eStorageScheme(mssROWS_FIRST)
+ ,m_vData(v)
+ {}
+
+ //---------------------------------------------------------------------------------------------
+ /* Constructs a Matrix object representing a vector
+ */
+ template<size_t TSize>
+ Matrix(T (&v)[TSize])
+ :m_nRows(TSize)
+ ,m_nCols(1)
+ ,m_eStorageScheme(mssROWS_FIRST)
+ ,m_vData(v, v + TSize)
+ {}
+
+ //---------------------------------------------------------------------------------------------
+ template<size_t TRows, size_t TCols>
+ Matrix(T (&v)[TRows][TCols])
+ :m_nRows(TRows)
+ ,m_nCols(TCols)
+ ,m_eStorageScheme(mssROWS_FIRST)
+ ,m_vData(TRows*TCols, 0)
+ {
+ for (int m=0; m<TRows; ++m)
+ {
+ for (int n=0; n<TCols; ++n)
+ {
+ At(m,n) = v[m][n];
+ }
+ }
+ }
+
+ //---------------------------------------------------------------------------------------------
+ Matrix(int nRows, int nCols)
+ :m_nRows(nRows)
+ ,m_nCols(nCols)
+ ,m_eStorageScheme(mssROWS_FIRST)
+ ,m_vData(m_nRows*m_nCols)
+ {}
+
+ //---------------------------------------------------------------------------------------------
+ Matrix(const Matrix &ref)
+ {
+ Assign(ref);
+ }
+
+ //---------------------------------------------------------------------------------------------
+ Matrix& operator=(const Matrix &ref)
+ {
+ if (this!=&ref)
+ Assign(ref);
+
+ return *this;
+ }
+
+ //---------------------------------------------------------------------------------------------
+ Matrix& operator=(const T &v)
+ {
+ m_nCols = 1;
+ m_nRows = 1;
+ m_eStorageScheme = mssROWS_FIRST;
+ m_vData.assign(1, v);
+ return *this;
+ }
+
+ //---------------------------------------------------------------------------------------------
+ Matrix& operator+=(const Matrix &lhs)
+ {
+ if (m_nRows!=lhs.m_nRows || m_nCols!=lhs.m_nCols)
+ throw MatrixError("Matrix dimension mismatch");
+
+ for (int i=0; i<m_nRows; ++i)
+ {
+ for (int j=0; j<m_nCols; ++j)
+ {
+ At(i,j) += lhs.At(i,j);
+ }
+ }
+
+ return *this;
+ }
+
+ //---------------------------------------------------------------------------------------------
+ Matrix& operator-=(const Matrix &lhs)
+ {
+ if (m_nRows!=lhs.m_nRows || m_nCols!=lhs.m_nCols)
+ throw MatrixError("Matrix dimension mismatch");
+
+ for (int i=0; i<m_nRows; ++i)
+ {
+ for (int j=0; j<m_nCols; ++j)
+ {
+ At(i,j) -= lhs.At(i,j);
+ }
+ }
+
+ return *this;
+ }
+
+ //---------------------------------------------------------------------------------------------
+ Matrix& operator*=(const Matrix &rhs)
+ {
+ // Matrix x Matrix multiplication
+ if (rhs.GetDim()==0)
+ {
+ T v = rhs.At(0,0);
+ for (int m=0; m<m_nRows; ++m)
+ {
+ for (int n=0; n<m_nCols; ++n)
+ {
+ At(m, n) *= v;
+ }
+ }
+ }
+ else if (GetDim()==0)
+ {
+ T v = At(0,0);
+ Assign(rhs);
+ for (int m=0; m<m_nRows; ++m)
+ {
+ for (int n=0; n<m_nCols; ++n)
+ {
+ At(m, n) *= v;
+ }
+ }
+ }
+ else if (m_nCols==rhs.m_nRows)
+ {
+ Matrix<T> out(m_nRows, rhs.m_nCols);
+
+ // For each cell in the output matrix
+ for (int m=0; m<m_nRows; ++m)
+ {
+ for (int n=0; n<rhs.m_nCols; ++n)
+ {
+ T buf = 0;
+ for (int i=0; i<m_nCols; ++i)
+ {
+ buf += At(m, i) * rhs.At(i, n);
+ }
+ out.At(m,n) = buf;
+ } // for all rows
+ } // for all columns
+
+ Assign(out);
+ }
+ else
+ throw MatrixError("Matrix dimensions don't allow multiplication");
+
+ return *this;
+ }
+
+ //---------------------------------------------------------------------------------------------
+ void AsciiDump(const char *szTitle) const
+ {
+ using namespace std;
+
+ cout << szTitle << "\n";
+ cout << "------------------\n";
+ cout << "Cols: " << m_nCols << "\n";
+ cout << "Rows: " << m_nRows << "\n";
+ cout << "Dim: " << GetDim() << "\n";
+
+ for (int i=0; i<m_nRows; ++i)
+ {
+ for (int j=0; j<m_nCols; ++j)
+ {
+ cout << At(i, j) << " ";
+ }
+ cout << "\n";
+ }
+
+ cout << "\n\n";
+ }
+
+ //---------------------------------------------------------------------------------------------
+ std::string ToString() const
+ {
+ std::stringstream ss;
+ for (int i=0; i<m_nRows; ++i)
+ {
+ for (int j=0; j<m_nCols; ++j)
+ {
+ ss << At(i, j) << " ";
+ }
+ ss << "\n";
+ }
+
+ return ss.str();
+ }
+
+ //---------------------------------------------------------------------------------------------
+ ~Matrix()
+ {
+ m_vData.clear();
+ }
+
+ //---------------------------------------------------------------------------------------------
+ int GetRows() const
+ {
+ return m_nRows;
+ }
+
+ //---------------------------------------------------------------------------------------------
+ int GetCols() const
+ {
+ return m_nCols;
+ }
+
+ //---------------------------------------------------------------------------------------------
+ int GetDim() const
+ {
+ if (m_nCols==1)
+ {
+ return (m_nRows==1) ? 0 : 1;
+ }
+ else
+ return 2;
+ }
+
+ //---------------------------------------------------------------------------------------------
+ T& At(int nRow, int nCol = 0)
+ {
+ int i;
+ if (m_eStorageScheme==mssROWS_FIRST)
+ {
+ i = nRow * m_nCols + nCol;
+ }
+ else
+ {
+ i = nCol * m_nRows + nRow;
+ }
+
+ assert(i<(int)m_vData.size());
+ return m_vData[i];
+ }
+
+ //---------------------------------------------------------------------------------------------
+ const T& At(int nRow, int nCol = 0) const
+ {
+ int i;
+ if (m_eStorageScheme==mssROWS_FIRST)
+ {
+ i = nRow * m_nCols + nCol;
+ }
+ else
+ {
+ i = nCol * m_nRows + nRow;
+ }
+
+ assert(i<(int)m_vData.size());
+ return m_vData[i];
+ }
+
+ //---------------------------------------------------------------------------------------------
+ const T* GetData() const
+ {
+ assert(m_vData.size());
+ return &m_vData[0];
+ }
+
+ //---------------------------------------------------------------------------------------------
+ void SetStorageScheme(EMatrixStorageScheme eSheme)
+ {
+ m_eStorageScheme = eScheme;
+ }
+
+ //---------------------------------------------------------------------------------------------
+ EMatrixStorageScheme GetStorageScheme() const
+ {
+ return m_eScheme;
+ }
+
+ //---------------------------------------------------------------------------------------------
+ Matrix<T>& Transpose()
+ {
+ if (GetDim()==0)
+ return *this;
+
+ m_eStorageScheme = (m_eStorageScheme==mssROWS_FIRST) ? mssCOLS_FIRST : mssROWS_FIRST;
+ m_nRows ^= m_nCols ^= m_nRows ^= m_nCols;
+
+ return *this;
+ }
+
+ //---------------------------------------------------------------------------------------------
+ void Fill(const T &v)
+ {
+ m_vData.assign(m_vData.size(), v);
+ }
+
+ private:
+ int m_nCols;
+ int m_nRows;
+ std::vector<T> m_vData;
+
+ EMatrixStorageScheme m_eStorageScheme;
+
+ //---------------------------------------------------------------------------------------------
+ void Assign(const Matrix &ref)
+ {
+ m_nCols = ref.m_nCols;
+ m_nRows = ref.m_nRows;
+ m_eStorageScheme = ref.m_eStorageScheme;
+ m_vData = ref.m_vData;
+ }
+ };
+
+
+ //---------------------------------------------------------------------------------------------
+ template<typename T>
+ Matrix<T> operator*(const Matrix<T>& lhs, const Matrix<T>& rhs)
+ {
+ return Matrix<T>(lhs) *= rhs;
+ }
+
+ //---------------------------------------------------------------------------------------------
+ template<typename T>
+ Matrix<T> operator+(const Matrix<T>& lhs, const Matrix<T>& rhs)
+ {
+ return Matrix<T>(lhs) += rhs;
+ }
+
+ //---------------------------------------------------------------------------------------------
+ template<typename T>
+ Matrix<T> operator-(const Matrix<T>& lhs, const Matrix<T>& rhs)
+ {
+ return Matrix<T>(lhs) -= rhs;
+ }
+} // namespace mu
+
+#endif
\ No newline at end of file
diff -r 458e51062300 -r 5a4d909d9533 muparserx/value_test/muMatrixError.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/value_test/muMatrixError.h Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,18 @@
+#ifndef MU_MATRIX_ERROR_H
+#define MU_MATRIX_ERROR_H
+
+#include <stdexcept>
+#include <string>
+
+namespace mu
+{
+ class MatrixError : public std::runtime_error
+ {
+ public:
+ explicit MatrixError(const std::string &sMsg)
+ :std::runtime_error(sMsg)
+ {}
+ };
+}
+
+#endif
\ No newline at end of file
diff -r 458e51062300 -r 5a4d909d9533 muparserx/value_test/muMatrixTest.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/value_test/muMatrixTest.cpp Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,253 @@
+#include "muMatrixTest.h"
+
+using namespace std;
+
+
+namespace mu
+{
+ //-----------------------------------------------------------------------------------------------
+ MatrixTest::MatrixTest()
+ :m_nTests(0)
+ ,m_vTests()
+ {
+
+#if defined(_UNICODE)
+ m_stream = &std::wcout;
+#else
+ m_stream = &std::cout;
+#endif
+
+ AddTest(&MatrixTest::TestInitialization);
+ AddTest(&MatrixTest::TestAddSub);
+ AddTest(&MatrixTest::TestMul);
+ }
+
+ //-----------------------------------------------------------------------------------------------
+ void MatrixTest::AddTest(MatrixTest::testfun_type a_pFun)
+ {
+ m_vTests.push_back(a_pFun);
+ }
+
+ //-----------------------------------------------------------------------------------------------
+ int MatrixTest::TestInitialization()
+ {
+ int nFail = 0;
+
+ *m_stream << "testing matrix initialization...";
+
+ // Array initialization
+ double ref_v3[] = { 1.0, 2.0, 3.0};
+
+ // 1.1) Create empty array,initialize cell by cell afterwards
+ Matrix<double> v1(3);
+ v1.At(0) = ref_v3[0];
+ v1.At(1) = ref_v3[1];
+ v1.At(2) = ref_v3[2];
+
+ // Create a reference matrix
+ double ref[3][3] = { {1,2,3},
+ {4,5,6},
+ {7,8,9} };
+
+ // 1.) Construct empty matrix, fill afterwards cell by cell
+ Matrix<double> m1(3,3);
+ m1.At(0,0) = ref[0][0]; m1.At(0,1) = ref[0][1]; m1.At(0,2) = ref[0][2];
+ m1.At(1,0) = ref[1][0]; m1.At(1,1) = ref[1][1]; m1.At(1,2) = ref[1][2];
+ m1.At(2,0) = ref[2][0]; m1.At(2,1) = ref[2][1]; m1.At(2,2) = ref[2][2];
+
+ // 2.) Construct matrix from multidimensional array
+ Matrix<double> m2(ref);
+
+
+ if (nFail==0)
+ *m_stream << "passed" << endl;
+ else
+ *m_stream << "\n failed with " << nFail << " errors" << endl;
+
+ return nFail;
+ }
+
+ //-----------------------------------------------------------------------------------------------
+ int MatrixTest::TestAddSub()
+ {
+ int nFail = 0;
+
+ *m_stream << "testing addition and subtraction...";
+
+ Matrix<double> a,b,c,d;
+ a = 1;
+ b = 2;
+ c = 3;
+ d = 6;
+
+ Matrix<double> va3(3,3), vb3(3,3), vc3(3,3), vd3(3,3), m44(4,4), m34(3,4), m43(4,3);
+
+ va3.At(0,0) = 1; va3.At(0,1) = 2; va3.At(0,2) = 3;
+ va3.At(1,0) = 4; va3.At(1,1) = 5; va3.At(1,2) = 6;
+ va3.At(2,0) = 7; va3.At(2,1) = 8; va3.At(2,2) = 9;
+
+ vb3.At(0,0) = 9; vb3.At(0,1) = 8; vb3.At(0,2) = 7;
+ vb3.At(1,0) = 6; vb3.At(1,1) = 5; vb3.At(1,2) = 4;
+ vb3.At(2,0) = 3; vb3.At(2,1) = 2; vb3.At(2,2) = 1;
+
+ vc3.Fill(10);
+ vd3.Fill(0);
+
+ // Addition von Skalaren
+ nFail += Eval(a+b, c);
+ nFail += Eval(b+a, c);
+ nFail += Eval(a+b+c, d);
+ nFail += Eval(c-b, a);
+ nFail += Eval(d-c, c);
+
+#define THROWTEST(EXPR) \
+ { \
+ m_nTests++; \
+ try \
+ { \
+ EXPR; \
+ nFail++; \
+ } \
+ catch(...) \
+ { \
+ } \
+ }
+
+ // Addition von Matrizen mit nicht passenden Zeilen/Spaltenzahl
+ THROWTEST(a+va3);
+ THROWTEST(va3+a);
+ THROWTEST(a+va3);
+ THROWTEST(va3+a);
+ THROWTEST(va3+m44);
+ THROWTEST(va3+m34);
+ THROWTEST(va3+m43);
+ THROWTEST(m44+va3);
+ THROWTEST(m34+va3);
+ THROWTEST(m43+va3);
+
+ THROWTEST(a-va3);
+ THROWTEST(va3-a);
+ THROWTEST(a-va3);
+ THROWTEST(va3-a);
+ THROWTEST(va3-m44);
+ THROWTEST(va3-m34);
+ THROWTEST(va3-m43);
+ THROWTEST(m44-va3);
+ THROWTEST(m34-va3);
+ THROWTEST(m43-va3);
+
+ // Addition von Matrizen
+ nFail += Eval(va3+vb3, vc3);
+ nFail += Eval(vb3+va3, vc3);
+ nFail += Eval(vc3-vb3, va3);
+ nFail += Eval(vc3-va3, vb3);
+
+ if (nFail==0)
+ *m_stream << "passed" << endl;
+ else
+ *m_stream << "\n failed with " << nFail << " errors" << endl;
+
+ return nFail;
+ }
+
+
+ //-----------------------------------------------------------------------------------------------
+ int MatrixTest::TestMul()
+ {
+ int nFail = 0;
+ *m_stream << "testing multiplication...";
+
+ Matrix<double> a,b,c,d;
+ a = 1;
+ b = 2;
+ c = 3;
+ d = 6;
+
+ // Try assigning from array
+ double buf[]= { 1,2,3 };
+ Matrix<double> va3 = buf;
+
+ // Manual assignment
+ Matrix<double> vb3(3), vc3(3), vd3(3);
+ vb3.At(0) = 4, vc3.At(0) = 3, vd3.At(0) = 12;
+ vb3.At(1) = 5, vc3.At(1) = 4, vd3.At(1) = 15;
+ vb3.At(2) = 6, vc3.At(2) = 3, vd3.At(2) = 18;
+
+ // Skalarprodukt
+ THROWTEST(va3*vb3);
+ THROWTEST(vb3*va3);
+
+ double res1[3][3] = { { 4, 5, 6},
+ { 8, 10, 12},
+ {12, 15, 18} };
+ nFail += Eval(va3 * Matrix<double>(vb3).Transpose(), res1);
+ nFail += Eval(Matrix<double>(vb3).Transpose() * va3, 32);
+
+ double res2[3][3] = { { 4, 8, 12},
+ { 5, 10, 15},
+ { 6, 12, 18} };
+ nFail += Eval(vb3 * Matrix<double>(va3).Transpose(), res2);
+
+ double ma[2][3] = { {1, 2, 3},
+ {4, 5, 6} };
+ double mb[3][2] = { {6, -1},
+ {3, 2},
+ {0, -3}};
+ double res3[2][2] = { {12, -6},
+ {39, -12} };
+ nFail += Eval(Matrix<double>(ma)*Matrix<double>(mb), res3);
+
+ // Skalar-Vektor Multiplikatione
+ nFail += Eval(c*vb3, vd3);
+ nFail += Eval(vb3*c, vd3);
+
+ // gemischte Multiplikation
+ double res4[3][3] = { {12*3, 15*3, 18*3},
+ {16*3, 20*3, 24*3},
+ {12*3, 15*3, 18*3} };
+ nFail += Eval(c*vc3*Matrix<double>(vb3).Transpose(), res4);
+ nFail += Eval(vc3*c*Matrix<double>(vb3).Transpose(), res4);
+ nFail += Eval(vc3*Matrix<double>(vb3).Transpose()*c, res4);
+
+ if (nFail==0)
+ *m_stream << "passed" << endl;
+ else
+ *m_stream << "\n failed with " << nFail << " errors" << endl;
+
+ return nFail;
+ }
+
+ //-----------------------------------------------------------------------------------------------
+ void MatrixTest::Run()
+ {
+ int nFail = 0;
+ try
+ {
+ for (int i=0; i<(int)m_vTests.size(); ++i)
+ nFail += (this->*m_vTests[i])();
+
+ if (nFail==0)
+ {
+ *m_stream << _T("Test passed (") << m_nTests << _T(" distinct test)") << endl;
+ }
+ else
+ {
+ *m_stream << _T("Test failed with ") << nFail
+ << _T(" errors (") << m_nTests
+ << _T(" expressions)") << endl;
+ }
+ }
+ catch(std::exception &e)
+ {
+ *m_stream << _T("\nTest failed (unexpected exception):\n");
+ *m_stream << e.what() << endl;
+ }
+ catch(...)
+ {
+ *m_stream << _T("\nTest failed (unexpected exception):\n");
+ *m_stream << _T("Internal error");
+ }
+
+ m_nTests = 0;
+ }
+}
\ No newline at end of file
diff -r 458e51062300 -r 5a4d909d9533 muparserx/value_test/muMatrixTest.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/value_test/muMatrixTest.h Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,78 @@
+#ifndef MU_MATRIX_TEST_H
+#define MU_MATRIX_TEST_H
+
+#include <vector>
+#include <string>
+#include <iostream>
+
+#include "muMatrix.h"
+
+#ifndef _T
+#define _T
+#endif
+
+namespace mu
+{
+ class MatrixTest
+ {
+ public:
+ MatrixTest();
+
+ void Run();
+
+ private:
+ typedef int (MatrixTest::*testfun_type)();
+
+ int m_nTests;
+ std::vector<testfun_type> m_vTests;
+
+#if defined(_UNICODE)
+ std::wostream *m_stream;
+#else
+ std::ostream *m_stream;
+#endif
+
+ int TestInitialization();
+ int TestAddSub();
+ int TestMul();
+
+ void AddTest(testfun_type pFun);
+
+ int Eval(const Matrix<double> &m1, const Matrix<double> &m2)
+ {
+ m_nTests++;
+ int nFail = 0;
+ try
+ {
+ if (m1.GetDim()!=m2.GetDim())
+ throw MatrixError("invalid Matrix dimentsion");
+
+ if (m1.GetRows()!=m2.GetRows())
+ throw MatrixError("invalid Matrix rows");
+
+ if (m1.GetCols()!=m2.GetCols())
+ throw MatrixError("invalid Matrix rows");
+
+ for (int i=0; i<m1.GetRows(); ++i)
+ {
+ for (int j=0; j<m1.GetCols(); ++j)
+ {
+ if (m1.At(i,j)!=m2.At(i,j))
+ throw MatrixError("invalid Matrix value");
+ }
+ }
+
+ nFail = 0;
+ }
+ catch(...)
+ {
+ *m_stream << "\nincorrect result:\n" << m1.ToString() << "\nexpected:\n" << m2.ToString() << "\n";
+ nFail = 1;
+ }
+
+ return nFail;
+ }
+ };
+}
+
+#endif
\ No newline at end of file
diff -r 458e51062300 -r 5a4d909d9533 muparserx/value_test/resource.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/value_test/resource.h Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,3 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by app.rc
diff -r 458e51062300 -r 5a4d909d9533 muparserx/value_test/stdafx.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/value_test/stdafx.cpp Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,7 @@
+// stdafx.cpp : source file that includes just the standard includes
+// value_test.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
+
diff -r 458e51062300 -r 5a4d909d9533 muparserx/value_test/stdafx.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/value_test/stdafx.h Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,8 @@
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently, but
+// are changed infrequently
+//
+
+#pragma once
+
+// TODO: reference additional headers your program requires here
diff -r 458e51062300 -r 5a4d909d9533 muparserx/value_test/suSortPred.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/value_test/suSortPred.h Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,58 @@
+/*
+ __________ ____ ___
+ _____ __ _\______ \_____ _______ ______ __________\ \/ /
+ / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
+ | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
+ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
+ \/ \/ \/ \/ \_/
+
+ muParserX - A C++ math parser library with array and string support
+ Copyright 2010 Ingo Berg
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see http://www.gnu.org/licenses.
+*/
+#ifndef SU_PRED_H
+#define SU_PRED_H
+
+#include <functional>
+
+
+/** \brief Namespace containing utility functions and classes for string processing. */
+namespace su
+{
+ namespace pred
+ {
+ /** \brief Sort two strings based on their length.
+ */
+ template<class TString>
+ struct SortByLength
+ :public std::binary_function<TString, TString, bool>
+ {
+ bool operator()(const TString& a_sLeft, const TString& a_sRight) const
+ {
+ if (a_sLeft.length() == a_sRight.length())
+ {
+ return a_sLeft < a_sRight;
+ }
+ else
+ {
+ return a_sLeft.length() < a_sRight.length();
+ }
+ }
+ };
+ } // namespace pred
+} // end of namespace
+
+
+#endif
diff -r 458e51062300 -r 5a4d909d9533 muparserx/value_test/value_test.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/value_test/value_test.cpp Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,54 @@
+// value_test.cpp : main project file.
+
+#include "stdafx.h"
+#include <string>
+
+#include "mpDefines.h"
+#include "mpTypes.h"
+#include "mpValue.h"
+
+//--- MathUtils -----------------------------------------------------------------------------------
+#include "muMatrix.h"
+#include "muMatrixTest.h"
+
+
+MUP_NAMESPACE_START
+ //-----------------------------------------------------------------------------------------------
+ const char_type *g_sCmdCode[] = { _T("BRCK. OPEN "),
+ _T("BRCK. CLOSE "),
+ _T("IDX OPEN "),
+ _T("IDX CLOSE "),
+ _T("ARG_SEP "),
+ _T("IF "),
+ _T("ELSE "),
+ _T("ENDIF "),
+ _T("JMP "),
+ _T("VAR "),
+ _T("VAL "),
+ _T("FUNC "),
+ _T("OPRT_BIN "),
+ _T("OPRT_IFX "),
+ _T("OPRT_PFX "),
+ _T("END "),
+ _T("SCRIPT_GOTO "),
+ _T("SCRIPT_LABEL "),
+ _T("SCRIPT_FOR "),
+ _T("SCRIPT_IF "),
+ _T("SCRIPT_ELSE "),
+ _T("SCRIPT_ELSEIF "),
+ _T("SCRIPT_ENDIF "),
+ _T("SCRIPT_NEWLINE "),
+ _T("SCRIPT_FUNCTION"),
+ _T("UNKNOWN ") };
+MUP_NAMESPACE_END
+
+using namespace mup;
+using namespace mu;
+
+int main(int /* argc */, char ** /*argv*/)
+{
+ MatrixTest mt;
+ mt.Run();
+
+ return 0;
+}
diff -r 458e51062300 -r 5a4d909d9533 muparserx/value_test/value_test.sln
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/value_test/value_test.sln Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "value_test", "value_test.vcxproj", "{F2291F6C-D078-44F7-B0A5-AD200C348D23}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {F2291F6C-D078-44F7-B0A5-AD200C348D23}.Debug|Win32.ActiveCfg = Debug|Win32
+ {F2291F6C-D078-44F7-B0A5-AD200C348D23}.Debug|Win32.Build.0 = Debug|Win32
+ {F2291F6C-D078-44F7-B0A5-AD200C348D23}.Release|Win32.ActiveCfg = Release|Win32
+ {F2291F6C-D078-44F7-B0A5-AD200C348D23}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff -r 458e51062300 -r 5a4d909d9533 muparserx/value_test/value_test.sln.old
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/value_test/value_test.sln.old Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "value_test", "value_test.vcproj", "{F2291F6C-D078-44F7-B0A5-AD200C348D23}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {F2291F6C-D078-44F7-B0A5-AD200C348D23}.Debug|Win32.ActiveCfg = Debug|Win32
+ {F2291F6C-D078-44F7-B0A5-AD200C348D23}.Debug|Win32.Build.0 = Debug|Win32
+ {F2291F6C-D078-44F7-B0A5-AD200C348D23}.Release|Win32.ActiveCfg = Release|Win32
+ {F2291F6C-D078-44F7-B0A5-AD200C348D23}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff -r 458e51062300 -r 5a4d909d9533 muparserx/value_test/value_test.suo.old
Binary file muparserx/value_test/value_test.suo.old has changed
diff -r 458e51062300 -r 5a4d909d9533 muparserx/value_test/value_test.vcproj
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/value_test/value_test.vcproj Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,316 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9,00"
+ Name="value_test"
+ ProjectGUID="{F2291F6C-D078-44F7-B0A5-AD200C348D23}"
+ RootNamespace="value_test"
+ Keyword="ManagedCProj"
+ TargetFrameworkVersion="196613"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="0"
+ ManagedExtensions="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32;_DEBUG"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="4"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="$(NoInherit)"
+ LinkIncremental="2"
+ GenerateDebugInformation="true"
+ AssemblyDebug="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ ManagedExtensions="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="WIN32;NDEBUG"
+ RuntimeLibrary="2"
+ UsePrecompiledHeader="2"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="$(NoInherit)"
+ LinkIncremental="1"
+ GenerateDebugInformation="true"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ <AssemblyReference
+ RelativePath="System.dll"
+ AssemblyName="System, Version=2.0.0.0, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL"
+ MinFrameworkVersion="131072"
+ />
+ <AssemblyReference
+ RelativePath="System.Data.dll"
+ AssemblyName="System.Data, Version=2.0.0.0, PublicKeyToken=b77a5c561934e089, processorArchitecture=x86"
+ MinFrameworkVersion="131072"
+ />
+ <AssemblyReference
+ RelativePath="System.XML.dll"
+ AssemblyName="System.Xml, Version=2.0.0.0, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL"
+ MinFrameworkVersion="131072"
+ />
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\mpError.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\mpError.h"
+ >
+ </File>
+ <File
+ RelativePath=".\mpIToken.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\mpIToken.h"
+ >
+ </File>
+ <File
+ RelativePath=".\mpIValReader.h"
+ >
+ </File>
+ <File
+ RelativePath=".\mpIValue.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\mpIValue.h"
+ >
+ </File>
+ <File
+ RelativePath=".\mpTypes.h"
+ >
+ </File>
+ <File
+ RelativePath=".\mpValue.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\mpValue.h"
+ >
+ </File>
+ <File
+ RelativePath=".\mpValueCache.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\mpVariable.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\mpVariable.h"
+ >
+ </File>
+ <File
+ RelativePath=".\stdafx.cpp"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\value_test.cpp"
+ >
+ </File>
+ <Filter
+ Name="muMatrix"
+ >
+ <File
+ RelativePath=".\muMatrix.h"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\muMatrixError.h"
+ >
+ </File>
+ <File
+ RelativePath=".\muMatrixTest.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\muMatrixTest.h"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\resource.h"
+ >
+ </File>
+ <File
+ RelativePath=".\stdafx.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ <File
+ RelativePath=".\app.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\app.rc"
+ >
+ </File>
+ </Filter>
+ <File
+ RelativePath=".\ReadMe.txt"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff -r 458e51062300 -r 5a4d909d9533 muparserx/value_test/value_test.vcproj.NB1.user.user
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/value_test/value_test.vcproj.NB1.user.user Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioUserFile
+ ProjectType="Visual C++"
+ Version="9,00"
+ ShowAllFiles="false"
+ >
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ >
+ <DebugSettings
+ Command="$(TargetPath)"
+ WorkingDirectory=""
+ CommandArguments=""
+ Attach="false"
+ DebuggerType="3"
+ Remote="1"
+ RemoteMachine="NB1"
+ RemoteCommand=""
+ HttpUrl=""
+ PDBPath=""
+ SQLDebugging=""
+ Environment=""
+ EnvironmentMerge="true"
+ DebuggerFlavor=""
+ MPIRunCommand=""
+ MPIRunArguments=""
+ MPIRunWorkingDirectory=""
+ ApplicationCommand=""
+ ApplicationArguments=""
+ ShimCommand=""
+ MPIAcceptMode=""
+ MPIAcceptFilter=""
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ >
+ <DebugSettings
+ Command="$(TargetPath)"
+ WorkingDirectory=""
+ CommandArguments=""
+ Attach="false"
+ DebuggerType="3"
+ Remote="1"
+ RemoteMachine="NB1"
+ RemoteCommand=""
+ HttpUrl=""
+ PDBPath=""
+ SQLDebugging=""
+ Environment=""
+ EnvironmentMerge="true"
+ DebuggerFlavor=""
+ MPIRunCommand=""
+ MPIRunArguments=""
+ MPIRunWorkingDirectory=""
+ ApplicationCommand=""
+ ApplicationArguments=""
+ ShimCommand=""
+ MPIAcceptMode=""
+ MPIAcceptFilter=""
+ />
+ </Configuration>
+ </Configurations>
+</VisualStudioUserFile>
diff -r 458e51062300 -r 5a4d909d9533 muparserx/value_test/value_test.vcxproj
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/value_test/value_test.vcxproj Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,140 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{F2291F6C-D078-44F7-B0A5-AD200C348D23}</ProjectGuid>
+ <RootNamespace>value_test</RootNamespace>
+ <Keyword>ManagedCProj</Keyword>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ <CLRSupport>true</CLRSupport>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <CharacterSet>NotSet</CharacterSet>
+ <CLRSupport>false</CLRSupport>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Configuration)\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Configuration)\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level4</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>
+ </AdditionalDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AssemblyDebug>true</AssemblyDebug>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <PreprocessorDefinitions>WIN32;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>
+ </AdditionalDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <Reference Include="System">
+ <CopyLocalSatelliteAssemblies>true</CopyLocalSatelliteAssemblies>
+ <ReferenceOutputAssembly>true</ReferenceOutputAssembly>
+ </Reference>
+ <Reference Include="System.Data">
+ <CopyLocalSatelliteAssemblies>true</CopyLocalSatelliteAssemblies>
+ <ReferenceOutputAssembly>true</ReferenceOutputAssembly>
+ </Reference>
+ <Reference Include="System.Xml">
+ <CopyLocalSatelliteAssemblies>true</CopyLocalSatelliteAssemblies>
+ <ReferenceOutputAssembly>true</ReferenceOutputAssembly>
+ </Reference>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="mpError.cpp" />
+ <ClCompile Include="mpIToken.cpp" />
+ <ClCompile Include="mpIValue.cpp" />
+ <ClCompile Include="mpValue.cpp" />
+ <ClCompile Include="mpValueCache.cpp" />
+ <ClCompile Include="mpVariable.cpp" />
+ <ClCompile Include="stdafx.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="value_test.cpp" />
+ <ClCompile Include="muMatrixTest.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="mpError.h" />
+ <ClInclude Include="mpIToken.h" />
+ <ClInclude Include="mpIValReader.h" />
+ <ClInclude Include="mpIValue.h" />
+ <ClInclude Include="mpTypes.h" />
+ <ClInclude Include="mpValue.h" />
+ <ClInclude Include="mpVariable.h" />
+ <ClInclude Include="muMatrix.h" />
+ <ClInclude Include="..\parser\muMatrixError.h" />
+ <ClInclude Include="muMatrixTest.h" />
+ <ClInclude Include="resource.h" />
+ <ClInclude Include="stdafx.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="app.ico" />
+ <None Include="ReadMe.txt" />
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="app.rc" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
\ No newline at end of file
diff -r 458e51062300 -r 5a4d909d9533 muparserx/value_test/value_test.vcxproj.filters
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/value_test/value_test.vcxproj.filters Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Source Files\muMatrix">
+ <UniqueIdentifier>{d30e11b2-7b04-4b81-a70b-642cb076db3f}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="mpError.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="mpIToken.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="mpIValue.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="mpValue.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="mpValueCache.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="mpVariable.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="stdafx.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="value_test.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="muMatrixTest.cpp">
+ <Filter>Source Files\muMatrix</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="mpError.h">
+ <Filter>Source Files</Filter>
+ </ClInclude>
+ <ClInclude Include="mpIToken.h">
+ <Filter>Source Files</Filter>
+ </ClInclude>
+ <ClInclude Include="mpIValReader.h">
+ <Filter>Source Files</Filter>
+ </ClInclude>
+ <ClInclude Include="mpIValue.h">
+ <Filter>Source Files</Filter>
+ </ClInclude>
+ <ClInclude Include="mpTypes.h">
+ <Filter>Source Files</Filter>
+ </ClInclude>
+ <ClInclude Include="mpValue.h">
+ <Filter>Source Files</Filter>
+ </ClInclude>
+ <ClInclude Include="mpVariable.h">
+ <Filter>Source Files</Filter>
+ </ClInclude>
+ <ClInclude Include="muMatrix.h">
+ <Filter>Source Files\muMatrix</Filter>
+ </ClInclude>
+ <ClInclude Include="..\parser\muMatrixError.h">
+ <Filter>Source Files\muMatrix</Filter>
+ </ClInclude>
+ <ClInclude Include="muMatrixTest.h">
+ <Filter>Source Files\muMatrix</Filter>
+ </ClInclude>
+ <ClInclude Include="resource.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="stdafx.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="app.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="ReadMe.txt" />
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="app.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+</Project>
\ No newline at end of file
diff -r 458e51062300 -r 5a4d909d9533 muparserx/value_test/value_test.vcxproj.user
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/value_test/value_test.vcxproj.user Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project>
\ No newline at end of file
diff -r 458e51062300 -r 5a4d909d9533 muparserx/vs8/muparserX.sln
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/vs8/muparserX.sln Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "muparserx", "muparserx.vcproj", "{E202E8A6-284D-4AD9-A465-B11267571619}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {E202E8A6-284D-4AD9-A465-B11267571619}.Debug|Win32.ActiveCfg = Debug|Win32
+ {E202E8A6-284D-4AD9-A465-B11267571619}.Debug|Win32.Build.0 = Debug|Win32
+ {E202E8A6-284D-4AD9-A465-B11267571619}.Release|Win32.ActiveCfg = Release|Win32
+ {E202E8A6-284D-4AD9-A465-B11267571619}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff -r 458e51062300 -r 5a4d909d9533 muparserx/vs8/muparserx.vcproj
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/muparserx/vs8/muparserx.vcproj Tue Nov 08 10:39:59 2011 -0800
@@ -0,0 +1,584 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="muparserx"
+ ProjectGUID="{E202E8A6-284D-4AD9-A465-B11267571619}"
+ RootNamespace="muparser2"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="196613"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ ManagedExtensions="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../parser"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS"
+ MinimalRebuild="false"
+ BasicRuntimeChecks="3"
+ SmallerTypeCheck="true"
+ RuntimeLibrary="3"
+ FloatingPointModel="2"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="2"
+ GenerateDebugInformation="true"
+ AssemblyDebug="1"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="0"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="1"
+ OmitFramePointers="true"
+ WholeProgramOptimization="false"
+ AdditionalIncludeDirectories="../parser"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS"
+ StringPooling="true"
+ RuntimeLibrary="0"
+ BufferSecurityCheck="false"
+ EnableFunctionLevelLinking="true"
+ EnableEnhancedInstructionSet="2"
+ FloatingPointModel="2"
+ RuntimeTypeInfo="true"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="1"
+ GenerateDebugInformation="false"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath="..\sample\example.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\stdafx.h"
+ >
+ </File>
+ <File
+ RelativePath="..\sample\timer.cpp"
+ >
+ </File>
+ <Filter
+ Name="muparserx"
+ >
+ <Filter
+ Name="functions"
+ >
+ <File
+ RelativePath="..\parser\mpFuncCmplx.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpFuncCmplx.h"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpFuncCommon.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpFuncCommon.h"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpFuncMatrix.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpFuncMatrix.h"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpFuncNonCmplx.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpFuncNonCmplx.h"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpFuncStr.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpFuncStr.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="operators"
+ >
+ <File
+ RelativePath="..\parser\mpOprtBinAssign.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpOprtBinAssign.h"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpOprtBinCommon.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpOprtBinCommon.h"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpOprtCmplx.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpOprtCmplx.h"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpOprtIndex.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpOprtIndex.h"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpOprtMatrix.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpOprtMatrix.h"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpOprtNonCmplx.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpOprtNonCmplx.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="utils"
+ >
+ <File
+ RelativePath="..\parser\suSortPred.h"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\utGeneric.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="framework"
+ >
+ <File
+ RelativePath="..\parser\mpDefines.h"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpError.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpError.h"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpFwdDecl.h"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpICallback.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpICallback.h"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpIfThenElse.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpIfThenElse.h"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpIOprt.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpIOprt.h"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpIPackage.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpIPackage.h"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpIPrecedence.h"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpIToken.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpIToken.h"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpIValReader.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpIValReader.h"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpIValue.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpIValue.h"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpMatrix.h"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpMatrixError.h"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpParser.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpParser.h"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpParserBase.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpParserBase.h"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpRPN.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpRPN.h"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpScriptTokens.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpScriptTokens.h"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpStack.h"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpTest.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpTest.h"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpTokenReader.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpTokenReader.h"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpTypes.h"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpValReader.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpValReader.h"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpValue.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpValue.h"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpValueCache.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpValueCache.h"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpVariable.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpVariable.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="packages"
+ >
+ <File
+ RelativePath="..\parser\mpPackageCmplx.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpPackageCmplx.h"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpPackageCommon.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpPackageCommon.h"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpPackageMatrix.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpPackageMatrix.h"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpPackageNonCmplx.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpPackageNonCmplx.h"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpPackageStr.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpPackageStr.h"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpPackageUnit.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\parser\mpPackageUnit.h"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ <Filter
+ Name="doc"
+ >
+ <File
+ RelativePath="..\doc\custom\calc.cpp"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\doc\custom\example.txt"
+ >
+ </File>
+ <File
+ RelativePath="..\doc\custom\features.txt"
+ >
+ </File>
+ <File
+ RelativePath="..\doc\custom\licence.txt"
+ >
+ </File>
+ <File
+ RelativePath="..\doc\custom\Main.txt"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
More information about the CIG-COMMITS
mailing list