pax_global_header00006660000000000000000000000064141472327650014525gustar00rootroot0000000000000052 comment=b747e14a00afbff580e155d37e6669504f56c639 muparserx-4.0.11/000077500000000000000000000000001414723276500136365ustar00rootroot00000000000000muparserx-4.0.11/.gitignore000066400000000000000000000002251414723276500156250ustar00rootroot00000000000000*.obj *.ilk *.pdb *.lastbuildstate *.opensdf *.suo *.sdf *.log *.tlog *.ilk *.db *.db-shm *.ipch .vs/* out/* CMakeFiles/* CMakeCache.txt *.a example muparserx-4.0.11/CHANGELOG000066400000000000000000000303221414723276500150500ustar00rootroot00000000000000######################################################################### # # # __________ ____ ___ # # _____ __ _\______ \_____ _______ ______ __________\ \/ / # # / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ / # # | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \ # # |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \ # # \/ \/ \/ \/ \_/ # # # # Copyright (C) 2021 Ingo Berg, et al. # # # # Web: http://beltoforion.de/article.php?a=muparserx # # GitHub: http://https://github.com/beltoforion/muparserx # # e-mail: muparserx@beltoforion.de # # # # The code contains contributions made by the following people: # # Martin Rotter (https://github.com/martinrotter) # # Josh Blum (https://github.com/guruofquality) # # and others # # # # This software is distributed under the terms of the # # BSD - Clause 2 "Simplified" or "FreeBSD" Licence (BSD-2-Clause) # # # ######################################################################### ######################################################################### # # # Version history # # # ######################################################################### V4.0.9 (20200619) ----------------- Bugfixes: - Issue 68: Integer test causes floating point exceptions fixed as suggested V4.0.7 (20160331) ----------------- Bugfixes: - Issue 68: Assertion fails (i.e "abs(-3)>abs(2)") - untracked issue: cbrt function did not work properly - new functions: atan2, reminder, fmod V4.0.5 (20151120) ----------------- Changes: - New Noncomplex Functions: cbrt - Cubic root hypot - Length of a 2d vector pow - Power function - New complex functions: pow - Power function - Value construction and assignment from int is supported again (removed when going from in 3.x to 4.x). V4.0.4 (20151015) ----------------- Bugfixes: - Issue 59, 60, 61, 63: Various segfaults/assertions for unexpected input - Issue 55, 56, 57, 58: Various issued related to a failure to detect missing brackets. V4.0.0 (20150622) ----------------- API changes: - removed value and variable constructors from integer types. There was some confusion about the extend of support for integers (see Issue #36). Internally muparserx is always using floating point values even when dealing with integer numbers. There is no point in the API pretending to have real integer support. V3.0.2 (20140531) ----------------- Syntax rule changes: - Semicolon removed as term separator (was not meant to be in the release) - postfix operator identifiers are searched only at locations that could contain such an operator. (This will prevent conflicts with variable names.) Bugfixes: - untracked issue: Identifiers of uninitialized variables could be lost in error messages. - Issue 33: Value::operator+= and Value::operator-= do not work properly when used with complex values. V3.0.1 (20140527) ----------------- Bugfixes: - untracked issue: Index operator did not work properly when applied to non variable types. The bug only occured when used together with an assignment operator. V3.0.0 (20140525) ----------------- Warning: The library requires a C++11 compliant compiler! Syntax rule changes: - Curly brackets removed from unit postfix operator identifiers. (I need them for on the fly array construction) - in place array construction like: {1,2,3} to create a row vector - Comma can no longer be used to separate terms in an expression. - '#' added for comments API Changes: - C++11 features introduced in the code - Functions defining variables, constants, operators or functions will now throw an exception if a a token with a similar identifier already exists. Their API changed to take a managed pointer instead of a raw pointer. - Hooks for customizing error messages added; German translations added - Functions for undefining variables, constants, functions and operators added. - Functions for querying the presence of variables, constants, functions and operators added. Changes: - added "zeros" function for creating matrices initialized to all zero added - added "eye" function for creating an idendity matrices - added "size" function for determining matrix dimensions - factorial operator added - floating point data type can now be selected with the "MUP_FLOAT_TYPE" macro in mpDefines.h Bugfixes: - Issue 14: Precedence of Unary Operators - Issue 17: Wrong result on complex power - Issue 20: Library crash when " " is calculated - Issue 23: min, max and sum functions return values when called without parameters - Issue 26: bugfixes for "<<" and ">>" operators. - Issue 27: Querying multiple results of comma separated expressions did not work (multiple results are no longer supported) - Issue 31: m_nPosExpr incorrect value after Eval() or GetExprVar() - untracked issue: compiling with UNICODE did not work - untracked issue: Column number of matrices were not reported correctly - untracked issue: expressions ending with newline could not be evaluated V2.1.6 (20121221; Mayan calendar doomsday edition) -------------------------------------------------- Bugfixes: - Issue 16: Wrong operator precedence. Some binary operators had incorrect precedence values. - untracked issue: "Unexpected variable" errors could report incorrect expression positions V2.1.5 (20121102) ----------------- Bugfixes: - Issue 13: Unpredictable behaviour when using backslash character in strings; Fixed by adding support for more escape sequences ("\n", "\r", "\t", "\"", "\\") V2.1.4 (20121010) ----------------- Changes / Additions: - Added casting opertors to the Value class - Added project for qt creator Bugfixes: - Issue 8: Crash on invalid expression in Release - Issue 11: Roots of negative numbers computed incorrectly - untracked issue: Fixed a problem caused by changes in the behaviour of tellg in GCC 4.6 V2.1.3 (20120715) ----------------- Bugfixes: - Issue 7: Memory leak in GetExprVar V2.1.2 (20120221) ----------------- Changes: - License changed to the BSD-2-Clause licence Bugfixes: - Compiler warnings for gcc (gcc 4.3.4) fixed - Issue 4 fixed: memory exception in mpValReader.cpp V2.1.1 (20120201) ----------------- Bugfixes: - Complex power operations could introduce small imaginary values in the result even if both arguments were real numbers. (i.e. the result of -2^8 was something like "-8 + 9e-19i") V2.1.0 (20111016) ----------------- Bugfixes: - Issue 1: 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) - Issue 2: DblValReader::IsValue broken for numbers at the end of the string V2.0.0 (20111009) ----------------- Changes: - data type changed to a matrix type instead of a vector type - Multidimensional index operator added old: "m[1][2] = 1" new: "m[1,2] = 1" - internal change: 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 muparserx 4.0.11 =========================== The evaluation of a mathematical expression is a standard task required in many applications. It can be solved by either using a standard math expression parser such as muparser or by embedding a scripting language such as Lua. There are however some limitations: Although muparser is pretty fast it will only work with scalar values and although Lua is very flexible it does neither support binary operators for arrays nor complex numbers. So if you need a math expression parser with support for arrays, matrices and strings muparserx may be able to help you. For details please consult the [muparserx documentation](https://beltoforion.de/en/muparserx) V4.0.11 (20211123) ----------------- Bugfixes: - Issue 112: COmpilation issue due to an invalid header file name V4.0.10 (20211122) ----------------- Bugfixes: - Issue 107: Complex multiplication-assignment did not work correctly - Issue 110: Short evaluation for binary operators added (thanks to user egyptyu) V4.0.9 (20200619) ----------------- Changes: - Copied unit tests from muparser (no new failures) - Introduced a maximum expression length of 10000 - Expressions will be checked for non printable characters Bugfixes: - Issue 68: Integer test causes floating point exceptions; fixed as suggested V4.0.8 (20181218) ----------------- Changes: - Build system changed to CMake V4.0.7 (20160331) ----------------- Bugfixes: - Issue 68: Assertion fails (i.e "abs(-3)>abs(2)") - untracked issue: cbrt function did not work properly - new functions: atan2, reminder, fmod muparserx-4.0.11/cmake/000077500000000000000000000000001414723276500147165ustar00rootroot00000000000000muparserx-4.0.11/cmake/muparserxConfig.cmake000066400000000000000000000034101414723276500210720ustar00rootroot00000000000000if(DEFINED INCLUDED_MUPARSERX_CONFIG_CMAKE) return() endif() set(INCLUDED_MUPARSERX_CONFIG_CMAKE TRUE) ######################################################################## # muparserxConfig - cmake project configuration # # The following will be set after find_package(muparserx CONFIG): # muparserx_LIBRARIES - development libraries # muparserx_INCLUDE_DIRS - development includes ######################################################################## ######################################################################## ## installation root ######################################################################## if (UNIX) get_filename_component(MUPARSERX_ROOT "${CMAKE_CURRENT_LIST_DIR}/../../.." ABSOLUTE) elseif (WIN32) get_filename_component(MUPARSERX_ROOT "${CMAKE_CURRENT_LIST_DIR}/.." ABSOLUTE) endif () ######################################################################## ## locate the library ######################################################################## find_library( MUPARSERX_LIBRARY muparserx PATHS ${MUPARSERX_ROOT}/lib${LIB_SUFFIX} PATH_SUFFIXES ${CMAKE_LIBRARY_ARCHITECTURE} NO_DEFAULT_PATH ) if(NOT MUPARSERX_LIBRARY) message(FATAL_ERROR "cannot find muparserx library in ${MUPARSERX_ROOT}/lib${LIB_SUFFIX}") endif() set(muparserx_LIBRARIES ${MUPARSERX_LIBRARY}) ######################################################################## ## locate the includes ######################################################################## find_path( MUPARSERX_INCLUDE_DIR mpDefines.h PATHS ${MUPARSERX_ROOT}/include/muparserx NO_DEFAULT_PATH ) if(NOT MUPARSERX_INCLUDE_DIR) message(FATAL_ERROR "cannot find muparserx includes in ${MUPARSERX_ROOT}/include/muparserx") endif() set(muparserx_INCLUDE_DIRS ${MUPARSERX_INCLUDE_DIR}) muparserx-4.0.11/cmake/muparserxConfigVersion.in.cmake000066400000000000000000000006401414723276500230470ustar00rootroot00000000000000set(PACKAGE_FIND_NAME "muparserx") set(PACKAGE_VERSION "@MUPARSERX_VERSION@") # Check whether the requested PACKAGE_FIND_VERSION is compatible if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}") set(PACKAGE_VERSION_COMPATIBLE FALSE) else() set(PACKAGE_VERSION_COMPATIBLE TRUE) if ("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}") set(PACKAGE_VERSION_EXACT TRUE) endif() endif() muparserx-4.0.11/doc/000077500000000000000000000000001414723276500144035ustar00rootroot00000000000000muparserx-4.0.11/doc/custom/000077500000000000000000000000001414723276500157155ustar00rootroot00000000000000muparserx-4.0.11/doc/custom/Main.txt000066400000000000000000000007011414723276500173400ustar00rootroot00000000000000/** \mainpage
\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 project home page at google code. \section toc Table of content \ref page_features
*/ muparserx-4.0.11/doc/custom/calc.cpp000066400000000000000000000032701414723276500173250ustar00rootroot00000000000000#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()muparserx-4.0.11/doc/custom/example.txt000066400000000000000000000005451414723276500201150ustar00rootroot00000000000000/** \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. */ } */ muparserx-4.0.11/doc/custom/features.txt000066400000000000000000000050041414723276500202730ustar00rootroot00000000000000/*! \page page_features Features \section fea_overview Feature overview \section fea_predefined_const Predefined Constants By default the parser supports the following mathematical constants: \section fea_predefined_op Predefined Operators

Binary operators:

Postfix operators:

Infix operators:

\section fea_predefined_fun Predefined Functions */muparserx-4.0.11/doc/custom/footer.html000066400000000000000000000011761414723276500201060ustar00rootroot00000000000000


muParserX documentation - (C) 2010 Ingo Berg

muparserx-4.0.11/doc/custom/list_expr_var.cpp000066400000000000000000000007411414723276500213040ustar00rootroot00000000000000void 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"; } } muparserx-4.0.11/doc/custom/listvar.cpp000066400000000000000000000007251414723276500201110ustar00rootroot00000000000000void 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"); } muparserx-4.0.11/doc/doxyfile.dox000066400000000000000000002230371414723276500167510ustar00rootroot00000000000000# 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 , where is the value of # the FILE_VERSION_FILTER tag, and 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 , where # is the value of the INPUT_FILTER tag, and 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 # # Qt Help Project / Custom Filters. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # project's # filter section matches. # # Qt Help Project / Filter Attributes. 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 muparserx-4.0.11/doc/muParserX.jpg000066400000000000000000000213351414723276500170370ustar00rootroot00000000000000JFIFHHExifMM*Created with GIMPC  !"$"$C" S  !1Q"A 2Raq#78Tbu$3Br%4GWcv5CDU ?h<7iᅦL8߯4k#;^p/M,w_~+Y+֝q׈}´c],{N eoQeoQ__3X#gAY4-cgmR }3 ; 9~UቱD4ax@DDE)x.p/&xǤ>vӕay.54qr} Y[=?z}VO޵唰٦~:{)/q k՗^h9w:t'?Բ44QwtiW>"" """ """ """ """ """ """ """ """ N@1 <Ba_| o?l?y."538'?O5[YQ\<ߌ/h d89|~Vt|_>u7V۩2 hT\+DL%JM%ίVyo-&1 ؿ]6F:wJ """ """ """ """ """ """ """ """ """ ""]QJD 7\| 3Yo}Gj ,4Ėwr1:(?@nզFg5XĺQpV{2j i#>*vu~VcluhIDVLhˑh)&?{A?&Jkb}%3b0z!A8 [FViMiOmufSyyyyL Vzznp\Ԗ#O\3դ=#q5>< n%nm7QTd';ԎpbKx0W[Q]]r F<{k= h 馭BK@ D>_>6RX[@Aj{ eW-G1KIAG%D 52\@VؾiSwvj-Ȱ4k.MpqF>V b4ϪP\lz2Gh [;Xܭ[~1Qu_Gpzt]5*53u󻼫]$ҟY.$8肚vlQiK$MC%$e%[7TmS׶hk?ҝQz:p2pZFv O%4"bTpu$Lv<#[D[-QSSY`Ge'5RVe[F=zdk{q}M~h .WM?0<\F>B]2[ֳSj=/V7\elw 1ᬑs8#-R2(hk0@WLPi6(Y#bkqᗱ 0?M6ڟ{=ӻ7g8@FvqMe5%KΟ:SOQsԽn:rÚO1Q틵Қ]9"*3'u ox3s#H@]I_Zz[IoWSnZi%mS%8saw5WO^zG{[nMO]or ( [w\7vI%ss+I2 +騞BlQG—=p鷻{qs**-dfkp8|I*ItRPH鮔QU>~Q^?h,; vSSȞ=O@:@DDD@DDD@DDDA[UM..fWtA صw_s/kbߙ~}-As=/*̺)!Sdh~?OtO.h~?tvɴ9%_Yf #x}.~cg:ًr4S^|k_\N<}GY*z*I犞%W268Jiuw_@doڧQun{۪N&Z$EsAi,$h WQ`BɣpsAvصw_yQUG1j޾>l {0odӼ1S~DcQ<堸WYw^.ܫ]3:1#:[GU 1 J Aps_eU= ,uSS$Ը涝clǜJJ}o:Nb*'!a6uGe4.t\rHz.98 1g{|w kޫ%uSKoa #=~'՚tݫ;[{[^ j+lQH#1=^?DKbt.f' v$:o|3i{ZdymwW~e K]P. (6߷C%\_(s(108܍͙댂pF\ T_?ֻaq4jZ K9hs\0ZBvNhڋVP[)ubF7J nj: Dmh=ˋH#بoaKԻrj- y$#eCKwT]38t-; TY#| ϡPF˨v?||.hQ_Œ'}OAяciѾ_o~аqӷ(Gʪ+=o#-_GlWOGIy<㍾nq ittgJ3EI-#"sxd(c]Tz].kIu5H1{WDu5<|bcwHZ/Ob}߹FD"~N9J """ """ """ -_p/MƇu25 šLj{x8vOVr<о9eaC^C΢뗩uL3xw1Rp%7ZwYHY`c9wU˵ >Ol*cTTn7g){qާe;.sUmvQ(T,&\sx-8,c /5IiZ6qüWKeO|#Ā;)f'hJWU,2'0JrZVYu3^ N,;4ɤg{PG{qviw;CuGd06^CZT8gA nàm=%rrڶAP4## rW1Q/i5li;eLVُS԰xsoQ6FM hrk`槭(^,M~Z%dFpuF[n36z \Y()x,ok&^Zx\ q-]^nmc|SѲ6Q1`0c FZK&]gWAn4xō{GajPPT߻Dv.(:V3-};g9 )Vp7=iit삲^nZt!Ysx'Yfk[)WW ? Ii^I>]$@dTzwwu'hUt94SQ:W%H}CG]ܗtp G_X [%+m[*n4U|s5qfH =@9 ͻ4WleU7ҭa8XI\,EkwUt3J[M= D/k\ztgmmZi-VfR)g6;c`-[I҆;^S\d8u=:)szwZ><l;F#hAVL{KHQDFaqɍ ^WZ(CcYVr5fIŤNiˉ%z\8ƘzAw?vR^*P(5OUQ3=5%>oܶZ]Aj5={la?ߣ=?muparserx-4.0.11/doc/muParserX.png000066400000000000000000001141261414723276500170440ustar00rootroot00000000000000PNG  IHDR~ pHYsHHFk>IDATxu\T>g Nn泰؝"Jw0wwfgfu^a1@ @ !Tiw@ @ " @ r @ B9z@ C=@ P!@ @(AO @ c'@ 1D@ " @ r @ B9z@ C=@ P!@ @(AO @ c'@ 1D@ " @ r @ B9z@ C=@ P!@ @(AO @ c'@ 1D@ " @ r @ B9z@ C=@ P!@ @(AO @ c'@ 1D@ " @ r @ B9z@ C=@ P!@ @(AO @ c'@ 1D@ " @ r @ B9z@ C=@ P!@ @(AO @ c'@ 1D@ " @ 4~f?m`3ve " @ (q?T7y=7O*yX+qriPVv@ GX ׇRtJ{MFnz,!>+-)QiwP z@ 2GUgJ):F4Nݘ!|PǐjfZ[=%>D@ 9~K,F?º~QG xWx8~Dΰ/4!@ $,8-6<F.6iy}H g`v|b_NJcm<ɠvu4=~eLigPT'@("9TRⷩ1KĔ {wv6ABj؅~Lb&1QzO{icszS%:I\^5#Z컑"Ep?ܯ盐?D@ c1ҿM_NwK]+,d&0}:FnfwHOWcgXޘō0_G %INyUh2;g6vXΉW~-&0"!"K{ C=@ Baxq٘~ǮnH1w\ݴҽ#pӎvof]+}w䌆ދ?ftzJ9R$WZDewlSKx'0xڏw.FDJ Ϛnv_3MP@ E;gKm_~#5 79:4CqYˤ;dQ(3A38Z~J~ vVy޲iiyO.xZt/m'OM9[vv{7z/Rd|nD<'a'@("솟{c &dM}B[lNZJ;0r)Ķ{2-MX:i7#?}L%ΜG!s}%Di(1bC:ca=ZxG:2t{f^ ^H4?.RV~ z0e@ BQ#ǫsaxL8 ٵNӪbat<bҼߵ~Ҩk[Mħ\V*&o`e3x0hVG Me UHIJ7d;nF)> A{1qe+G>X]ʓ}z@ "Tʻx?DZ|߻?mZ:+z'wiwQ"* ތ3Lo"}ie֨I $p/op#٨ ^> ,C_ @ (?cXoug$ ]}'y ?RD]OT>ϔe.U$;>=?O>/+eR#eQ8@7 ˀD$@ ~hv)LV̕4&)eN}&yQ?'gm:m,-7AO PDMWʻl :W˿IQ%:;Q&d n@ܔ#'@("sb*ϨR}wղ 6y#n*72 @ E%%WPR>g/ % -sG*7(@ `WL_L+,{͙+8UࣖglHyW I}D @ Z 6.FՒE-{)w;Co=zD/K{ 0@ BI-=M(\;i't۰?v;6nx+C ~lo?V8("*'W^<`S/ϲ+9or>\ٻvw=Wn ̏vޖ=ފw:$12y]kTSMv6Kx VX@ 8u +x=vC]vVW&ظȕy#k Qg?{rU.Cθ~ޖ)]06!'Fq06bŴKi"H @ YǙ_g^IK[W"s:[D.x(`SP|N)&w#s*(g\qZ͵DTD211?DHiH@ n&mf9?( 6=QʫM+ʫ.FY?ǹ= ݷKygoӻ:9_۞~K'*.ΝJd={Oz@ !]fotOMU5Gʳr\uT>7*7R>U'بEO)RMal)* ӈ7kDOh6HqM~NvۼyO !KSA=@ _uyܷ6])p(U 6jF4P2Fbw.wػ Lc?2'xAAAҾ& @ T+-IkAF55Bmk~R~RM/*QٷZIaӁt~6G,\LJ3L sy}dȢX@ enbD׼RI5++͕w}sa((*϶*~Eo bHo"44Ҿ2$@ 4oqmE *5Pr,坋!$@ ȥG%'\{GoHZR0^T +s(sU%;*J467DM9҆v&:"&Vqt{.ڃ2ш&5 w6k=m2ϼ 3!@ NѤJ2}Ƥ.s,B_dE!+2FIȍ9env{ذ\ðzB¿XQb_1[I ͳyi|#%3wdJ+v~:HC:U\"ݴޒHFk׮V~&W>䜥{;VW-R)&ǹKaz5z2c~7v o4Z|!Di@  oaFG_w4m| )B҂K 1ؗz!q9f2\6߄x7%0[g~Xlc?gŀ1ԽReE'CR>l$UQF3 ~ٲer'9oee7Y'䒜Q1 0w~\xeVy\TuVĀK֧9ߜe~nbМG%6F:IQ&Ia{roi+Pf}([SyܬҮC " @ {4.j:4A|: ᯒ'Kkzxebyl?o͕ϻUgӶbk_p 4Gt;{? ]$p߲6IfYIك̖lSYO'"of>+@{VC#R4H[ǝ̬* ׫ΕW*sG+rX {;ځ/MYԜB酧&}@si*AO SEe?)S cmևՅg \Qo Y-ygiĔȼulڟ/OƸ#΂'|1|e$[; ǻؓpϔmZ5')*ȫ-LgiгJyGʻ99{s\xK˻m\}%L1=Gf ܡSrQ CO FFFFۗR'o o ``)/\vw&MIK̗^ojY-Z띭wήg@ LHHHHHH!*kiikkkkkkET0ŭ9~3S5w'\ [ASz:*W"jO2J<ͳS GkT=`/vDcٞ_L""$kV rNX%6Z x)fK(į+oszfގ=7WNzQ?WCעIy\+[VGf> E]lOOMUog'J7s9ԑ}5=}Pך^k,F5+rr)H( %z#FD߈` ɐ S4XbE37le-r-=gW>8|EEE6m^ۼF@T$ފӊӊL_/W=f=Cu:qd;l@bMH7WyIl.;ϲJDmrՕ}G';gc YΞߗ^+0C/?sQ' fj:ZW^>Ƶ0{&}4=gfGsέn>A|ъ.WZnńUh"5#̲cCjR@(<{fMR\RR^}͖-1:Oj6-`W0,,Y:Qޔ7`ı:]:}zzzzBai@YOYOY؝;cwD"H)/+VX| 7%D"iU%=$=$=9(lؾ}c5j,######>9!R %88XT55|{xY@_W5 ]sSQ.vuvpɡiap<\u]ak]4;jȘ_oUu]ѣ3{^'7ak?ӍV)ϕ7szf歜[׾<;ruLDFۙۙkWϷ<'JsݾСC_WmپZrht\5ڍя|j{{)z?ǔj{{FX6lfroV bb+ gY|6(((((Q*JҢk'$$$$$4dT_VL|9r ;s}fg.]2Il5̠=uj[v䓔ңFVacl_VK,ټyl&u]iaϥt3" (=rBflAYUF̵\KZ)yS8ߩe]9m7x=[cӈ6K;k% P"UUWAL! yBn|ձ::IyeeR7xx̙3\t&d^G=Oөsγf=xnSg@  8,h٘zZuuu711111^^^.p865hkkkhѤ|\mA[yF EXK/;TCov/ ^xR,)Z7/|5O_RÆ_+6 vDR-vqv\I{Uhu֭[jZִQڳE T!?%?%?ӧO&MlVs]]]]]]ůlaׇ]~{r-ZhтM)>dU˪U-vr)T7hkvX6=ﮉ{eV/7uײ滫%],&5 ^]no|>QheUNZ| @}zXzXQG^U\\Vg@ 333ElǏ?~M{@sJyvnͣKZʳhhhT8gb0*Hʑ#a; ZVsS],F])*RE&^]$Jy-:5Wigk>+ǓO~̇q<3a8ke ^>JlrJu]`@s`OMN)FTEITE%9RUQE?]`9=HC\=$PPP```CwCwCwp'pW?B­i5ՐMl {u$jUq-@(,l1&M4i҄@ sT3EMMs^QۣL˙3KklJgu*oKREj.{?*g^zǍ 4k#HRoz?}Wo\V:iiii_^8N ԅvתUVZ؋a s9Üy˗/bX,fWz[mUVZԖQk<~[%/m<- &oT^yͿR>?E勖+BKB矣I_d$&0k,VV,>{C=E;,,Yx7B9j-677777W>"""""",,,,,LS}Ǐ&M^fɻ|Ɋ5*1}LhYڽ&?!!!k6I8ο G@ NH KljLW+qQ^=rn)C+NKq5&gHExwD6xQeJ*w @pUs$IPڽ&EA0\0\0Y{iOiOiw{7ha#nM"D4*9Iw T%$NtO,ey|}%QKcrQrIy%mY|Ob1u{l'$$zoV P6⫊ḻQnULLLLLLڠAA6+++++իW^b2gq5kהBaqqfo,Yv3 q뼷V[voz{ ?~U{{)z7mִٸ-_|gfWS))|i^##CCiК;br䠡3vn.%%u_],W_}WWWԏٳg G.w߹o*y8߿Oޟ?y?{Ĥz}/q۵35;9U8C&`^glՐ"Ky"|W3*fj`c~iMCnF]erȲ,Jǁ0* aL˜'N8vd7cLLbn洩Λ*U_ruө+G},_PHTc&w_>|weep%\ 9M֧O9 }m:p:N:RK&{yp-XjZִk׈%!VƭL~u?(잻L~MM +վV4_||W^7^s9f{fvt7M5p벷SgqD~__}m3M%'oDHSt,,qgZyi}i,_GkVRM:u.|}}}}}##Ghh׮]vWf:a5Nu%I+G)O):&QEHyuz"5/0&gT!gn'VQzjttt/-[T=3n 1py/y/_Vv˞sݾLpnC!>4{"eeD{ޱ'$#F⹅w!f{4ݑ rr>UTJ=6믋8q16&p*TɁ>^\$׷^z_p#F// 9p ?\DDz̫ׯ^1B(MLfƋ/6< dڣdvle`Pwiio}2ȩ!y rj>|>}&zX{XOXaM=~wSVVMua\﻽eAAJX&M[̒0jjxMb%;<Z|f9\ScÎ urqw2|3|EQ JA_[nu%eӿ~xybr5Eb b b 2g(YthQ;;bwdSvЕH_/6dK- %= u"FsM<%~ n 7' O[F{ħF)k̖BXR>g1J 6USEM LMRXh,eIVg]-]-]- Qo /Ter»{zeT7پ[kTol^yY#gd8v#G{`HQ4ƌ9ś*C6Ō#w;(Ֆ꽪aM7=>UB?)B~h6EO#ٱ{|T8p1sB߶ۣ7+Y´̱mƶw*~Ncݎu5xo qbg?ҜnV8`pN5tvaׇ] v47r z햲 O&)¶3̛|__ Dh6B H|vG._W$HHHHHHx<Ǔs F&>pÉlU]WWWWWW[[[[[e^C䊋kV^Ҫ**#r_|)[kĞ C,ƕļ]wY_} ȢB@Myɳ%wssskذ° Ì+TT=zJy$$6xtpL¹՗Slzrjv}}ccWٱ9:u>={"vkkw{ɬYcB7G4+IRIDoi{Dg3\t^X)2cy<ˋ/gi߿}EXUhчo:-߻w7lzrrEW&[ltuSuX1__ʋp:Iq괠3:gc+տ]]2w}uxdaaed\]me4 s3CjBfZhѢE Bwtœj(MqqUT\Rר?R2xsi!ROVWyRIE h/4yd?cz][lDT*{`}UKy) vv 2O\8ƍtcmg]tHlϽ{,<3Ϋⷣ>AA~K/]/[Jycݎu4i$f_(`os~s9a a Y3gH>}Z3fsSuIѪU-,Y,L]ߏ=^eC ַ69g`݇uU usmdqƍ3GʳL0`K^yC o)a_ݷuF׍uA7o_,ŒE+Fdᩦ|v nx=|Og "5mRmssi?SZnݻU;+L雨ڒS:pu3wx5cٌeVKRW,' řOcc*8-'ldw^yvu^s{9EBZL6۸h׎WPz-SKCFl͝7wR}{2}ҏJ&Tp:,v^ƼgYpܜbei75Sc=n&j&c`b54ER]'ӓNSo,\߉2eԱtttO1 swQRbU8W-sl_g\`+bҞi*UUf__k?v^y Ժ^n<\AA8x 5uq|]d<jLt܈yWSSU.o o JA)AW&r̀QQ4hlq~k6>mcc6;OB?wܛU)c[}v j|Dvk=-1[bx^uklJS0vI;e<ѿђFKu{[n}d [ -yKxK?d1W٣fAa r -}/L7n2(Vy*6{iY>8"FFFjrru_0]0=w2F^%)kYDm7f#Û{adžkmi5&rY6y%%%H3:V[)~ %}!YZ 6y<ǫVrS~ u5))/fA!Jiˮ]MBS!2y!!!ߥO1d0I [(hz u.X38 4`` +xO>1G#* ZA(8̑9Sp B[h `!,DչjAuh1C{^y则fnʅ*l4yИJEo Mz .6Bwqq׭[E{NN<62G` :`F `ڂZZmPz| LF׆ !XHkO)B)Ta ju垇~3xăS g3=lV|^o{e1m!((Zk}OU ~AhbPbP깷޶DW 1;C@"B($ADA*@ N 82 A dq8n2[TWol@<͒WmϽ½)`ZZ;:::ڝ%/|_}!sŖ[Vli TFIюm7\7h-Xzz)yQY ,tz_x^{Y-u|G{|A @Rn4Dk .+N#T< ge z\Kʷ$uEh "!\50h20x-/:7vvU(E(^H$t4tPYll*,=Ѓz`  P Wt؀ 菮?~7{n9/wC& <~&RPqQQQQ {SeXgXkk mI1xbD7xtN;뭚+NBjz\-+^7n RլWDZjS$СMO]  mLxcMiS:־}3 3C{`(y52?-ZعX_! B kcmxp)RQUGU_~iMkͪ5>ht;m(#`n0{p ng x Iz4іP6Ŧ~1 $@ ?+|HP !C$@ @ CdX?2|iRX#c8l`Vx +w2 [[  mƭ@/#Ha">gYpB8]]H׀ >AkT>Ͻ滛nr7p8UW^e =65J@a& "smvn%*|DV>4 963dUtDCWWۭ:Yk%Jy"Y{J<+]M$B_ÿf.x(üqǣ^eނ޼)j QwPé(B}Wp-v-W2;4P5C͠2t.` ]X-6 ->~MNg`|?)ǁH {`C e -iAN0 !(18*5=pq Lk0͑=Z$ $ df-Zo|I `Oi 5X9~ʥ-ZV"v9ltiokA f@G)Ii0~FƟr1yu}*xly~>YOn C=C؃=T10:AA'03 e?fm#0߼6`IpAw[!xH n6xuƂfYqV;//x7ލ U` OLLLLLUū 0@z* ,0,,,,,LrBrBrBY ]2dvqqqqqq)1,Ee|CT;b\K0MDˍL > naˆ[ѵ ۢ7Ln&7a=KNub|Fxd"ͧϹETce]sݏ$nvĔQlFM74ֲnףk6y|U1\E!Oʳ; @ȮM\ﹶAc:1T'HMR *>O2v\;[)ڵV@U a(xF'݊ES:ti^L4hѵhoڛfwfXu.D@,&ЄlOyӗ_VBׇ͞<1Ąk7S|ӷ͂3\6oF_jWWO-^-}vw=θ:=U^Yye+%o 5 ]ɡt;QT2B4ݰn a#lNP jkx o-ZVY` \h5jo͡9)Uɰ@ @h&xZr{`1q~1~1~1x&gZgѯ7olؼ+Wn`lm^|ƇSp.[oYa=Q=%)ozNg:Ƌd'Lanѳ)F]gLMCuV׭?L8ݧ% 'pQ,c `[ &kū5A/s\iZViSI+}mnzbiR8tYF8>l0T)Aa 6[K}99 z}ssbkk*PEs+qqO^lO sNuVS0Aܪnnwpssه!|`PST֒'wߤ5o'Nx3s=nnyv;w oܾӏN?fUS@TwqK&umֵ-Wݙ0u}-kϡ=:u E /#dzm򾋿/ J9 P Å:u oᣆ.ԅ" j`h=@ @hMTjM뛖iiiFH-kGnٽ!mB76=tMX+&$ttE&&&PC2b#Y2;W5>r*)1n /3u%}a&wLAUQUTm_cǺot73t vi5Ã}X.ꗐ!vy0x6D̃6ZP j|z cddq _k])}hUB](+tB2A z@(boI۔)II݅WIu\>|?˰.9\pS|J{N+nl̞5_:_k:kt>>jtz:=rFHߗRA3g]@W4̏?"$6I.cp$KKK$@W_}|BLBLB$S)98b_EVEVEVؾ}>va#2'B-hr,?`|V ݅`mN\M^Kk3ʤ^[n͜B }wxfRSTSS|z5D ML2)ˢ:E'6NG\4nry_+jSA0盐?l%@(2Gfm=,{Y܀sEʋVH H^H1Կ*$NN898+8+8+z3ͬ7>Yhڇ]w6 z;v.WZش(6ji-lj)[DYH!jbW ?NDL!q:t2)]a xOh®Cx8Ѳ*R|h!!Ǖq/ %(z =mը͗mJܔy' WX=;w:W]mԆgXYS{OyxǟjcTultF.4i:,Y3.o/j X4`Ѣo[vJoz"76"8].Ng[UwUUuL__@4]/J/J/#Gxݧ;?=zM=`Ҵ!C+~"?ڎm;Z`#͊S +OՏ3¾ *GlY_ImQ.'Țf$&:i5ZpFpFPZOh=of}bfʐ!)CRI6Y[!@ 8l<~6,x#HpٖJuKpvss\pU }m6^u}W݆wWxcyc9͔TiO\W?<# y7klج9s6XmUwU{ Xd,b,F|MJp|(5pppKWj |M{q(pN9\Ptu]XӏׂE|gEb *T' Na)1=.z\8 DЗi'%H}}RˡC=&+vn,1?}Mb:!3iߧ}ל_Z1􋡎6s9A4OwLfeq_R!4A- |9#i 7 7 79vtM"\\s5u÷o ߚZUeJN)]>v}L3M3M3Q3 5+~,G>'|Z^ 6Bߦ}%sk죰MkdP͠A5z4=)5z^[8`q^uz3 @ #RGd_w|5US<ȵM Ypp` ./H05zwnݹus9ժU*eFE%t ']Jy[<2xd8ACJҮ...ڨ/emtFFFc' xBiJY'%<+CuVuMȖ̖ ǑQ|5`:t@iPAO(pK" ^\}9m]ں̩yM&&OL32 j5 =pv]lrڊōNjUOOOOytхԱl_٪%tvo(3>3^ݦ2III?fcfuoԽQ""bTYUeUU;h!ɐdH26+Y]: s2 ql$Ve8 $j[A~}~iPAO(pgpgp`ٓ$5x[m7|!d2wբ{ZxSց}>,Nc##Zk1iIs& @(T}qZZS} OD}#Gz3'\vNJ^#..X{.I$'|W_y`5+|;***Td VjkV%DvfV@]]]R(@=s9s x,`굧!vMlgsETzK{{{5^yN{;Ϳu3zvle|UddUoԱ\`qgSuF̼ywoͿ5eC./@eZ>KZa7=czLǕWz\~u@tNO>dz]8(fs-X.,_QByzBE?S?SjPY43%#A e0 ='yyLҞ A{7Ԋ[%J -ꌫ3\e62Ӛ+z+jKv'`N8jr!#l-pwlL^ί| 222c0j%CCC0X, Vm)$$wM;*lllʎ*;xuyuyuKG2ii86ii 7uX/wSm))ުתxA.&&W+w,Gٻ잦JJ%;;miχ ~6f?EDiQp;8U or@کsչU[F]@5לuӱ~k[\J%RTsss z%މpqXFQvnݎ:uҞ?Ax vi4k-ӌiRmwYc{1p˧%]/׭Wma-l++⊸~dȼ!Tfɖūձ8Id'4巤ђhI$u~||-t!)Y=zFŌJIIuNH?H?=yCmVz]鵥gPU~kn-Z4~Lϵk)&my=,YJϢ^cʈ+#dOۧ "a,W_aqaqaqB߅y{M]&\k7nԎoǷS"_[|m!⊸B$Dk ;>Z1EwEw&Zk5#8o 0BqTQ(·n}O{v 8W+WmXrquG}R;;=W[_`$u7oΚmA U\?~Z/^F)ll'tjIuutîj8;/C"炞#{9J%vҢ IN }˷{c&)]osaAAFO _z"ūZjRn+J ,Y,KVT*J>N8D 6Dk7w}Zdv+r)9(>%[:Dv]pb쥞cw~Smy3f nI/q̋1/z`.+|.]z=mF?H@ (^B.\wyfF/_j?6D_#>u|N?;ԱgknqƖ 6_|a]uYfʰq֞=#܏A>AVf6afS/_jv3jUѠA]?:5K=/.|\qA^l?W6.]vk״v&dmJ۔y}-j)j))S\;6wl^EnddZqH:u3Ig5bhBi77y͑#W K(⮜W^Y隃kN٬s{[muؿu}Wvtn`jZjͷ͝1Ò]IzZ*6l6Tpڐ H<(髦 6%g t,,-ذ`îl:grtѽ|j)YC~O3R!2w?~׏&|}=]/N0Th*g?KR}:uZPoʾ)TWBCЛO4htOGFӢDHzMSgk;;_}?z%7,B7t|{sO?4h93X>N-ZZ?l^+SLyK۵k׮];M(t: -e" `㞍=ͺ?gφlT^~Ki5^Whiἳu]p8fYAɯSZpuvt*BrP>}-[/} ܜT!BZ~S:S*N1z}.o@kr~!~ ׺uPZjko(TSPlR!2xZUV]4lYg_@t >P)/j[7D5gSl;vxNnLOIfa?'qهn}#GdY,(g1g1l\3gLII6iSI_K_KX P @ tB 6 &;zJ34C f7*AO @ c Q@ @+a%Uz9,Y@ $7V 8&zggK5q3E)(bE%~Pc6Hffs-tT0ρHfJf'O+rW{ؙ3#DV}&YFߌ"!gׅuً%-śśp*l;e`2VL2\~V~VÄ S+E͍P9YXЎc~  zABjJxJxyoyoE)rXX˸7OoU7]ܻM#;7 ["V"E졨GQFĥĥ$ c60Q@ JrSh"F.syfiha#aoĶ)Yp,8g.\{$Sz˒kG3G3G)].B6P6P9zvLu΢P[PÙ3n]@߭l4V+xr瞧/ u77& xl`^WM&M|G~y^ IvTMCӠz:zj L@?S`&M_QV땡2X ??6Z=Fȼ(i/_ϔlTPqϖg."$77ggF8H8H/+@zzR}}aqz(X X 6aCJ:%7,rt*T0qEqEi+ F1:Q"Zegh+MQi_r~NZj X[  )))NNN@( A_hP&q{測zjӥmmSNNA-S%j,5kLc12|±2v̙eOV}ܷܷS Ң>j>5Jgpj٦5LV,S,cOOsneed؈9xlW#BYD^#aM&ZMt:՛ZJ-2a( jHIɼҒ/=/گ_/z{(C"eJwoeG3@gV7o8}^^KggY...䈇gn,~_Qp8Vtc00a,++wEEQK ܠ!zF<C־}h-z[Q֖[yg35kEkQmććkJ9*J@+Lۘ1ގhH`3XƒёL{ k\ ( q>OpR^^{Z%B>{ ="$S8u̩S)ExZxZ0BBHAUQUƄJti4?M> j9sH+hN)_ vKq.TکBoufI<*ɫ39f⤉D*+++**qf֣h=Hҁ z="[dK-S55e2s@,f3+++|2@#899:T}>H{pi P ^<.~l$sY,P^V&\]~:¤"zĀR^WLU-RR^b14"n$zʍ D(ݫ74zu]W/'Ta60ZQlRp_2FIIz5'*Sg%i4{MM=Z2-=-=qq~ԅP{m;wRLD&"J%5M5M5yyD/ESL2p 8a9,-N zTST nncncH7R۬^ bDE)];5[R8QWWXa}(jSz6m@8kGŏJy'IxU<4jI;S;SP=Cq삼\PJCiZKh-pNhW    ++[XAVR+=k%A1$O$Od=ttS H#gYt'BZ+e L Q&%Db)bge'yyM?-H&MId١UAaJ:*^ƴi:PҎՎޠ7t07vLNފLdqU6ך"xx=R/Qqq~5q2q7 x3v]%---gggNIJ5b_uoBQb/J!@(*777CǐRNT2Sʳ]sF(%Ww"=:J;J;ʕǫīĵ cp neu"(D!I,~wqq wZ8|Ց1g̙)RNeJN;EjP ,˚ghr䂾!f p.ePKʳ cҽӽ <**sP"J,RETOTOG$Ֆ778`;h"@>胢bhr //(/Q}T_NJJ'X(deϒ>%}Jkp,X-/)j be-ppp.ި7U="YZ܃tBTRtC.}D-blۯ_BPsW_:ZW 26elzT@dP0w5w5ң8*dE2;Y?2 t{ {e wq8Alll+ʹXC>s=P<HR._'p*e@+PB'm6u JixإfȝzF=CBSګ[X8YMYMy}l @$Xh,ԿbózKR@TTbz3fQbJbJjBZЮ`g)R:g>g>u BՖ\)W)剚BrTrTB)M%68`ۤh?2 *gTP4AY&B&&0p705g60J•O8y|)0P*~z?%{pBIU+t_/oAA\ BAx"__ JSJJ+z&z&]ڱ['x+ s9[]+RBet蘅OOpsh5yQ&MLB ,\}eqGpGpGPZ%$2INBaA]{yxIxޢΉA b))))"5G'Q T.b(ʟ'nP!(JQ#h46E4$@4+ڲڊ(^"xxP¶B-7ș8qY,RpV-8q8.؂&&5C͐шFj}M0/LKTAOٰz&,H 1YY 5Sѷ[3Xue:ښ(L</@ԯ聎+EGQ$}2b~_~_ B.(:)*""# S=S=3SW9 ;;cp!uBUAQo S{SCRC2DR-ZZMl(6 iƔZDh838jjɲٺ B\Ks(___B) FHY:I 7|OufeH iAMe6d~2Gq‰D&n&nFOı8+-|FͣCid*Cs"PDA)Xh(J%7ᪿ AAiW88I+ϩh'7@J~"F S@q#6SFp NAPA\} ~^͉THgƂ Z^TTa;|KUCZNZNiz_ \ExD}\GA-e5H<%}S&QCA *A%PrՂH?x^!o$o$od2BZR?3yyyU 6jL "5 <_.}Švh(BQHiN5Z> S7p&+ =08$ φ)++WG\+`fRAE"HJc~K;jϸ`^W߸ h*V]B*o>p<9t2gg֦i## Q(ދXk--Meef/>;Nw''rY;Y;4i4]ޒ<|Sp 1􅜅x*2KL*A{{{~'B"$vvv!* Oͧn]R "5Lsvi}tv:hrG0AsT4*&,ܼ?>N@h=h?!R^pxwj-D;`)-{{JXf[U23?!QmTⰅU샠]1A/i.i.UlWxFڣ7$1Ixbb$C)[BwRݑ;6*2bCc(^͍0BnT @UŸ41ۯ:;,`% g7/%|*HJk \\*&U/g2g*""@(z y:ۗuQ!{{sE/KȌA+%gg ;UDAdKskskskˆʆʲ# P;zbi& N>T>T>!#dڜJ]"?J{ Fu%@l~}Q@?aX#es3!0 jzvh:RRSb"1ۯUnBM h{pվz,X{.s7v♼: P$fO߸RvkW >ݢx{NanP7ͼ\-1C!L"z^(oYDDu{&ZMFr((={d,Փ,#_|%;;_YwYwYwppp8Xq(6(6(6x:Gya8zmUAaTކh#:#[!@PWcS:Ԩ4Bl"_8BPڨNs9<(% n4-UfXV -F A:Gcvs CNxP, .i | YHO'0 A;pPGʳ.]^esGt+?%YMyu8>S^+'' qÊVo444u96 TjE'9!^èҘ>@P7J faЈFfJmCeO: zdG#!Վ/}ξʁr@_i0c_NNL$ɅY:7h/^,h=gan~7H$A|6Y(mmA Js qsxިߌqppr̒\}P@ũ!l%S+tF((^no]Gơh(*f|ADk*`t~FUNazhc|BI@ zTDۄKKZ2 ,,-ߒ.;8'"x.Og~LN7S?{owaߓS%rƓwna44 k,'z6 h:]N N ijs_BPj@ 000:::X@;j5R+֮* )܄pj61tnGF- z (DGw7[%~ h#ź!x؃=X@e,*TP 5 ăP.A=. h*<>`a_ԄʍI$͖*Sn*JH#Wr, X ݹ:V0{ZVEVE^GqUqU']+]+?&--i(DYc9z~@h eE9_JY+xx!h*cɱfrppPh)%Mj05 `0(+XS&~A-TqDqDqbSlX ŸnD7x^D1QL=9OrS۩v0C0,A2Dko ²3G(D[ jYQ@DA(B*8@;ĩ8;ම- `:`F .>E =^4@ 4\ g&mFa&jB%[>hhLTs[f$<ǠV?h)9jXͽhhpy<yp4hΗ2@ Q4@ mm G2$Cu}IKߥ*+&(&0XV*vƄYQ>a_uP7 FaHA lk9L[ҳZTjPB](**B$DB$+s9Üa&3 ƨ{=z=0aq _E|{f@f2=22iUyb$]qRqWUf# 0 S)7%˒J 2VHz$UeELG#>-sJy66|L./d2o֠ >A hcHEΒ.@=Ɵ.m 8@srrq^r^R"Ƅ1KLS71 kaCl<oB9tPvuFo8 eA_ m4;\9˜ejkx ~T/ sa. ňb$q^N;Ҏu^/;Xn`E &5^/[[ I%G N^(yQTE**r?PLG鄭dVb䑴[v&d\9^؂Cd2!$9uDqd LL$HęX H@r䧬[-sA e< {.ZV z=A=Wڣ!|\[t?š8h@_)ssҹL[-Vßg{kb{)F>R%RRf#)}H=QE,)//ʸ3Xcnmcmc~f2U*=9{o+eK٢Et %Z)Z)SH@-eKoCCuy}k*G+x暚\l-pPJJr+)sjF58DKeS)ԍ;;S0VKnC0CO`?9 A-L5(ya=FBBvUjߠVAg %nL*8xTƏcPpC K1@ARn4 x.jgY#{ zjKc `vTHLّ}dWn !Bڂ[c^;=P(+סk8K BZ*jrF {M$`L R P `b47Q'B!Y,&léhn*7g\rga8ܓ3y2[T[` AwtQ Fڰ/O?n L6xO-h j\LQt470~"}0XFHX3p[`K*ݰ~H?2Lw EuP=T^a7Z.DhdZwQӔj\J!uH1G1G1G-T?zq.C4S(jA,PXNg PuT6*&bqO_@WЕS?tP*Xnf*ghmPY-[hm)hoZz"=ũʩJqy>7;# ss.ycycPa\NPقdWdW}uu8p.ú 7xdLy/ H`^BrN}uP#9J+ZsހW*E#QD4 AmP5g-g- x+6E MBP0¶Ñr dE ȭm*=%dTg0۴_ A bf&3)hJ#`@7_~[!)7_WDFhE&!dYY@0;2GAn,7V iu!?䇊O6iicic;$B"'*A%p@%Es%;/;/ZXKyM^W^W&1Kau9J#\O B5iwvѼ0;B$wR`HtRmOz > z>ȃ?Ā.va8@CCK()ctӘӘUP*B7^^6` ѐҵTKTP'>"X{<]ٕ%F]%fg\r}>Ii*R< ?ډspۊB`KR/,\q8ƟqA{us \uk` )E0B'y( e>FaAԗ__V<%^ ѐ4a0PET1W}\PVh ?Ӝ:MP} Jb2L<Euқ@G|PE(wQ2Jڢo[Զ=Z=9/wf 331L }/|G6@7Q䗛.]mz(=Jd0g~Up7JoA0&"'@#P/Z N]QMMpq[֨t*Bb.nZV2Cʌ2@ґe!,\Y8 ga'석HDHT}5`%g?܁:B#?D2ILNT=}O_/)7fz3Q :RaTZ 8*m!!\uqt%.]GZg wwx)^0˙5eOS܂-7_X@ݢn 3 t>' tA`^SC1{TfXn JUNDDUztHG]P0ԀXx4T~xU(3A$TQ~~`_ǘc8jJ5-Eע))(0Lz&Vݡ;UlWlg*  212FQg+؂jAhWJ N"*w̙qƻr}&=kFV hkښZʹa쥺-F *T1>DhCp3L_@"7ƍ^=Gr$Grvio9🇤f3A P+ J#x՘_aš8h7?1#a1셚PQ&ʄ'.A!"UpWlRhc7\.1JE[Hhhh4 mƑ4,4  A-cTLHh50 - Ҁ;]g顟r{ww;7XˁɞqYcUU#wd /䅜讨{ '˓iNt9\6@"/圬wջ몺j7|sor ;cSDD]5]]tV̙Xwٟ2Joq#Gʲ2ʃt69힭?QjՇ걺.4kP6mn]';g\ܒov]{g&dMwOwOs.ٜ hͼL9DȒJ}~rClTʡur:sį|==_7<[,/ʏߥ\ʿP3\Wpy|wZZSZ{Yֹ)2ҽ{O?9'@[y޷Eǒ,ɒ\ʥ\Oؒ-ْdKs'Gr*뺳̾b]ۥS:l*a.fygZ_H9]ٗ}q彜ͅwnh[|<'LWguc?>[<%mqzWf_<]3!wSnwz(_*We2:w.`+s1B/?wuW˩r*`z{B.3xl~}XHhLg:}L97?—t=Dީkfq(;ʎlʱyz"y'k&[x4SĖewM3ts:ߗŕYfa89P`~3^gC&3x_ض^+\\哂NoYeY2`3[s,WE%a , 0A 0A 0A 0A 0A 0A 0A 0A 0A 0A 0A 0A 0A 0A 0A 0A 0A 0A 0A 0A 0A 0A 0A 0A 0A 0A 0A 0A 0A 0A 0A 0A аo4\uIENDB`muparserx-4.0.11/doc/muParserX_2.png000066400000000000000000001141711414723276500172650ustar00rootroot00000000000000PNG  IHDR<8 pHYsHHFk>IDATxuXTKw٤;L@@Q? v׾vww* JWPbXs&qߝygc AAAet  /"AAA@B   4"AAAh E  AA$!  BH(BAAP    AAA@B   4"AAAh E  AA$!  BH(BAAP    AAA@B   4"AAAh E  AA$!  BH(BAAP    AAA@B   4"AAAh E  AA$!  BH(BAAP    AAA@B   4"AAAh E  AA$!  BH(BAAP    AAA@B   4"AAAh E  AA$!  BH(BAAP    AAvޗZx E  Rμ*&tIx'~20{GMw  ӼY?S튩:w?)&C]0KLNjd `.!  JMUvB튩:cCVg $/~џd<{yrM<AAˋ1b9z/2x/u$so$3sH_oM$AA$<",:Co&+<*N?ˤ(f #͊X|& 9Yhi+VV K2dWtd,ӲDqP  ?ǰufdBT>B#IBLR%I6 B@VAb̥rgiCA?aF3kQz]QxlemF}y:\Әb=qOMo"$! ӓ̃oӖo2$jmE.ͪZd['z`wLbڦ %/&-~|&|R8ɺN{.+?~Sw1M䏄"AA9?>SsOg(Rdh=wK"ݮL=Z^ ;82m#hCifa!~~8 qLf]ٸQqy:])GZήWkJξkkҽm =Z踷1Q3O/yὦ4QAA` $]d>b?Lѡ˖LI[P=;d%ӛ3Br'c.Z'x SƧ+2ZFIçڡ3ڵ5z__Xns;6I׸5^oΊ E  s؀ 8{`?H=Zu얿Eb1R6ϭ &odHʥ-[÷C鲕uIU_N̉|\AH@EDɶ1WJaי`}7t[~F/oJ Ϧ';q· B@N~[Æ~akC  _AhSe;εum8<+ O3n̾~~S?7wG/)0d HhGnӪq>3(&ɤ%7Fۧ鎻:垈+W<ůsο3!dV#AANAB} ߪ̈gCYm}R#8 ģ {`_(8d,:a@/#SzU7ǎΜ%荻//A; ^>4 P  ? 2*6P;?B@/>tW"|fBr@ B@GJewH:AAN>˱~ B/?ɽ 9! BX!l[H$ E=2+BAr,3J!BKL[~Mo#WfX1zk~CcAAA,cF,I?}goq+Xqkp+Ckqkְx%?}`=-qR.d& efBX~ILW5' $wkCiZszkְܫVm?sur{؟]ҮMxRLʊT]yikدHS"dAAD9ezAWk `1o3Wbod߲&@&Do /qZwθy[_ |!j Bj|-̄aLgBj/Ω{mZkN Tj_2[rꯕVB@WAYCn}a M/`RI8 _u&kzP2ioު!," (R_g'75휠sDrf3&175Av>AH> _cy*=*1XV=(4u9;ލb̈́x~[h^5z}eW̻w1ڠ ښ~ 4$! m~q۾4Z0w۽ [UL3!Ka\aү[c&ĽXA;U.ZDkgҟU%a-?O+g";hAA>FA#,ۡKћ]ubmsB_d.o&$ UBr*˱OUtbˆf,_G։kŤ0_'OK'#iAAYSS?xh B<,Rᜐ_zX9!x ~JߢfBؚ;kWvV񺨸zs1N7N7N+'#   ~KbEUWT5q^ {lg\3?㹉mءq-܃{;w+#AAoIM!wUxz>xOA%Br+ok~GbAH_cy!W;vO5=52+BA[J),H/9Q˶vtn*4Q(#ErcAH"1Mj "AA mEkƦ-u9/?N BJow,um=~L$! ("'W?3&[M_ZF< }g̒3rA/މmVjYKf ]s_E`:'_A4^Ll?t15 hK?~u~OϏ \ܐLE%BCXo44~H(BA1UZV>l-xo%4I*̈́yfBLL-w*t39~Y1rv뿓θil;+d9'$Wb/9:&%"}0l*|Cl [Cx~y܈a8= 3 B kШ ͵u3 ^>V>V62Tʚ~($!ras͝@ap# ! ttKMM)iffWU^e}3U^^^^5jTSy y ___}qŵ !qU\W 5֏[K}"ƫ][6ߡMOOGe[o@hS޳^K>}l_>!SCsBnm Okcw7 yЬP]M +X\񰡨-z&Tf\gH*ڮx OjõO|v&gaw=ŷA{l^e>Rh>gqv6Ki!zBF:TQԓLɞ\e;Ŗ˨6EFdFdC8Cxs =Ge?T1CYAAnM ՕIHo&MCBBBBB,,,LMMMMM5==yzvvWVqZi+W ʂʂS| :ΠEYuMx Bzn UF3|!c?׸7gaYV1 *ep R+ZO>'6&%MV}wm͍T4rP-<.R*`?xON{̄qܥf57Vkc~ 3OFCVQL=C{S аp OBBc=3334ҠJZkwEB JAzzzzV,Y[5/~t(_׿^3fp`eʳK^z5,}S%s]luhZg4PӒד;꼛EBL/pW (aOLS=Ǐ5:EƲ?]3ƿP(}b:qb8 $Gv|;{aܭ/ NR#|3!? B]1^wUz|w%zVDT'mww!fC @ON <,\5//prbƉˮ & &iGAK85[ce.꺫m>}Vj.ݍ7F!d"\sr--999J")X81V!}lf&uͪ"rc7J $cB~6t+wU S Q_W[|Y ku^kxS{n&c%sEwOtL)^L/eT Q5)|&XE!?̈́<{;>Q9]#F2BB T`tAʎ;ϼ5>㖏["~RM MWWWWWWAՃUOi"؝;c 3)k0`7uM$=a+Jٞ=B/b9/3!/x΄/'$W *!*䟋ӲeǏSc,̮]#_AEB i4ޕzWj?lxFӽ&}u֭[.u:Iq:s9{ٳgJ63D.[[[[[[;rXF{g= *1D:3Qr,僐F`N}5!1 ģX!!ූk9oɶ /#A%TT1v%ﶽUll|{MDyghhhhhX#Fp ؓ'cO@KJ*:uZKjkkkkk{zzzzz*WwIE'a/80ل\)tߜy\!Ļco9˱~ BH:ExJkbߴla0ea²yMH(BD4|Pfn$~}QwiA5LPPPck^^{-resO2ZI(xדJÖ&M*✐_ B< ̙i7(aboJ̄x3+"^gFFWK9,mNfV0+e7Pܑ%K_yWyWE7dL(UVUdȖ-';'mӷM#*GTy,k5w1Ɏ;I$$d9r8'5 c`cv.'ן4R 8'/,,2bX|SiiiiiibxͲEYj5gVj<'$ܡB3!)^w^_%gB<Ӝp[|mM15*m4 vDAf*~8|gzyyyըQA& *rAy>w @g~~8RM&M]N8nXSZSػY[3q-^b;*X [~Iׯ_ajߓfp5ktڣe7kCL>BϬnSMmí[ʧBǿ)={JH4=n߻}_z>[u?N4Ӵv9̦y0/R! A һUZccժUfosEy-{UgN>uTQ8ڹa*;7~gW߯!f)g,=Ѓ$ ݬp)of[m\QG =F[gUnBǣGslF%%%5kPlɓOF<P( E&YMT9rLc 8ϼO2BOfOŕ,a? ,*<ɵݱ8'$wR%c'\t'uBTe+AN[W2a=?ӥNYe1sF #Cߡ>q†SF*vg /9;:յjӧO߽;ﰳ.K/Kof-kC YYo%yȶȦъ} 0-קO>s0``:_$};tYSO i,b(S7Z2@ BX쳺w޵']]wЫ;Rv-|•s*On>(S7sڛ7k?Y72A՛M* $yFVs $|^AHQ3!^r,gB}! c8Pf[{6e Rȍ"jZ 92Ȓ-6.ڸ+B}oطA>>}'O/Y]z4m&^;vluC'6 !ԗʔ4H2H-I[W?XX6ύ7?ԨS6+Rʰ6͇6nϷ/=vn= FA7ǧ]rx64Rwޚ54{ۮ0|r?F8͊+~$$ZTD*4=fx[oK-5:uUw;o}w[D%{1f%$C[ 6`2R|}30|X$)elnr/(pf] }Xa͖iV ے,X89s VF8(=jӓ/ѱ1ӎێ[j=z5Y hRIv#A)e/?>{XZa-c(ӇοXc^I$PW$<k=f .k+HHFQc2ebWjU?JO8nkkI8H8?MsOҨL!#Lذӫ։ʌL[l!^FH))kz%l]u vS_p?ߚ5ԈnSMmc{'NX7fRg|#{!Bޯ{N>N_+Z̦gۮު{ݕlZÔSnب|bjۤ.on1ڷ.tdEE~I>}Z{bsE$RwcԥQV3g0BjQ~IsUZί:owv7akքSM7Ud2_F_}mTxyP( Dԉa#b3e91c7[x oٯ[x_Pשu[Hj5s%6jݿ AHs?Ӊ?5x/iKH ӸO>}Os/O3O3O3O/OBU|bi7-`0;6U$ov]+, ^WʴŦBPM\8h>m2}`?)\`×6[lZl p¯6:T?b#-}0F:tF,|hʯ5ݚj+f9Ϳ7+Vnn&[⍋鹧`gm4cY4Qj7`Z0xlUA]Ia݇5-b'ofUGOrSsn?3Dg   ՍQ7=]ӣQ3RZ?fBT]_ƭ̊{dZw;tcww+:!Cx|.<߹~ZR;s'6*ⓧVj`,:EE3dM|&{|Xڱ ? :+7W\K6K6Ka3l&74SݦW,^l=H-; BKMpR!n֝^wzѻw.QQF>Q '.쳓??[oge^&#"#"<4SZžmRw3gRf7o4 E/_TxcrMa0,x4mJwtZ8hΌ;3^Ξb$Hʵt\jJ888괮ӺN;wܹsGXOOOOOO@@:onQX~ r[[ BDQ]˱~ B@ЅpBhV EԢnߺ}]022*ޜ8u}C%;=t```@9IҨLm`]Ւ ?[0w?g}mEv [ɿEfqq^PjmmW^9a{{rx81Jæ T=ɯW:6:EL#9V/5m(;iwTȀ . K>6w5uM'(˛@7hMT7o!YX5YܷeUêi"Kp {f콳a: TjWCU*ڃkqz...\k`<yvu& D+^[*Л`q;!?eoi )vR~=I]A"TS&i_7W(H( D DncRbj^^Ψ: T^_W>v@6````B0s0K+=[0P =#pG0'ppgd U A5Pj9j X+YjA-ܑ;X;xkOFQ_Cm 6Pj:uboC4Mu{{iuuTBXlzP r_)U}R>p< \dT9 x]xrHA$lHȂHL _!EJyuu oeoe_B BB kxϔi):N6ۚ[{o=-; Pp#_W}B! ! R!!]IIqsqo ҺUV^u/%xT^^qm$Yv`Q}ϯw__U&jzBgϞ={LEEEK,r-WxTQGz9'Xtj,ZSOe-M$Mo"z)Q*^Q_ KJLi&vqV#nJ2SnNv[Iɾw&Fuq6Pm@hH(UUWq:jiH^uA@d +2 RJapctdFC0@q4 N)(ZjʖMZXU; BUPQ-T 9'xB5oO)ƨ138 `vPCcڣP:A'hj l9FިZh-;h*BW|!@\=TJPPǚ5/]ŕK- 2vvv\SJ0]-@<}AlTiW>n" B(B hAq]:7kz ;6f=ŧ)|B nE7Q|nx{#TgwƓ}VBUX2>fkvpNC <'+ f--7,tZiyn<7G t'\<bXϿ{aN{hCK9kTa5CHq.D3n7embXtMWS}~ B}X+?9{Tj-a^"Y<Zhڃ8mt-@/KXljW~z tR#(U0E0E@qqq ho.++A+[5@UQU8ՠZ @5jBM,I+z{37׿8OIÜ@'d{6sG !`73 ",CT78'rs}F&Mқ$eԒh/Vtzc{)[ԥF;Dwe_+ =L';hH(&Mvf¨s9e"Q$C!t!;(KEYnE)ҰJì :A,{ց.0D'Q}k+k+iH-Z5ѳII څn۰ TX ŕ   H`tn n &$ 'gѢqWoar lѹ [@<^xuI>{| 3y-z- yѝrOtbbodKmN{7Zj'* $'=p*Sn~Gw;vfC6n^j,0m2>pP`IN c* Fp,&&e*7krc -,bX nҠTƈVVp~~N }緖@[y+Sg!--ϯh,h~_^뜜  #B(B$DB$ű8!!R oR938sɻYBոvj1l,J#}7'D,X͊ c.0I"ݚ"KKKU []nVLFW/{K."a߹[U#)t%=&WM\EN lwW]g𳄏 :[yu5։/'#^L|4<bLf9"5e?H(a6̆M,:XN Kd j1nB n*88;9;$Z,D7.0FB{n}n}9њ5CN!Jo-pk5׌G0Ua4 OSnmd &#6:lVyt;?qڥB]$$df_%y6mx?F#s-Z† K5Gj3c6F߄W|?ύR?E'E'&%/%|`aa^&rxgҚgjqR'u(k\$v?疷ٶ|lӚW:M6!i.B`i7Lu?W燞z$< OX Ÿpγdffu%J֕j27ߠ~ ֐ QIQIQIvC lllK҇и={fӏ)ݳ,%#G-^8'Ȣ![כ0@>%T73#&)8로_PbלܡAp7a"qsji>ꢺ` &T腱m[EV2NI{2^u:'{aSv&H_ }5}PD[Une۱Ƌ/1Ԁ ͠ kC !דדdGN'ʋsaQn=pK'K` @:H=М RSRYBo6xYi~/+WdI0 2!S/GVxN<'#vdԨQU?Y|f]8w&.vvs4Ho:vW%''8{)Q%,J}_wVj l(UhsUZb΍,X1xG2( ]Scv5fKB$!'Ϟ<{ Ƨ[ 8%pJiu՝`K=?M#q1'PXHNJB(cJD[\o^`+*S?ED?NT0t۷: F4hR~Ol܆0Ωééc]K555W}VV[e%/h ;hH(#ՑzMTYrmm[*C{M3_6o>XaÆmuy&ڽ7#s3oP_%V2=YlHNNpvۭA+B+Bwf55פ722yh,HK"hItZ.$DKDKDK>JhZyTUAfz3Y @ *ά80"X&c%|^R *gճ|ۘ;y"Y<7c.64wcz|ZXJ n& ',Ӫ-]/BSE===6SOz1+Zh=S ېIdӖlYeϴӇNUUjëuekN] rppҟc{0`ԢmϷ=m]]Yv .ּ[`\zLzLJ-Us*|'_/|B sRxyÍ 7Z"Kdwccc5ki7|^yi֧=()p|(-:u*زbK00!9^R^ݽXrcɍWη:juۃ^dOOz4iWKΪU3ӱӧL2gg?zGiG ~{~{n:eÒ9as¶@C~欮Ԃ+f83k`VyѢLN8-rQ%{<;G]G]eӷYKp+^Q*BE5F-붬v š8T}\}y Uy*UYad7ԜPx$$&Ymͷ^ <xFHHY)+n7kOvcߍ}qjǝ:YY2[YvvvW]wJ[`;6ߣPm~ (S>222M#)N; :q R4 v J*s7oN ^UTIE h ߼F+u!9'@V p[.ZRsa.t.0.\VujO i Gt. ӅDG =[%J]Om't鸻@hYF:u_" ^ȓǞ7rSղVM@_}XX(\s<<ˢ/'V^Z쟣rНon=]Ls[kG"> Gw]RRI0zP8{<$9$:[^Q^QQ]cd0p]v :LZi SwǛo~*cU*eʻ888釴rttt222)/]#]#]ۗo_ d +˻G#%גkrT7*ިL-}!be蝞RbzJP&,wˍ&p33է (ѧY/Ͽ7)LՇ+ӓNOZ^&Gf{K~l6GVYyRA4X{cEEJUH4&iLJm4op搦kkkLDq8Q"D7Qov3_3_"R~xȬȬoKu;ӝi7nkE'E'&RbJʔ<1[דig[={MPf(}(߯Kݖky" ~l5N6{6o'^..M7A}cܽe ')?rȥ]'"//fo ݵݴݴݜ9UsR*RITE>}___)~o"D;4yW"fEl}_$N6UwRIUB6lPm Q*VԵteO )?\j3t6]xCL=??0wiߥ}?7rʼn+݀$KrCgn/vUOQ&p*=o}i8JPmýƖ/|u{T?[ũ~_;vzxxx^xq-Ֆj[E^-ʲU/VX2+JҀK-A.H(BSwT척>}5ՠ튷+O;poI Qj™-ϴ:35UAv6ugtan3,{$Ș11wIjЬoo#Rd ~?wZi^}~9dg1߬/// hSק)) hdԮ4ESot;vК2eʔ)[;6؜ó,Y-ee]v;_m쬱Vu gr?t2L2tA[A[A[Mr=}MU| >c?e A(*VXݲuÞ {|Ҁg!01cUn\rm/[Y_ёH//dq6q6IS^9r y=zөwRdwY+§MP iW<^.[$[$/pe}0V& c$75000xiॆGA Er/fp{tHY/_0}yn ;/ |jeI368՘1Q+7$)#'cփR{@ǔ]aw;̃ovb!!8ߝP䱚:֢A-^oW /eKTSӷ4 lebnp/ `п hs`dB&R~;Z5ڇ7mB {^tĢE6샋kamη'8ɐ p jBMPImWqʹ< l$2yf<3YĚ50@#`7uww /A"x 7x9]C8B-\cSK6Zh~{~{nZٴylk7ɀ2 ^M߉:kԄ ʾuz37}玞-aX2}oГ}w߭Dv11z.]^h',cM\2zW^7 /gg~NCxQ7W"6nmPgYMg&&&6wlQ<;۾o~ EB7PJ+/pPX)2*ʟF;toNjlWَX:?z| 6쿊}PC{uj˗=5@<\[RoIZ.b+P,?WIK3t2t=[6;񬧥 P],c_BWZUkUu >6j885Me#4!4!4! @'OЋՋ+cLyzZZZJ~#qG⎘1cvky$!~Fv/޽xxo}߬D\o:hvc>pm@o -5=b"}_H%.'XNi%Ogs/%s9q22ڤwnYfg/hpu&ic7nmʠAS@߁mϞM}6&t Q<{ 34w%dAdSB!e. 2>d@0cMw ErPDJ"%F=mI[~$ŲYڏ u4hrrdNm֯[-VeÖ_?3p{{_R>iϥz N'H L~FaFazZƶΡ{{s vO6V%WvIvI^!khqCr=A{ ~#ߦ88eX(%oV_\WBBwM|M| BB,VuR7oUN;0],efleÛn&&ԋ7Q7czlg..C7^{?TC5<[)evǷj!(H(BAA K*IIb$FҫYY sA#IRh<}OgscbE +:Ρ Q>Ŕ^<<T,e1۰>d4 DF4MӔ׈kđ±±ݼZPj ƭq'v 2@-QK?KE'FR#Z22Y f>i>Bu::U'דcOq wsOsOs5XC.U w4{ҦҦEELڲyh*LWfzU<]YY6FO9 BEdVDӯ^Ү][-jXW"|[x#W#Wt+hu(c eH}*llbB1ks'վ}O0Ő6>uׂ_T@%%^A䞗WSWgLmq0kT(Q4GÊI=4i_.9Q(UěɲpY\RP-W-W2`Z`2=mO3g/ʸR JsXV~Cn(ši"$BN1B, ..B~]}g}gm[~:?(J;SU͊)M(SDU* BP `u <({C 1SxyTAu˄˄D4MTӐPD3ۋ8>>NeHYKQF>& qg̬2)eRFoO99זMZ+b9}d yjJ2gϮQF;;[Ǽy#zFr"$C'C'[+Կ34,Z֠&&D~)̐J"bXa0J} --MQҫ&IIrf>i9-ŀAYm GQC4 B(W2erzҋfA ޓɌd%K]ɐ UI{H@҅ /^t3=gz> j*zi1yye˛:YuD2f_p:NǶ N N)u;v:CN3UGM-[B(R  U;U;T"F#**_-[@u- t (y͐ ɐ29erFYE560:'B"3262{$(#~~~"CpK$_%_%_  #`PKߊLgˇʇʇBo /?O AAH(0 &+QZ=Ce T#`-I+R_e+j8ewwk5(k5V||M^^&b^3|,JkJkĤd$?,@;Ў"F]{^n^a3 ((s4@2WQݨn[={ykxkNVVFu@\lmp'auS=|s /OߢoQΆy $d @xxmsf^E+WFHr͕,MH2*S+8q:ss8Thq/3^fͮE|Ȃ|21s02jP5%UX~d1Y|||2y<?}>C),++Ejjjܮܮܮ9AKdVDh]+?9=IGPhpUED$P^^Cϡo0]aXQ*4c `.;N|ddߴ9R'XܼBDAhh-:NA‹U6__P} }>EE]Og-+^MTիϓ/ `_!4o/o/wqw ^b6i+-{hfmfm$HP+sxtQƮ]Yڌ6#8#a$V{a/wZʙvH i;M{VHO-Q9b݄YtAk`` oWRFRFka-\s 6aHm*Q z*4*?Un\=Wb/Ǝc //["["[BEST4FȺبببU*|)OVR+ùùÕ)O5$Qp)tJAJ=J.ËϞ+Jn(ӊq#FzP8 ,pDb[ֿt8pALGnb5Ž-a0=@TZ 7ZoW|>{X 0z qNqNQOe)\'7䅼PcS$̂Y5]v;OcŸq_}Oa~iuZD-BbFWB22 wxx On-VHuNެMkӂ B~f|~HݤiAҰa3 W 8Әi /z]y67<:ʄ(6 s X3wpg--mQ<ۂI>I>;}}9  ?\&dg/ У5Jy:\^^^0TE"6R͐ BP/ EhGr $},YL\įEll?ddm6WpO㩐+xKucQӒmV̯_E R"S{^~^#Aڃ,ChooEϦgS7ݫ,,?lIlf%J'll|wƲe` E-Bu,t,Ed^!~"^$^$-0A\#tA-A-$Mߎ>WyH+5ޒ(?l¿mVx:Cu rwswsFo6zFՂPQMI`2wqY6R2E2Ej884{{02l S ۞۞SU{SJ~p8v ],R,-|||w2w2w2؀ بF===Z L( ݁DI`J;TA;ƜBSF]p/].Srrt5"8ph+?ϟۛ{{sjMF,X Bu"E-+g? m-LgɳoeTzTzTqe\6+D()7@M)Sk },ΪTUTK}̹eOdOdO;+8 }}}]R0#rME888Raw T m"m"} `% l lt}`FFekZk@]] '1$XXBSSISF]4F02=9=9+\zԤ>S&m6=ʤ2nI$eI/PRt]E}싚gH]d/e_Vx$|88ό9.2F uuץ۔p>GՕ)U4\`y((PAMg˴2@a ?׏׏3ƲOyuy8#~f}=&ICJPlCg7g7Hs9:U@W|N)#*8 Gx!,yrU84Vz >Xv;c>z=9sZ(Ro\@S1cPDf qrrh )CcHĢ6G44sssB]A7@-Ӗwݒsv?IBIDATO^F\؜?X)o.fl*rKd2kyi ))6lf6~%5ˊبx$0FGI^$Yqe*&6 =9]9]iQMOJPܻ@%SɔN;vBι]+A///θ3\Ľj@5t0',2!S~O~O~uRA'IFN 9iFğL,="J@=C@sEc,QOKa)??.y,y,&o'o0+yה,,o^J'a'섳bFH/dVB2'2tA+x<Z^ ^ +tE'B L$< +ӻWT.(ϕ,,999777!! [a+-؅U-f q2\Pn֠5<ϊ kȬ dd$O$Od=r~kQr}MЙ!|, K$A2Kt.lz6. 𕚉*Uvn(bnjCmqDREE "vB+^O׃ AfET1nx382@ @zZ`L 30C038a4*@dr8r ?yt%o`JCUΝ9x^s?ʷu+X=X5#@^ eS3șҧ=Tu:uIt b].۸۹78/a0| ƃkL}>0: ,r0TzCvꩱC?pYJJE e'q99i1-  '~%o%7ʔ2E&6MA%R*p]FTm6s9cϥ~a`a2c'{ KΖ[g `KGt4 BBȬ Ӥd%%eEFgEsQR::Ytt,tApHANGB#u܍l 쟼::Z\ |i4MA9/k/?i4Yw$QD-p*p*pչQp^*'c`t<\a<ݙXFefZe9ntt,Jn*7U$"vc}>ʀE\K_IDlbbWAexx縳Ji*7Mo[psppzjjr>*S $I1ot18a9,9AHaI E(?ʏ(AӃ$? ET ӓ{H-L|(TA6 Y B/O->/===™ɞed@X>&o[V&]u.7?9˙إwl^^,^+ BΓΓPJ耐7o=qd\ڟdkO3EKKѓyRJvcXe!^)^)QD(]!mH*RIAoe2ys!=L;Lpn$ ,YR" H@Λ͛D+\S>_>_1MFF8oOJvQ\~DEA Ԇ5h+ 8!HB=_-Ul0EgQ;G@?[ a$z"J6Fx@T}x/ #sw؀  t*:CgCxqN` 4=ao{x-|''cf0ϒrx gt߳~|M7+ hIu|SN>\QLRLRUh)^,eG١~uH[h T[-SSPA&K-*߿fg( EP"JDy>#yX`zGGYt|,yutZr-9K;9O0@XlɢnR7@}@ Pf2U"(P?0p#B]R6|-)(P]TWµd>Aȏ@1\1iH[(L 2igڙelbVB[ڑv?GF2mGLF /⳸sT`PzSxAFǗi*>\k"WR;Ne euBP;n9f, m > *'k낾S?I?B#׸D&I-xP\ځv|p|z\pSwmplx鄜bp{wŝs{Sk99oB1>?i+ڊ̓d_}.עx5t O)8;"E5E5# 9e7f%[#*$՟OE0uhԿ_"ZBKT6.](ŢX4Gv*oKuS @ӣ!?Yyt__CwhZ}10VB{hs,}|Mg&77S*|bb\Pj5xIܿA>A^Pfff-%$LxcZP 2O%o H9zM 7֡Sn70D/5uo!"*`x 9U2J-7Q(GړJ po@R35j:5T*܇NL'&RH^xI'ǓkHW37QLSFSp 0)L HV$+ XMݦЮ+P d d 6 6r\iUBUIA r_5烆|/׀k@TmD3pV.e8InPs7f(0:Olj=hy0,%$z}GC* :TWH*}>:HuDKy(*+*+L2X@u\ _~+hƭqk_W/EQmT]GupWp`GB0{؞9d[{j`Ĺ@ ȀCx37yyL:\*\[Y!XBx\g--ZGTSF].)"j|E}ZN`x]| wb(0Ӕi|S4HBcx'މ**2E7ʦ}i_ꁪ{mq0L&tjmi88 @ZH  T)s\ W+v ;#88h 7PM'1eLK N`tqJSslRE%E%SuԟiHsn8 '$ Cah1`F;gK Ԇ"*^ `1..9}>D&T/ mv` Ӌ) U0w`<0\'Qt2L5mMUVZz-xc)o)oVJ@Ӌ|qs[xq*A1t uR/))1Ela"*/+.@"Fz&:jS=(EU:`Lʧ$ -Ђf L _Oƍp#d<"ۃAGP=.= fVg{)0jt5j^1ࢂ0lM}ϐ)pvÄ2{^dqwZcpjlmhH0jҡ!C`lC) H0Ic"q ]#Ė<q8s<}_<|וǜs4\1ά3l+۲9G|Rd?wTfj>۹soٜzn͟zW39's232#7vW9t G2TƗcy'6,k,/Q⺸.K".|tlqs-ed줓i/W­53v{ɘ˪=ɑ?̛y>[O;ӝ|wM_3<4\h<dzsOE{=[w?=Dy"KsWsSn?Gr$y2P_0"w d @9W:-Q>:)o͙Z噟Y;2-Gs4'Fꆺ!/睼C=C't26{sKnɴ+1ў]f82sȯ/q${yyէSQ2ty˘Yٛs}neVf]]SdCO6W:4wɬGsȄLH_NTPhvfgeS6Z]\3\W[`>s9#5?󳦮볥Go+eq̃FdN)Vr8s\___ >__| /___/\ \ \/ \/ \/ \/ \_/ Copyright (C) 2016 Ingo Berg All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef MUP_COMPAT_H #define MUP_COMPAT_H // This file contains code to maintain backwards compatibility with older compilers. // Note: This does not work on windows since the lazy bums at microsoft are unable to assign a macro value properly and // don't give a shit in general: // // https ://connect.microsoft.com/VisualStudio/feedback/details/763051/a-value-of-predefined-macro-cplusplus-is-still-199711l // // I'll hereby officially announce that i also stopped giving a shit whether this library runs on anything older then VS2013. This // is not a bug, please refrein from reporting it. Seriousely, report it to Microsoft. #if !defined(_MSC_VER) && __cplusplus <= 199711L // Warning: If you activate this in a project on windows all hell will break loose and Satan himself will come out of hell to eat // your soul whilst reciting verses from the Microsoft MFC programming manual. #define override #define unique_ptr auto_ptr #define nullptr NULL #endif #endif muparserx-4.0.11/parser/mpDefines.h000066400000000000000000000075231414723276500172240ustar00rootroot00000000000000#ifndef MUP_DEFINES_H #define MUP_DEFINES_H /** \file \brief A file containing macros used by muParserX
               __________                                 ____  ___
    _____  __ _\______   \_____ _______  ______ __________\   \/  /
   /     \|  |  \     ___/\__  \\_  __ \/  ___// __ \_  __ \     / 
  |  Y Y  \  |  /    |     / __ \|  | \/\___ \\  ___/|  | \/     \ 
  |__|_|  /____/|____|    (____  /__|  /____  >\___  >__| /___/\  \
        \/                     \/           \/     \/           \_/
  Copyright (C) 2021 Ingo Berg, et. al.
  All rights reserved.

  Redistribution and use in source and binary forms, with or without 
  modification, are permitted provided that the following conditions are met:

   * Redistributions of source code must retain the above copyright notice, 
     this list of conditions and the following disclaimer.
   * Redistributions in binary form must reproduce the above copyright notice, 
     this list of conditions and the following disclaimer in the documentation 
     and/or other materials provided with the distribution.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
  POSSIBILITY OF SUCH DAMAGE.
*/ #include #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("4.0.11 (2021-11-23)") /** \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 Floating point type used by the parser. */ #define MUP_FLOAT_TYPE double #define MUP_INT_TYPE int64_t /** \brief Verifies whether a given condition is met. If the condition is not met an exception is thrown otherwise nothing happens. This macro is used for implementing asserts. Unlike MUP_ASSERT, MUP_VERIFY will not be removed in release builds. */ #define MUP_VERIFY(COND) \ if (!(COND)) \ { \ stringstream_type ss; \ ss << _T("Assertion \"") _T(#COND) _T("\" failed: ") \ << __FILE__ << _T(" line ") \ << __LINE__ << _T("."); \ throw ParserError( ss.str() ); \ } #if defined(_DEBUG) #define MUP_TOK_CAST(TYPE, POINTER) dynamic_cast(POINTER); /** \brief Debug macro to force an abortion of the programm with a certain message. */ #define MUP_FAIL(MSG) \ bool MSG=false; \ assert(MSG); #define MUP_LEAKAGE_REPORT #else #define MUP_FAIL(MSG) #define MUP_TOK_CAST(TYPE, POINTER) static_cast(POINTER); #endif #endif muparserx-4.0.11/parser/mpError.cpp000066400000000000000000000147711414723276500172760ustar00rootroot00000000000000/* __________ ____ ___ _____ __ _\______ \_____ _______ ______ __________\ \/ / / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ / | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \ \/ \/ \/ \/ \_/ Copyright (C) 2016 Ingo Berg All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "mpError.h" #include "mpIToken.h" #include "mpParserMessageProvider.h" MUP_NAMESPACE_START std::unique_ptr ParserErrorMsg::m_pInstance; const ParserMessageProviderBase& ParserErrorMsg::Instance() { if (!m_pInstance.get()) { m_pInstance.reset(new ParserMessageProviderEnglish); m_pInstance->Init(); } return *m_pInstance; } void ParserErrorMsg::Reset(ParserMessageProviderBase* pProvider) { if (pProvider != nullptr) { m_pInstance.reset(pProvider); m_pInstance->Init(); } } string_type ParserErrorMsg::GetErrorMsg(EErrorCodes eError) const { if (!m_pInstance.get()) return string_type(); else return m_pInstance->GetErrorMsg(eError); } ParserErrorMsg::~ParserErrorMsg() {} ParserErrorMsg::ParserErrorMsg() {} //--------------------------------------------------------------------------- // // 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, EErrorCodes ec) :m_Err() ,m_sMsg(sMsg) ,m_ErrMsg(ParserErrorMsg::Instance()) { m_Err.Errc = ec; } ParserError::ParserError(const ErrorContext& a_Err) :m_Err(a_Err) , m_sMsg() , m_ErrMsg(ParserErrorMsg::Instance()) { m_sMsg = m_ErrMsg.GetErrorMsg(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 muparserx-4.0.11/parser/mpError.h000066400000000000000000000127531414723276500167410ustar00rootroot00000000000000/* __________ ____ ___ _____ __ _\______ \_____ _______ ______ __________\ \/ / / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ / | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \ \/ \/ \/ \/ \_/ Copyright (C) 2016, Ingo Berg All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef MUP_ERROR_H #define MUP_ERROR_H #include #include #include #include #include #include #include "mpTypes.h" #include "mpParserMessageProvider.h" MUP_NAMESPACE_START //--------------------------------------------------------------------------------------------- class ParserErrorMsg { public: ~ParserErrorMsg(); static const ParserMessageProviderBase& Instance(); static void Reset(ParserMessageProviderBase *pProvider); string_type GetErrorMsg(EErrorCodes eError) const; private: static std::unique_ptr m_pInstance; 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 actually found. char_type Type2; ///> For type conflicts only! This is the type that was expected. 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 IngecMISSINGo 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, EErrorCodes ec = ecUNDEFINED); 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 ParserMessageProviderBase &m_ErrMsg; }; } // namespace mu #endif muparserx-4.0.11/parser/mpFuncCmplx.cpp000066400000000000000000000477501414723276500201070ustar00rootroot00000000000000/** \file \brief Definition of functions for complex valued operations.
               __________                                 ____  ___
    _____  __ _\______   \_____ _______  ______ __________\   \/  /
   /     \|  |  \     ___/\__  \\_  __ \/  ___// __ \_  __ \     / 
  |  Y Y  \  |  /    |     / __ \|  | \/\___ \\  ___/|  | \/     \ 
  |__|_|  /____/|____|    (____  /__|  /____  >\___  >__| /___/\  \
        \/                     \/           \/     \/           \_/
                                       Copyright (C) 2016 Ingo Berg
                                       All rights reserved.

  muParserX - A C++ math parser library with array and string support
  Copyright (c) 2016, Ingo Berg
  All rights reserved.

  Redistribution and use in source and binary forms, with or without 
  modification, are permitted provided that the following conditions are met:

   * Redistributions of source code must retain the above copyright notice, 
     this list of conditions and the following disclaimer.
   * Redistributions in binary form must reproduce the above copyright notice, 
     this list of conditions and the following disclaimer in the documentation 
     and/or other materials provided with the distribution.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
  POSSIBILITY OF SUCH DAMAGE.
*/ #include "mpFuncCmplx.h" //--- Standard includes ---------------------------------------------------- #include #include #include #include //--- Parser framework ----------------------------------------------------- #include "mpValue.h" #include "mpError.h" MUP_NAMESPACE_START //----------------------------------------------------------------------- // // class FunCmplxReal // //----------------------------------------------------------------------- FunCmplxReal::FunCmplxReal() :ICallback(cmFUNC, _T("real"), 1) {} //----------------------------------------------------------------------- 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 = std::cos(a_pArg[0]->GetFloat()); } else { cmplx_type v(a_pArg[0]->GetFloat(), a_pArg[0]->GetImag()); *ret = std::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 = std::sin(a_pArg[0]->GetFloat()); } else { cmplx_type v(a_pArg[0]->GetFloat(), a_pArg[0]->GetImag()); *ret = std::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 = std::tan(a_pArg[0]->GetFloat()); } else { cmplx_type v(a_pArg[0]->GetFloat(), a_pArg[0]->GetImag()); *ret = std::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 = log(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 v(a_pArg[0]->GetFloat(), a_pArg[0]->GetImag()); *ret = std::log(v) * (float_type)1.0/std::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); } //----------------------------------------------------------------------- // // class FunCmplxPow // //----------------------------------------------------------------------- FunCmplxPow::FunCmplxPow() :ICallback(cmFUNC, _T("pow"), 2) {} //----------------------------------------------------------------------- void FunCmplxPow::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int) { *ret = std::pow(a_pArg[0]->GetComplex(), a_pArg[1]->GetComplex()); } //----------------------------------------------------------------------- const char_type* FunCmplxPow::GetDesc() const { return _T("pox(x, y) - Raise x to the power of y."); } //----------------------------------------------------------------------- IToken* FunCmplxPow::Clone() const { return new FunCmplxPow(*this); } MUP_NAMESPACE_END muparserx-4.0.11/parser/mpFuncCmplx.h000066400000000000000000000217071414723276500175460ustar00rootroot00000000000000/** \file \brief Definition of functions for complex valued operations.
			   __________                                 ____  ___
	_____  __ _\______   \_____ _______  ______ __________\   \/  /
   /     \|  |  \     ___/\__  \\_  __ \/  ___// __ \_  __ \     /
  |  Y Y  \  |  /    |     / __ \|  | \/\___ \\  ___/|  | \/     \
  |__|_|  /____/|____|    (____  /__|  /____  >\___  >__| /___/\  \
		\/                     \/           \/     \/           \_/
									   Copyright (C) 2016 Ingo Berg
									   All rights reserved.

  muParserX - A C++ math parser library with array and string support
  Copyright (c) 2016, Ingo Berg
  All rights reserved.

  Redistribution and use in source and binary forms, with or without
  modification, are permitted provided that the following conditions are met:

   * Redistributions of source code must retain the above copyright notice,
	 this list of conditions and the following disclaimer.
   * Redistributions in binary form must reproduce the above copyright notice,
	 this list of conditions and the following disclaimer in the documentation
	 and/or other materials provided with the distribution.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  POSSIBILITY OF SUCH DAMAGE.
*/ #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(); virtual ~FunCmplxReal(); virtual void Eval(ptr_val_type& ret, const ptr_val_type* a_pArg, int a_iArgc) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; //----------------------------------------------------------------------- /** \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) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; //----------------------------------------------------------------------- /** \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) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; //----------------------------------------------------------------------- /** \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) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; //----------------------------------------------------------------------- /** \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) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; //----------------------------------------------------------------------- class FunCmplxCos : public ICallback { public: FunCmplxCos(); virtual void Eval(ptr_val_type& ret, const ptr_val_type* a_pArg, int a_iArgc) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; //----------------------------------------------------------------------- class FunCmplxSin : public ICallback { public: FunCmplxSin(); virtual void Eval(ptr_val_type& ret, const ptr_val_type* a_pArg, int a_iArgc) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; //----------------------------------------------------------------------- class FunCmplxCosH : public ICallback { public: FunCmplxCosH(); virtual void Eval(ptr_val_type& ret, const ptr_val_type* a_pArg, int a_iArgc) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; //----------------------------------------------------------------------- class FunCmplxSinH : public ICallback { public: FunCmplxSinH(); virtual void Eval(ptr_val_type& ret, const ptr_val_type* a_pArg, int a_iArgc) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; //----------------------------------------------------------------------- class FunCmplxTan : public ICallback { public: FunCmplxTan(); virtual void Eval(ptr_val_type& ret, const ptr_val_type* a_pArg, int a_iArgc) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; //----------------------------------------------------------------------- class FunCmplxTanH : public ICallback { public: FunCmplxTanH(); virtual void Eval(ptr_val_type& ret, const ptr_val_type* a_pArg, int a_iArgc) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; //----------------------------------------------------------------------- class FunCmplxSqrt : public ICallback { public: FunCmplxSqrt(); virtual void Eval(ptr_val_type& ret, const ptr_val_type* a_pArg, int a_iArgc) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; //----------------------------------------------------------------------- class FunCmplxExp : public ICallback { public: FunCmplxExp(); virtual void Eval(ptr_val_type& ret, const ptr_val_type* a_pArg, int a_iArgc) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; //----------------------------------------------------------------------- class FunCmplxLn : public ICallback { public: FunCmplxLn(); virtual void Eval(ptr_val_type& ret, const ptr_val_type* a_pArg, int a_iArgc) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; //----------------------------------------------------------------------- class FunCmplxLog : public ICallback { public: FunCmplxLog(); virtual void Eval(ptr_val_type& ret, const ptr_val_type* a_pArg, int a_iArgc) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; //----------------------------------------------------------------------- class FunCmplxLog10 : public ICallback { public: FunCmplxLog10(); virtual void Eval(ptr_val_type& ret, const ptr_val_type* a_pArg, int a_iArgc) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; //----------------------------------------------------------------------- class FunCmplxLog2 : public ICallback { public: FunCmplxLog2(); virtual void Eval(ptr_val_type& ret, const ptr_val_type* a_pArg, int a_iArgc) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; //----------------------------------------------------------------------- class FunCmplxAbs : public ICallback { public: FunCmplxAbs(); virtual void Eval(ptr_val_type& ret, const ptr_val_type* a_pArg, int a_iArgc) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; //----------------------------------------------------------------------- class FunCmplxPow : public ICallback { public: FunCmplxPow(); virtual void Eval(ptr_val_type& ret, const ptr_val_type* a_pArg, int a_iArgc) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; } // namespace mu #endif muparserx-4.0.11/parser/mpFuncCommon.cpp000066400000000000000000000214241414723276500202420ustar00rootroot00000000000000/* __________ ____ ___ _____ __ _\______ \_____ _______ ______ __________\ \/ / / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ / | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \ \/ \/ \/ \/ \_/ Copyright (C) 2016 Ingo Berg All rights reserved. muParserX - A C++ math parser library with array and string support Copyright (c) 2016, Ingo Berg All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "mpFuncCommon.h" #include #include #include #include "mpValue.h" #include "mpParserBase.h" MUP_NAMESPACE_START //------------------------------------------------------------------------------ // // FunParserID // //------------------------------------------------------------------------------ FunParserID::FunParserID() :ICallback(cmFUNC, _T("parserid"), 0) {} //------------------------------------------------------------------------------ void FunParserID::Eval(ptr_val_type &ret, const ptr_val_type * /*a_pArg*/, int /*a_iArgc*/) { string_type sVer = _T("muParserX V") + GetParent()->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) { if (a_iArgc < 1) throw ParserError(ErrorContext(ecTOO_FEW_PARAMS, GetExprPos(), GetIdent())); float_type max(-1e30), val(0); for (int i=0; iGetType()) { case 'f': 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) { if (a_iArgc < 1) throw ParserError(ErrorContext(ecTOO_FEW_PARAMS, GetExprPos(), GetIdent())); float_type min(1e30), val(min); for (int i=0; iGetType()) { 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) { if (a_iArgc < 1) throw ParserError(ErrorContext(ecTOO_FEW_PARAMS, GetExprPos(), GetIdent())); float_type sum(0); for (int i=0; iGetType()) { 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 = (float_type)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 muparserx-4.0.11/parser/mpFuncCommon.h000066400000000000000000000106741414723276500177140ustar00rootroot00000000000000/* __________ ____ ___ _____ __ _\______ \_____ _______ ______ __________\ \/ / / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ / | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \ \/ \/ \/ \/ \_/ Copyright (C) 2016 Ingo Berg All rights reserved. muParserX - A C++ math parser library with array and string support Copyright (c) 2016, Ingo Berg All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #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) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; // 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) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; // 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) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; // 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) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; // 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) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; // class FunSizeOf MUP_NAMESPACE_END #endif muparserx-4.0.11/parser/mpFuncMatrix.cpp000066400000000000000000000171041414723276500202560ustar00rootroot00000000000000/** \file \brief Definition of functions for complex valued operations.
               __________                                 ____  ___
    _____  __ _\______   \_____ _______  ______ __________\   \/  /
    /     \|  |  \     ___/\__  \\_  __ \/  ___// __ \_  __ \     /
    |  Y Y  \  |  /    |     / __ \|  | \/\___ \\  ___/|  | \/     \
    |__|_|  /____/|____|    (____  /__|  /____  >\___  >__| /___/\  \
          \/                     \/           \/     \/           \_/

    muParserX - A C++ math parser library with array and string support
    Copyright (c) 2016, Ingo Berg
    All rights reserved.

    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice,
    this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright notice,
    this list of conditions and the following disclaimer in the documentation
    and/or other materials provided with the distribution.

    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
    IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
    INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
    NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
    WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    POSSIBILITY OF SUCH DAMAGE.
    
*/ #include "mpFuncMatrix.h" //--- Standard includes ---------------------------------------------------- #include #include #include #include //--- Parser framework ----------------------------------------------------- #include "mpValue.h" #include "mpError.h" MUP_NAMESPACE_START //----------------------------------------------------------------------- // // class FunMatrixOnes // //----------------------------------------------------------------------- FunMatrixOnes::FunMatrixOnes() :ICallback(cmFUNC, _T("ones"), -1) {} //----------------------------------------------------------------------- FunMatrixOnes::~FunMatrixOnes() {} //----------------------------------------------------------------------- void FunMatrixOnes::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int argc) { if (argc < 1 || argc>2) { ErrorContext err; err.Errc = ecINVALID_NUMBER_OF_PARAMETERS; err.Arg = argc; err.Ident = GetIdent(); throw ParserError(err); } int_type m = a_pArg[0]->GetInteger(), n = (argc == 1) ? m : a_pArg[1]->GetInteger(); if (m == n && n == 1) { *ret = 1.0; // unboxing of 1x1 matrices } else { *ret = matrix_type(m, n, 1.0); } } //----------------------------------------------------------------------- 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); } //----------------------------------------------------------------------- // // class FunMatrixZeros // //----------------------------------------------------------------------- FunMatrixZeros::FunMatrixZeros() :ICallback(cmFUNC, _T("zeros"), -1) {} //----------------------------------------------------------------------- FunMatrixZeros::~FunMatrixZeros() {} //----------------------------------------------------------------------- void FunMatrixZeros::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int argc) { if (argc < 1 || argc>2) { ErrorContext err; err.Errc = ecINVALID_NUMBER_OF_PARAMETERS; err.Arg = argc; err.Ident = GetIdent(); throw ParserError(err); } int_type m = a_pArg[0]->GetInteger(), n = (argc == 1) ? m : a_pArg[1]->GetInteger(); if (m == n && n == 1) { *ret = 0.0; // unboxing of 1x1 matrices } else { *ret = matrix_type(m, n, 0.0); } } //----------------------------------------------------------------------- const char_type* FunMatrixZeros::GetDesc() const { return _T("zeros(x [, y]) - Returns a matrix whose elements are all 0."); } //----------------------------------------------------------------------- IToken* FunMatrixZeros::Clone() const { return new FunMatrixZeros(*this); } //----------------------------------------------------------------------- // // class FunMatrixEye // //----------------------------------------------------------------------- FunMatrixEye::FunMatrixEye() :ICallback(cmFUNC, _T("eye"), -1) {} //----------------------------------------------------------------------- FunMatrixEye::~FunMatrixEye() {} //----------------------------------------------------------------------- void FunMatrixEye::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int argc) { if (argc < 1 || argc>2) { ErrorContext err; err.Errc = ecINVALID_NUMBER_OF_PARAMETERS; err.Arg = argc; err.Ident = GetIdent(); throw ParserError(err); } int_type m = a_pArg[0]->GetInteger(), n = (argc == 1) ? m : a_pArg[1]->GetInteger(); matrix_type eye(m, n, 0.0); for (int i = 0; i < std::min(m, n); ++i) { eye.At(i, i) = 1.0; } *ret = eye; } //----------------------------------------------------------------------- const char_type* FunMatrixEye::GetDesc() const { return _T("eye(x, y) - returns a matrix with ones on its diagonal and zeros elsewhere."); } //----------------------------------------------------------------------- IToken* FunMatrixEye::Clone() const { return new FunMatrixEye(*this); } //----------------------------------------------------------------------- // // class FunMatrixSize // //----------------------------------------------------------------------- FunMatrixSize::FunMatrixSize() :ICallback(cmFUNC, _T("size"), -1) {} //----------------------------------------------------------------------- FunMatrixSize::~FunMatrixSize() {} //----------------------------------------------------------------------- void FunMatrixSize::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int argc) { if (argc != 1) { ErrorContext err; err.Errc = ecINVALID_NUMBER_OF_PARAMETERS; err.Arg = argc; err.Ident = GetIdent(); throw ParserError(err); } matrix_type sz(1, 2, 0.0); sz.At(0, 0) = (float_type)a_pArg[0]->GetRows(); sz.At(0, 1) = (float_type)a_pArg[0]->GetCols(); *ret = sz; } //----------------------------------------------------------------------- const char_type* FunMatrixSize::GetDesc() const { return _T("size(x) - returns the matrix dimensions."); } //----------------------------------------------------------------------- IToken* FunMatrixSize::Clone() const { return new FunMatrixSize(*this); } MUP_NAMESPACE_END muparserx-4.0.11/parser/mpFuncMatrix.h000066400000000000000000000100151414723276500177150ustar00rootroot00000000000000/** \file \brief Definition of functions for complex valued operations.
               __________                                 ____  ___
    _____  __ _\______   \_____ _______  ______ __________\   \/  /
   /     \|  |  \     ___/\__  \\_  __ \/  ___// __ \_  __ \     / 
  |  Y Y  \  |  /    |     / __ \|  | \/\___ \\  ___/|  | \/     \ 
  |__|_|  /____/|____|    (____  /__|  /____  >\___  >__| /___/\  \
        \/                     \/           \/     \/           \_/
                                       Copyright (C) 2016, Ingo Berg
                                       All rights reserved.

  Redistribution and use in source and binary forms, with or without 
  modification, are permitted provided that the following conditions are met:

   * Redistributions of source code must retain the above copyright notice, 
     this list of conditions and the following disclaimer.
   * Redistributions in binary form must reproduce the above copyright notice, 
     this list of conditions and the following disclaimer in the documentation 
     and/or other materials provided with the distribution.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
  POSSIBILITY OF SUCH DAMAGE.
*/ #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(); virtual ~FunMatrixOnes(); virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; //----------------------------------------------------------------------- /** \brief Parser callback object for creating matrices consisting entirely of zeros. \ingroup functions */ class FunMatrixZeros : public ICallback { public: FunMatrixZeros(); virtual ~FunMatrixZeros(); virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; //----------------------------------------------------------------------- /** \brief Parser callback object for creating unity matrices. \ingroup functions */ class FunMatrixEye : public ICallback { public: FunMatrixEye(); virtual ~FunMatrixEye(); virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; //----------------------------------------------------------------------- /** \brief Determines the dimensions of a matrix. \ingroup functions */ class FunMatrixSize : public ICallback { public: FunMatrixSize(); virtual ~FunMatrixSize(); virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; } // namespace mu #endif muparserx-4.0.11/parser/mpFuncNonCmplx.cpp000066400000000000000000000157221414723276500205540ustar00rootroot00000000000000/** \file \brief Implementation of basic functions used by muParserX.
               __________                                 ____  ___
    _____  __ _\______   \_____ _______  ______ __________\   \/  /
   /     \|  |  \     ___/\__  \\_  __ \/  ___// __ \_  __ \     / 
  |  Y Y  \  |  /    |     / __ \|  | \/\___ \\  ___/|  | \/     \ 
  |__|_|  /____/|____|    (____  /__|  /____  >\___  >__| /___/\  \
        \/                     \/           \/     \/           \_/
                                       Copyright (C) 2016, Ingo Berg
                                       All rights reserved.

  Redistribution and use in source and binary forms, with or without 
  modification, are permitted provided that the following conditions are met:

   * Redistributions of source code must retain the above copyright notice, 
     this list of conditions and the following disclaimer.
   * Redistributions in binary form must reproduce the above copyright notice, 
     this list of conditions and the following disclaimer in the documentation 
     and/or other materials provided with the distribution.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
  POSSIBILITY OF SUCH DAMAGE.
  
*/ #include "mpFuncNonCmplx.h" //--- Standard includes ---------------------------------------------------- #include #include #include //--- muParserX framework -------------------------------------------------- #include "mpValue.h" #include "mpError.h" #undef log #undef log2 MUP_NAMESPACE_START #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", std::sin, "sine function") MUP_UNARY_FUNC(FunCos, "cos", std::cos, "cosine function") MUP_UNARY_FUNC(FunSin, "tan", std::tan, "tangens function") // arcus functions MUP_UNARY_FUNC(FunASin, "asin", std::asin, "arcus sine") MUP_UNARY_FUNC(FunACos, "acos", std::acos, "arcus cosine") MUP_UNARY_FUNC(FunATan, "atan", std::atan, "arcus tangens") // hyperbolic functions MUP_UNARY_FUNC(FunSinH, "sinh", std::sinh, "hyperbolic sine") MUP_UNARY_FUNC(FunCosH, "cosh", std::cosh, "hyperbolic cosine") MUP_UNARY_FUNC(FunTanH, "tanh", std::tanh, "hyperbolic tangens") // hyperbolic arcus functions MUP_UNARY_FUNC(FunASinH, "asinh", std::asinh, "hyperbolic arcus sine") MUP_UNARY_FUNC(FunACosH, "acosh", std::acosh, "hyperbolic arcus cosine") MUP_UNARY_FUNC(FunATanH, "atanh", std::atanh, "hyperbolic arcus tangens") // logarithm functions MUP_UNARY_FUNC(FunLog, "log", std::log, "Natural logarithm") MUP_UNARY_FUNC(FunLog10, "log10", std::log10, "Logarithm base 10") MUP_UNARY_FUNC(FunLog2, "log2", std::log2, "Logarithm base 2") MUP_UNARY_FUNC(FunLn, "ln", std::log, "Natural logarithm") // square root MUP_UNARY_FUNC(FunSqrt, "sqrt", std::sqrt, "sqrt(x) - square root of x") MUP_UNARY_FUNC(FunCbrt, "cbrt", std::cbrt, "cbrt(x) - cubic root of x") MUP_UNARY_FUNC(FunExp, "exp", std::exp, "exp(x) - e to the power of x") MUP_UNARY_FUNC(FunAbs, "abs", std::fabs, "abs(x) - absolute value of x") #undef MUP_UNARY_FUNC #define MUP_BINARY_FUNC(CLASS, IDENT, FUNC, DESC) \ CLASS::CLASS() \ :ICallback(cmFUNC, _T(IDENT), 2) \ {} \ \ void CLASS::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int) \ { \ *ret = FUNC(a_pArg[0]->GetFloat(), a_pArg[1]->GetFloat()); \ } \ \ const char_type* CLASS::GetDesc() const \ { \ return _T(DESC); \ } \ \ IToken* CLASS::Clone() const \ { \ return new CLASS(*this); \ } MUP_BINARY_FUNC(FunPow, "pow", std::pow, "pow(x, y) - raise x to the power of y") MUP_BINARY_FUNC(FunHypot, "hypot", std::hypot, "hypot(x, y) - compute the length of the vector x,y") MUP_BINARY_FUNC(FunAtan2, "atan2", std::atan2, "arcus tangens with quadrant fix") MUP_BINARY_FUNC(FunFmod, "fmod", std::fmod, "fmod(x, y) - floating point remainder of x / y") MUP_BINARY_FUNC(FunRemainder, "remainder", std::remainder, "remainder(x, y) - IEEE remainder of x / y") #undef MUP_BINARY_FUNC MUP_NAMESPACE_END muparserx-4.0.11/parser/mpFuncNonCmplx.h000066400000000000000000000107211414723276500202130ustar00rootroot00000000000000/** \file \brief Implementation of basic functions used by muParserX.
               __________                                 ____  ___
    _____  __ _\______   \_____ _______  ______ __________\   \/  /
   /     \|  |  \     ___/\__  \\_  __ \/  ___// __ \_  __ \     / 
  |  Y Y  \  |  /    |     / __ \|  | \/\___ \\  ___/|  | \/     \ 
  |__|_|  /____/|____|    (____  /__|  /____  >\___  >__| /___/\  \
        \/                     \/           \/     \/           \_/
                                       Copyright (C) 2016, Ingo Berg
                                       All rights reserved.

  Redistribution and use in source and binary forms, with or without 
  modification, are permitted provided that the following conditions are met:

   * Redistributions of source code must retain the above copyright notice, 
     this list of conditions and the following disclaimer.
   * Redistributions in binary form must reproduce the above copyright notice, 
     this list of conditions and the following disclaimer in the documentation 
     and/or other materials provided with the distribution.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
  POSSIBILITY OF SUCH DAMAGE.
  
*/ #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) override; \ virtual const char_type* GetDesc() const override; \ virtual IToken* Clone() const override; \ }; MUP_UNARY_FUNC_DEF(FunSin) MUP_UNARY_FUNC_DEF(FunCos) MUP_UNARY_FUNC_DEF(FunTan) // 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(FunCbrt) MUP_UNARY_FUNC_DEF(FunExp) MUP_UNARY_FUNC_DEF(FunAbs) #undef MUP_UNARY_FUNC_DEF #define MUP_BINARY_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) override; \ virtual const char_type* GetDesc() const override; \ virtual IToken* Clone() const override; \ }; MUP_BINARY_FUNC_DEF(FunPow) MUP_BINARY_FUNC_DEF(FunHypot) MUP_BINARY_FUNC_DEF(FunAtan2) MUP_BINARY_FUNC_DEF(FunFmod) MUP_BINARY_FUNC_DEF(FunRemainder) #undef MUP_BINARY_FUNC_DEF } // namespace mu #endif muparserx-4.0.11/parser/mpFuncStr.cpp000066400000000000000000000142701414723276500175630ustar00rootroot00000000000000/* __________ ____ ___ _____ __ _\______ \_____ _______ ______ __________\ \/ / / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ / | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \ \/ \/ \/ \/ \_/ Copyright (C) 2016, Ingo Berg All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "mpFuncStr.h" #include #include #include #include #include #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 = (float_type)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); } //------------------------------------------------------------------------------ // // ToLower function // //------------------------------------------------------------------------------ FunStrToLower::FunStrToLower() :ICallback(cmFUNC, _T("tolower"), 1) {} //------------------------------------------------------------------------------ void FunStrToLower::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(), ::tolower); *ret = str; } //------------------------------------------------------------------------------ const char_type* FunStrToLower::GetDesc() const { return _T("tolower(s) - Converts the string s to lowercase characters."); } //------------------------------------------------------------------------------ IToken* FunStrToLower::Clone() const { return new FunStrToLower(*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; double out; // <- Ich will hier wirklich double, auch wenn der Type long double // ist. sscanf und long double geht nicht mit GCC! in = a_pArg[0]->GetString(); #ifndef _UNICODE sscanf(in.c_str(), "%lf", &out); #else swscanf(in.c_str(), _T("%lf"), &out); #endif *ret = (float_type)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 muparserx-4.0.11/parser/mpFuncStr.h000066400000000000000000000073751414723276500172400ustar00rootroot00000000000000/* __________ ____ ___ _____ __ _\______ \_____ _______ ______ __________\ \/ / / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ / | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \ \/ \/ \/ \/ \_/ Copyright (C) 2016, Ingo Berg All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #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) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; //------------------------------------------------------------------------------ /** \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) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; //------------------------------------------------------------------------------ /** \brief Convert a string to lower case letters. \ingroup functions */ class FunStrToLower : public ICallback { public: FunStrToLower(); virtual void Eval(ptr_val_type& ret, const ptr_val_type *a_pArg, int a_iArgc) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; //------------------------------------------------------------------------------ /** \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) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; // class FunStrToDbl } // namespace mu #endif muparserx-4.0.11/parser/mpFwdDecl.h000066400000000000000000000043211414723276500171500ustar00rootroot00000000000000/* __________ ____ ___ _____ __ _\______ \_____ _______ ______ __________\ \/ / / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ / | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \ \/ \/ \/ \/ \_/ Copyright (C) 2016, Ingo Berg All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef MUP_FWD_DECL_H #define MUP_FWD_DECL_H #include "mpDefines.h" MUP_NAMESPACE_START class ParserXBase; class ParserMessageProviderBase; class ICallback; class IToken; class IValue; class IValueReader; class IPrecedence; class IOprtIndex; class Value; class ValueCache; template class TokenPtr; MUP_NAMESPACE_END #endif muparserx-4.0.11/parser/mpICallback.cpp000066400000000000000000000120251414723276500200000ustar00rootroot00000000000000/** \file \brief Implementation of the interface for parser callback objects.
               __________                                 ____  ___
    _____  __ _\______   \_____ _______  ______ __________\   \/  /
   /     \|  |  \     ___/\__  \\_  __ \/  ___// __ \_  __ \     / 
  |  Y Y  \  |  /    |     / __ \|  | \/\___ \\  ___/|  | \/     \ 
  |__|_|  /____/|____|    (____  /__|  /____  >\___  >__| /___/\  \
        \/                     \/           \/     \/           \_/
                                       Copyright (C) 2016 Ingo Berg
                                       All rights reserved.

  muParserX - A C++ math parser library with array and string support
  Copyright (c) 2016, Ingo Berg
  All rights reserved.

  Redistribution and use in source and binary forms, with or without 
  modification, are permitted provided that the following conditions are met:

   * Redistributions of source code must retain the above copyright notice, 
     this list of conditions and the following disclaimer.
   * Redistributions in binary form must reproduce the above copyright notice, 
     this list of conditions and the following disclaimer in the documentation 
     and/or other materials provided with the distribution.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
  POSSIBILITY OF SUCH DAMAGE.
*/ #include "mpICallback.h" #include #include "mpParserBase.h" MUP_NAMESPACE_START //------------------------------------------------------------------------------ ICallback::ICallback(ECmdCode a_iCode, const char_type *a_szName, int a_nArgc) :IToken(a_iCode, a_szName) ,m_pParent(nullptr) ,m_nArgc(a_nArgc) ,m_nArgsPresent(-1) {} //------------------------------------------------------------------------------ ICallback::~ICallback() {} //--------------------------------------------------------------------------- ICallback* ICallback::AsICallback() { return this; } //--------------------------------------------------------------------------- IValue* ICallback::AsIValue() { return nullptr; } //------------------------------------------------------------------------------ /** \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("; pos=") << GetExprPos(); ss << _T("; id=\"") << GetIdent() << "\""; ss << _T("; argc=") << GetArgc() << " (found: " << 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 muparserx-4.0.11/parser/mpICallback.h000066400000000000000000000066601414723276500174550ustar00rootroot00000000000000/** \file \brief Definition of the interface for parser callback objects.
               __________                                 ____  ___
    _____  __ _\______   \_____ _______  ______ __________\   \/  /
   /     \|  |  \     ___/\__  \\_  __ \/  ___// __ \_  __ \     / 
  |  Y Y  \  |  /    |     / __ \|  | \/\___ \\  ___/|  | \/     \ 
  |__|_|  /____/|____|    (____  /__|  /____  >\___  >__| /___/\  \
        \/                     \/           \/     \/           \_/
                                       Copyright (C) 2016 Ingo Berg
                                       All rights reserved.

  muParserX - A C++ math parser library with array and string support
  Copyright (c) 2016, Ingo Berg
  All rights reserved.

  Redistribution and use in source and binary forms, with or without 
  modification, are permitted provided that the following conditions are met:

   * Redistributions of source code must retain the above copyright notice, 
     this list of conditions and the following disclaimer.
   * Redistributions in binary form must reproduce the above copyright notice, 
     this list of conditions and the following disclaimer in the documentation 
     and/or other materials provided with the distribution.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
  POSSIBILITY OF SUCH DAMAGE.
*/ #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); 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 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 int m_nArgc; ///< Number of this function can take Arguments. int m_nArgsPresent; ///< Number of arguments actually submitted }; // class ICallback MUP_NAMESPACE_END #endif muparserx-4.0.11/parser/mpIOprt.cpp000066400000000000000000000133121414723276500172300ustar00rootroot00000000000000/* __________ ____ ___ _____ __ _\______ \_____ _______ ______ __________\ \/ / / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ / | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \ \/ \/ \/ \/ \_/ Copyright (C) 2016 Ingo Berg All rights reserved. muParserX - A C++ math parser library with array and string support Copyright (c) 2016, Ingo Berg All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #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("; pos=") << GetExprPos(); ss << _T("; id=\"") << 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; } //--------------------------------------------------------------------------- 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("; pos=") << GetExprPos(); ss << _T("; id=\"") << GetIdent() << _T("\""); ss << _T("; argc=") << GetArgc(); ss << _T("]"); return ss.str(); } //------------------------------------------------------------------------------ // // Unary Infix Operators // //------------------------------------------------------------------------------ IOprtInfix::IOprtInfix(const char_type *a_szIdent, int nPrec) :ICallback(cmOPRT_INFIX, a_szIdent, 1) ,IPrecedence() ,m_nPrec(nPrec) {} //------------------------------------------------------------------------------ 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("; pos=") << GetExprPos(); ss << _T("; id=\"") << GetIdent() << _T("\""); ss << _T("; argc=") << GetArgc(); ss << _T("]"); return ss.str(); } //--------------------------------------------------------------------------- IPrecedence* IOprtInfix::AsIPrecedence() { return this; } //------------------------------------------------------------------------------ int IOprtInfix::GetPri() const { return m_nPrec; } //------------------------------------------------------------------------------ EOprtAsct IOprtInfix::GetAssociativity() const { return oaNONE; } } // namespace mu muparserx-4.0.11/parser/mpIOprt.h000066400000000000000000000103451414723276500167000ustar00rootroot00000000000000/** \file mpIOprt.h \brief Definition of base classes needed for parser operator definitions.
               __________                                 ____  ___
    _____  __ _\______   \_____ _______  ______ __________\   \/  /
   /     \|  |  \     ___/\__  \\_  __ \/  ___// __ \_  __ \     / 
  |  Y Y  \  |  /    |     / __ \|  | \/\___ \\  ___/|  | \/     \ 
  |__|_|  /____/|____|    (____  /__|  /____  >\___  >__| /___/\  \
        \/                     \/           \/     \/           \_/
                                       Copyright (C) 2016 Ingo Berg
                                       All rights reserved.

  muParserX - A C++ math parser library with array and string support
  Copyright (c) 2016, Ingo Berg
  All rights reserved.

  Redistribution and use in source and binary forms, with or without 
  modification, are permitted provided that the following conditions are met:

   * Redistributions of source code must retain the above copyright notice, 
     this list of conditions and the following disclaimer.
   * Redistributions in binary form must reproduce the above copyright notice, 
     this list of conditions and the following disclaimer in the documentation 
     and/or other materials provided with the distribution.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
  POSSIBILITY OF SUCH DAMAGE.
*/ #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; //------------------------------------------ // IPrecedence implementation //------------------------------------------ virtual IPrecedence* AsIPrecedence(); virtual EOprtAsct GetAssociativity() const; virtual int GetPri() const; private: 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 IPrecedence { public: IOprtInfix(const char_type *a_szIdent, int nPrec); virtual ~IOprtInfix(); virtual string_type AsciiDump() const; //------------------------------------------ // IPrecedence implementation //------------------------------------------ virtual IPrecedence* AsIPrecedence(); virtual int GetPri() const; virtual EOprtAsct GetAssociativity() const; private: int m_nPrec; }; // class IOperator } // namespace mu #endif muparserx-4.0.11/parser/mpIOprtBinShortcut.cpp000066400000000000000000000065441414723276500214260ustar00rootroot00000000000000/* __________ ____ ___ _____ __ _\______ \_____ _______ ______ __________\ \/ / / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ / | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \ \/ \/ \/ \/ \_/ Copyright (C) 2021 Ingo Berg, et al. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "mpIOprtBinShortcut.h" MUP_NAMESPACE_START //--------------------------------------------------------------------------- // logic operator // && 、 and 、 ||、 or // //--------------------------------------------------------------------------- IOprtBinShortcut::IOprtBinShortcut(ECmdCode eCmd, const char_type* a_szIdent, int nPrec, EOprtAsct eAsc) :IToken(eCmd, a_szIdent) , IPrecedence() , m_nPrec(nPrec) , m_eAsc(eAsc) , m_nOffset() {} //--------------------------------------------------------------------------- IToken* IOprtBinShortcut::Clone() const { return new IOprtBinShortcut(*this); } //--------------------------------------------------------------------------- void IOprtBinShortcut::SetOffset(int nOffset) { m_nOffset = nOffset; } //--------------------------------------------------------------------------- int IOprtBinShortcut::GetOffset() const { return m_nOffset; } //--------------------------------------------------------------------------- string_type IOprtBinShortcut::AsciiDump() const { stringstream_type ss; ss << GetIdent(); ss << _T(" [addr=0x") << std::hex << this << std::dec; ss << _T("; pos=") << GetExprPos(); ss << _T("; offset=") << m_nOffset; ss << _T("]"); return ss.str(); } //--------------------------------------------------------------------------- int IOprtBinShortcut::GetPri() const { return m_nPrec; } //--------------------------------------------------------------------------- EOprtAsct IOprtBinShortcut::GetAssociativity() const { return m_eAsc; } //--------------------------------------------------------------------------- IPrecedence* IOprtBinShortcut::AsIPrecedence() { return this; } MUP_NAMESPACE_END muparserx-4.0.11/parser/mpIOprtBinShortcut.h000066400000000000000000000056561414723276500210760ustar00rootroot00000000000000#ifndef MUP_I_OPRT_BIN_SHORTCUT_H #define MUP_I_OPRT_BIN_SHORTCUT_H /** \file \brief Definition of basic types used by muParserX
               __________                                 ____  ___
    _____  __ _\______   \_____ _______  ______ __________\   \/  /
   /     \|  |  \     ___/\__  \\_  __ \/  ___// __ \_  __ \     /
  |  Y Y  \  |  /    |     / __ \|  | \/\___ \\  ___/|  | \/     \
  |__|_|  /____/|____|    (____  /__|  /____  >\___  >__| /___/\  \
        \/                     \/           \/     \/           \_/
  Copyright (C) 2021 Ingo Berg, et al.
  All rights reserved.

  Redistribution and use in source and binary forms, with or without
  modification, are permitted provided that the following conditions are met:

   * Redistributions of source code must retain the above copyright notice,
     this list of conditions and the following disclaimer.
   * Redistributions in binary form must reproduce the above copyright notice,
     this list of conditions and the following disclaimer in the documentation
     and/or other materials provided with the distribution.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  POSSIBILITY OF SUCH DAMAGE.
*/ #include "mpIToken.h" #include "mpIPrecedence.h" MUP_NAMESPACE_START //--------------------------------------------------------------------------- /** \brief A class for encapsulation if-then-else tokens. */ class IOprtBinShortcut : public IToken, public IPrecedence { public: IOprtBinShortcut(ECmdCode eCmd, const char_type *a_szIdent, int nPrec, EOprtAsct m_eAsc); void SetOffset(int nOffset); int GetOffset() const; //--------------------------------------------- // IToken interface //--------------------------------------------- virtual IToken* Clone() const override; virtual string_type AsciiDump() const override; virtual IPrecedence* AsIPrecedence() override; //--------------------------------------------- // IPrecedence interface //--------------------------------------------- virtual int GetPri() const override; virtual EOprtAsct GetAssociativity() const override; private: int m_nPrec; EOprtAsct m_eAsc; int m_nOffset; }; MUP_NAMESPACE_END #endif muparserx-4.0.11/parser/mpIPackage.cpp000066400000000000000000000044431414723276500176440ustar00rootroot00000000000000/* __________ ____ ___ _____ __ _\______ \_____ _______ ______ __________\ \/ / / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ / | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \ \/ \/ \/ \/ \_/ Copyright (C) 2016 Ingo Berg All rights reserved. muParserX - A C++ math parser library with array and string support Copyright (c) 2016, Ingo Berg All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "mpIPackage.h" #include "mpDefines.h" #include "mpParserBase.h" MUP_NAMESPACE_START //------------------------------------------------------------------------------ IPackage::IPackage() {} //------------------------------------------------------------------------------ IPackage::~IPackage() {} MUP_NAMESPACE_END muparserx-4.0.11/parser/mpIPackage.h000066400000000000000000000045411414723276500173100ustar00rootroot00000000000000#ifndef MU_IPACKAGE_H #define MU_IPACKAGE_H /* __________ ____ ___ _____ __ _\______ \_____ _______ ______ __________\ \/ / / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ / | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \ \/ \/ \/ \/ \_/ Copyright (C) 2016 Ingo Berg All rights reserved. muParserX - A C++ math parser library with array and string support Copyright (c) 2016, Ingo Berg All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #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 muparserx-4.0.11/parser/mpIPrecedence.h000066400000000000000000000050261414723276500200110ustar00rootroot00000000000000/** \file mpIPrecedence.h \brief Definition of base classes needed for parser operator definitions.
               __________                                 ____  ___
    _____  __ _\______   \_____ _______  ______ __________\   \/  /
   /     \|  |  \     ___/\__  \\_  __ \/  ___// __ \_  __ \     / 
  |  Y Y  \  |  /    |     / __ \|  | \/\___ \\  ___/|  | \/     \ 
  |__|_|  /____/|____|    (____  /__|  /____  >\___  >__| /___/\  \
        \/                     \/           \/     \/           \_/
                                       Copyright (C) 2016 Ingo Berg
                                       All rights reserved.

  muParserX - A C++ math parser library with array and string support
  Copyright (c) 2016, Ingo Berg
  All rights reserved.

  Redistribution and use in source and binary forms, with or without 
  modification, are permitted provided that the following conditions are met:

   * Redistributions of source code must retain the above copyright notice, 
     this list of conditions and the following disclaimer.
   * Redistributions in binary form must reproduce the above copyright notice, 
     this list of conditions and the following disclaimer in the documentation 
     and/or other materials provided with the distribution.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
  POSSIBILITY OF SUCH DAMAGE.
*/ #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 ~IPrecedence(){} virtual int GetPri() const = 0; virtual EOprtAsct GetAssociativity() const = 0; }; } // namespace mu #endif muparserx-4.0.11/parser/mpIToken.cpp000066400000000000000000000234761414723276500174000ustar00rootroot00000000000000/* __________ ____ ___ _____ __ _\______ \_____ _______ ______ __________\ \/ / / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ / | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \ \/ \/ \/ \/ \_/ Copyright (C) 2016 Ingo Berg All rights reserved. muParserX - A C++ math parser library with array and string support Copyright (c) 2016, Ingo Berg All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "mpIToken.h" #include #include #include #include #include #include "mpIPrecedence.h" MUP_NAMESPACE_START #ifdef MUP_LEAKAGE_REPORT std::list 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::const_iterator item = IToken::s_Tokens.begin(); std::vector 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::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 nullptr; } //--------------------------------------------------------------------------- IValue* IToken::AsIValue() { return nullptr; } //--------------------------------------------------------------------------- IPrecedence* IToken::AsIPrecedence() { return nullptr; } //------------------------------------------------------------------------------ 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 muparserx-4.0.11/parser/mpIToken.h000066400000000000000000000162511414723276500170360ustar00rootroot00000000000000/*
               __________                                 ____  ___
    _____  __ _\______   \_____ _______  ______ __________\   \/  /
   /     \|  |  \     ___/\__  \\_  __ \/  ___// __ \_  __ \     / 
  |  Y Y  \  |  /    |     / __ \|  | \/\___ \\  ___/|  | \/     \ 
  |__|_|  /____/|____|    (____  /__|  /____  >\___  >__| /___/\  \
        \/                     \/           \/     \/           \_/
                                       Copyright (C) 2016 Ingo Berg
                                       All rights reserved.

  muParserX - A C++ math parser library with array and string support
  Copyright (c) 2016, Ingo Berg
  All rights reserved.

  Redistribution and use in source and binary forms, with or without 
  modification, are permitted provided that the following conditions are met:

   * Redistributions of source code must retain the above copyright notice, 
     this list of conditions and the following disclaimer.
   * Redistributions in binary form must reproduce the above copyright notice, 
     this list of conditions and the following disclaimer in the documentation 
     and/or other materials provided with the distribution.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
  POSSIBILITY OF SUCH DAMAGE.
*/ #ifndef MUP_ITOKEN_H #define MUP_ITOKEN_H #include #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; friend class TokenPtr; friend class TokenPtr; friend class TokenPtr; friend class TokenPtr; friend class TokenPtr; friend class TokenPtr; friend class TokenPtr; friend class TokenPtr; friend class TokenPtr; 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 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 class TokenPtr { public: typedef T* token_type; //--------------------------------------------------------------------------- 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(m_pTok); } //--------------------------------------------------------------------------- T& operator*() const { assert(m_pTok); return *(static_cast(m_pTok)); } //--------------------------------------------------------------------------- token_type Get() const { return static_cast(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 muparserx-4.0.11/parser/mpIValReader.cpp000066400000000000000000000062471414723276500201620ustar00rootroot00000000000000/* __________ ____ ___ _____ __ _\______ \_____ _______ ______ __________\ \/ / / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ / | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \ \/ \/ \/ \/ \_/ Copyright (C) 2016 Ingo Berg All rights reserved. muParserX - A C++ math parser library with array and string support Copyright (c) 2016, Ingo Berg All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "mpIValReader.h" #include "mpTokenReader.h" #include MUP_NAMESPACE_START //-------------------------------------------------------------------------------------------- IValueReader::IValueReader() :m_pTokenReader(nullptr) {} //-------------------------------------------------------------------------------------------- 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) ? nullptr : buf[size-1-pos].Get(); } } muparserx-4.0.11/parser/mpIValReader.h000066400000000000000000000074201414723276500176210ustar00rootroot00000000000000/* __________ ____ ___ _____ __ _\______ \_____ _______ ______ __________\ \/ / / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ / | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \ \/ \/ \/ \/ \_/ Copyright (C) 2016 Ingo Berg All rights reserved. muParserX - A C++ math parser library with array and string support Copyright (c) 2016, Ingo Berg All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #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 muparserx-4.0.11/parser/mpIValue.cpp000066400000000000000000000331651414723276500173700ustar00rootroot00000000000000/** \file \brief Implementation of the virtual base class used for all parser values.
                __________                                 ____  ___
     _____  __ _\______   \_____ _______  ______ __________\   \/  /
    /     \|  |  \     ___/\__  \\_  __ \/  ___// __ \_  __ \     /
    |  Y Y  \  |  /    |     / __ \|  | \/\___ \\  ___/|  | \/     \
    |__|_|  /____/|____|    (____  /__|  /____  >\___  >__| /___/\  \
          \/                     \/           \/     \/           \_/
    Copyright (C) 2016 Ingo Berg
    All rights reserved.

    muParserX - A C++ math parser library with array and string support
    Copyright (c) 2016, Ingo Berg
    All rights reserved.

    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice,
    this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright notice,
    this list of conditions and the following disclaimer in the documentation
    and/or other materials provided with the distribution.

    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
    IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
    INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
    NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
    WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    POSSIBILITY OF SUCH DAMAGE.
    
*/ #include "mpIValue.h" //--- Standard includes ------------------------------------------------------ #include #include #include #include //--- 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); } //--------------------------------------------------------------------------- IValue::IValue(ECmdCode a_iCode, const string_type &a_sIdent) :IToken(a_iCode, a_sIdent) { assert(a_iCode == cmVAL); } //--------------------------------------------------------------------------- IValue::~IValue() {} //--------------------------------------------------------------------------- ICallback* IValue::AsICallback() { return nullptr; } //--------------------------------------------------------------------------- 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 << std::setprecision(std::numeric_limits::digits10) << 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(this)->At(i) != const_cast(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(this)->At(i) != const_cast(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(); char_type 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 muparserx-4.0.11/parser/mpIValue.h000066400000000000000000000153751414723276500170400ustar00rootroot00000000000000#ifndef MUP_IVALUE_H #define MUP_IVALUE_H /** \file \brief Definition of the virtual base class used for all parser values.
               __________                                 ____  ___
    _____  __ _\______   \_____ _______  ______ __________\   \/  /
   /     \|  |  \     ___/\__  \\_  __ \/  ___// __ \_  __ \     / 
  |  Y Y  \  |  /    |     / __ \|  | \/\___ \\  ___/|  | \/     \ 
  |__|_|  /____/|____|    (____  /__|  /____  >\___  >__| /___/\  \
        \/                     \/           \/     \/           \_/
  Copyright (C) 2021 Ingo Berg, et al.
  All rights reserved.

  Redistribution and use in source and binary forms, with or without 
  modification, are permitted provided that the following conditions are met:

   * Redistributions of source code must retain the above copyright notice, 
     this list of conditions and the following disclaimer.
   * Redistributions in binary form must reproduce the above copyright notice, 
     this list of conditions and the following disclaimer in the documentation 
     and/or other materials provided with the distribution.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
  POSSIBILITY OF SUCH DAMAGE.
*/ #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 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:
  • 0 - scalar
  • 1 - vector
  • 2 - matrix
*/ inline int GetDim() const { return (IsMatrix()) ? GetArray().GetDim() : 0; } //--------------------------------------------------------------------------- virtual bool IsVariable() const = 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); } // namespace mu #endif muparserx-4.0.11/parser/mpIfThenElse.cpp000066400000000000000000000073201414723276500201630ustar00rootroot00000000000000/* __________ ____ ___ _____ __ _\______ \_____ _______ ______ __________\ \/ / / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ / | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \ \/ \/ \/ \/ \_/ Copyright (C) 2016 Ingo Berg All rights reserved. muParserX - A C++ math parser library with array and string support Copyright (c) 2016, Ingo Berg All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #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("; pos=") << GetExprPos(); 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 muparserx-4.0.11/parser/mpIfThenElse.h000066400000000000000000000061621414723276500176330ustar00rootroot00000000000000/** \file \brief Definition of basic types used by muParserX
               __________                                 ____  ___
    _____  __ _\______   \_____ _______  ______ __________\   \/  /
   /     \|  |  \     ___/\__  \\_  __ \/  ___// __ \_  __ \     / 
  |  Y Y  \  |  /    |     / __ \|  | \/\___ \\  ___/|  | \/     \ 
  |__|_|  /____/|____|    (____  /__|  /____  >\___  >__| /___/\  \
        \/                     \/           \/     \/           \_/
                                       Copyright (C) 2016 Ingo Berg
                                       All rights reserved.

  muParserX - A C++ math parser library with array and string support
  Copyright (c) 2016, Ingo Berg
  All rights reserved.

  Redistribution and use in source and binary forms, with or without 
  modification, are permitted provided that the following conditions are met:

   * Redistributions of source code must retain the above copyright notice, 
     this list of conditions and the following disclaimer.
   * Redistributions in binary form must reproduce the above copyright notice, 
     this list of conditions and the following disclaimer in the documentation 
     and/or other materials provided with the distribution.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
  POSSIBILITY OF SUCH DAMAGE.
*/ #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 override; virtual string_type AsciiDump() const override; virtual IPrecedence* AsIPrecedence() override; //--------------------------------------------- // IPrecedence interface //--------------------------------------------- virtual int GetPri() const override; virtual EOprtAsct GetAssociativity() const override; private: int m_nOffset; }; MUP_NAMESPACE_END #endif muparserx-4.0.11/parser/mpMatrix.h000066400000000000000000000272211414723276500171100ustar00rootroot00000000000000#ifndef MU_MATRIX_H #define MU_MATRIX_H /* __________ ____ ___ _____ __ _\______ \_____ _______ ______ __________\ \/ / / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ / | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \ \/ \/ \/ \/ \_/ Copyright (C) 2016, Ingo Berg All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include "mpMatrixError.h" MUP_NAMESPACE_START //----------------------------------------------------------------------------------------------- template class Matrix { template friend Matrix operator+(const Matrix& lhs, const Matrix& rhs); template 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 &v) :m_nRows(v.size()) , m_nCols(1) , m_eStorageScheme(mssROWS_FIRST) , m_vData(v) {} //--------------------------------------------------------------------------------------------- /* Constructs a Matrix object representing a vector */ template Matrix(T(&v)[TSize]) :m_nRows(TSize) , m_nCols(1) , m_eStorageScheme(mssROWS_FIRST) , m_vData(v, v + TSize) {} //--------------------------------------------------------------------------------------------- template 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 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.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& Transpose() { if (GetDim() == 0) return *this; m_eStorageScheme = (m_eStorageScheme == mssROWS_FIRST) ? mssCOLS_FIRST : mssROWS_FIRST; std::swap(m_nRows, m_nCols); return *this; } //--------------------------------------------------------------------------------------------- void Fill(const T &v) { m_vData.assign(m_vData.size(), v); } private: int m_nRows; int m_nCols; EMatrixStorageScheme m_eStorageScheme; std::vector m_vData; //--------------------------------------------------------------------------------------------- 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 Matrix operator*(const Matrix& lhs, const T& rhs) { return Matrix(lhs) *= rhs; } //--------------------------------------------------------------------------------------------- template Matrix operator*(const Matrix& lhs, const Matrix& rhs) { return Matrix(lhs) *= rhs; } //--------------------------------------------------------------------------------------------- template Matrix operator+(const Matrix& lhs, const Matrix& rhs) { return Matrix(lhs) += rhs; } //--------------------------------------------------------------------------------------------- template Matrix operator-(const Matrix& lhs, const Matrix& rhs) { return Matrix(lhs) -= rhs; } MUP_NAMESPACE_END #endif muparserx-4.0.11/parser/mpMatrixError.h000066400000000000000000000042111414723276500201140ustar00rootroot00000000000000#ifndef MU_MATRIX_ERROR_H #define MU_MATRIX_ERROR_H /* __________ ____ ___ _____ __ _\______ \_____ _______ ______ __________\ \/ / / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ / | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \ \/ \/ \/ \/ \_/ Copyright (C) 2016, Ingo Berg All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include MUP_NAMESPACE_START class MatrixError : public std::runtime_error { public: explicit MatrixError(const std::string &sMsg) :std::runtime_error(sMsg) {} }; MUP_NAMESPACE_END #endif muparserx-4.0.11/parser/mpOprtBinAssign.cpp000066400000000000000000000203541414723276500207210ustar00rootroot00000000000000/** \file \brief This file contains the implementation of binary assignment operators used in muParser.
               __________                                 ____  ___
    _____  __ _\______   \_____ _______  ______ __________\   \/  /
   /     \|  |  \     ___/\__  \\_  __ \/  ___// __ \_  __ \     / 
  |  Y Y  \  |  /    |     / __ \|  | \/\___ \\  ___/|  | \/     \ 
  |__|_|  /____/|____|    (____  /__|  /____  >\___  >__| /___/\  \
        \/                     \/           \/     \/           \_/
                                       Copyright (C) 2016, Ingo Berg
                                       All rights reserved.

  Redistribution and use in source and binary forms, with or without 
  modification, are permitted provided that the following conditions are met:

   * Redistributions of source code must retain the above copyright notice, 
     this list of conditions and the following disclaimer.
   * Redistributions in binary form must reproduce the above copyright notice, 
     this list of conditions and the following disclaimer in the documentation 
     and/or other materials provided with the distribution.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
  POSSIBILITY OF SUCH DAMAGE.
*/ #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(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(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(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(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(); // fix for #107: *pVar = cmplx_type(a * c - b * d, a * d + b * c); // *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(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 muparserx-4.0.11/parser/mpOprtBinAssign.h000066400000000000000000000111661414723276500203670ustar00rootroot00000000000000/** \file \brief This file contains the definition of binary assignment operators used in muParser.
               __________                                 ____  ___
    _____  __ _\______   \_____ _______  ______ __________\   \/  /
   /     \|  |  \     ___/\__  \\_  __ \/  ___// __ \_  __ \     / 
  |  Y Y  \  |  /    |     / __ \|  | \/\___ \\  ___/|  | \/     \ 
  |__|_|  /____/|____|    (____  /__|  /____  >\___  >__| /___/\  \
        \/                     \/           \/     \/           \_/
                                       Copyright (C) 2016, Ingo Berg
                                       All rights reserved.

  Redistribution and use in source and binary forms, with or without 
  modification, are permitted provided that the following conditions are met:

   * Redistributions of source code must retain the above copyright notice, 
     this list of conditions and the following disclaimer.
   * Redistributions in binary form must reproduce the above copyright notice, 
     this list of conditions and the following disclaimer in the documentation 
     and/or other materials provided with the distribution.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
  POSSIBILITY OF SUCH DAMAGE.
*/ #ifndef MUP_OPRT_BIN_ASSIGN_H #define MUP_OPRT_BIN_ASSIGN_H //--- Standard includes ---------------------------------------------------------- #include //--- 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) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; //------------------------------------------------------------------------------ /** \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) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; //------------------------------------------------------------------------------ /** \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) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; //------------------------------------------------------------------------------ /** \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) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; //------------------------------------------------------------------------------ /** \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) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; MUP_NAMESPACE_END #endif muparserx-4.0.11/parser/mpOprtBinCommon.cpp000066400000000000000000000463701414723276500207330ustar00rootroot00000000000000/* __________ ____ ___ _____ __ _\______ \_____ _______ ______ __________\ \/ / / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ / | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \ \/ \/ \/ \/ \_/ Copyright (C) 2021 Ingo Berg, et al. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "mpOprtBinCommon.h" #include #include MUP_NAMESPACE_START //----------------------------------------------------------------------------------------------- // // class OprtStrAdd // //----------------------------------------------------------------------------------------------- OprtStrAdd::OprtStrAdd() :IOprtBin(_T("//"), (int)prADD_SUB, oaLEFT) {} //----------------------------------------------------------------------------------------------- void OprtStrAdd::Eval(ptr_val_type& ret, const ptr_val_type *arg, int argc) { MUP_VERIFY(argc == 2); string_type a = arg[0]->GetString(); string_type b = arg[1]->GetString(); *ret = a + b; } //----------------------------------------------------------------------------------------------- const char_type* OprtStrAdd::GetDesc() const { return _T("string concatenation"); } //----------------------------------------------------------------------------------------------- IToken* OprtStrAdd::Clone() const { return new OprtStrAdd(*this); } //----------------------------------------------------------------------------------------------- // // class OprtEQ // //----------------------------------------------------------------------------------------------- OprtEQ::OprtEQ() :IOprtBin(_T("=="), (int)prRELATIONAL1, oaLEFT) {} //----------------------------------------------------------------------------------------------- void OprtEQ::Eval(ptr_val_type& ret, const ptr_val_type *a_pArg, int) { *ret = *a_pArg[0] == *a_pArg[1]; } //----------------------------------------------------------------------------------------------- const char_type* OprtEQ::GetDesc() const { return _T("equals operator"); } //----------------------------------------------------------------------------------------------- IToken* OprtEQ::Clone() const { return new OprtEQ(*this); } //----------------------------------------------------------------------------------------------- // // class OprtNEQ // //----------------------------------------------------------------------------------------------- OprtNEQ::OprtNEQ() :IOprtBin(_T("!="), (int)prRELATIONAL1, oaLEFT) {} //----------------------------------------------------------------------------------------------- void OprtNEQ::Eval(ptr_val_type& ret, const ptr_val_type *a_pArg, int) { *ret = *a_pArg[0] != *a_pArg[1]; } //----------------------------------------------------------------------------------------------- const char_type* OprtNEQ::GetDesc() const { return _T("not equal operator"); } //----------------------------------------------------------------------------------------------- IToken* OprtNEQ::Clone() const { return new OprtNEQ(*this); } //----------------------------------------------------------------------------------------------- // // class OprtLT // //----------------------------------------------------------------------------------------------- OprtLT::OprtLT() :IOprtBin(_T("<"), (int)prRELATIONAL2, oaLEFT) {} //----------------------------------------------------------------------------------------------- void OprtLT::Eval(ptr_val_type& ret, const ptr_val_type *a_pArg, int) { *ret = *a_pArg[0] < *a_pArg[1]; } //----------------------------------------------------------------------------------------------- const char_type* OprtLT::GetDesc() const { return _T("less than operator"); } //----------------------------------------------------------------------------------------------- IToken* OprtLT::Clone() const { return new OprtLT(*this); } //----------------------------------------------------------------------------------------------- // // class OprtGT // //----------------------------------------------------------------------------------------------- OprtGT::OprtGT() :IOprtBin(_T(">"), (int)prRELATIONAL2, oaLEFT) {} //----------------------------------------------------------------------------------------------- void OprtGT::Eval(ptr_val_type& ret, const ptr_val_type *a_pArg, int) { *ret = *a_pArg[0] > *a_pArg[1]; } //----------------------------------------------------------------------------------------------- const char_type* OprtGT::GetDesc() const { return _T("greater than operator"); } //----------------------------------------------------------------------------------------------- IToken* OprtGT::Clone() const { return new OprtGT(*this); } //----------------------------------------------------------------------------------------------- // // class OprtLE // //----------------------------------------------------------------------------------------------- OprtLE::OprtLE() :IOprtBin(_T("<="), (int)prRELATIONAL2, oaLEFT) {} //----------------------------------------------------------------------------------------------- void OprtLE::Eval(ptr_val_type& ret, const ptr_val_type *a_pArg, int) { *ret = *a_pArg[0] <= *a_pArg[1]; } //----------------------------------------------------------------------------------------------- const char_type* OprtLE::GetDesc() const { return _T("less or equal operator"); } //----------------------------------------------------------------------------------------------- IToken* OprtLE::Clone() const { return new OprtLE(*this); } //----------------------------------------------------------------------------------------------- // // class OprtGE // //----------------------------------------------------------------------------------------------- OprtGE::OprtGE() :IOprtBin(_T(">="), (int)prRELATIONAL2, oaLEFT) {} //----------------------------------------------------------------------------------------------- void OprtGE::Eval(ptr_val_type& ret, const ptr_val_type *a_pArg, int) { *ret = *a_pArg[0] >= *a_pArg[1]; } //----------------------------------------------------------------------------------------------- const char_type* OprtGE::GetDesc() const { return _T("greater or equal operator"); } //----------------------------------------------------------------------------------------------- IToken* OprtGE::Clone() const { return new OprtGE(*this); } //----------------------------------------------------------------------------------------------- // // 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) { MUP_VERIFY(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 = (float_type)((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) { MUP_VERIFY(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 = (float_type)((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 // //----------------------------------------------------------------------------------------------- OprtLogicOr::OprtLogicOr(const char_type *szIdent) :IOprtBin(szIdent, (int)prLOGIC_OR, oaLEFT) {} //----------------------------------------------------------------------------------------------- void OprtLogicOr::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int num) { MUP_VERIFY(num == 2); *ret = a_pArg[0]->GetBool() || a_pArg[1]->GetBool(); } //----------------------------------------------------------------------------------------------- const char_type* OprtLogicOr::GetDesc() const { return _T("logical or"); } //----------------------------------------------------------------------------------------------- IToken* OprtLogicOr::Clone() const { return new OprtLogicOr(*this); } //----------------------------------------------------------------------------------------------- // // class OprtLAnd // //----------------------------------------------------------------------------------------------- OprtLogicAnd::OprtLogicAnd(const char_type *szIdent) :IOprtBin(szIdent, (int)prLOGIC_AND, oaLEFT) {} //----------------------------------------------------------------------------------------------- void OprtLogicAnd::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int num) { MUP_VERIFY(num == 2); *ret = a_pArg[0]->GetBool() && a_pArg[1]->GetBool(); } //----------------------------------------------------------------------------------------------- const char_type* OprtLogicAnd::GetDesc() const { return _T("logical and"); } //----------------------------------------------------------------------------------------------- IToken* OprtLogicAnd::Clone() const { return new OprtLogicAnd(*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) { MUP_VERIFY(num == 2); if (!a_pArg[0]->IsScalar()) throw ParserError(ErrorContext(ecTYPE_CONFLICT_FUN, GetExprPos(), GetIdent(), a_pArg[0]->GetType(), 'i', 1)); if (!a_pArg[1]->IsScalar()) throw ParserError(ErrorContext(ecTYPE_CONFLICT_FUN, GetExprPos(), 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, GetExprPos(), a_pArg[0]->GetIdent(), a_pArg[0]->GetType(), 'i', 1)); if (b != (int_type)b) throw ParserError(ErrorContext(ecTYPE_CONFLICT_FUN, GetExprPos(), a_pArg[1]->GetIdent(), a_pArg[1]->GetType(), 'i', 2)); float_type result = a*std::pow(2, b); int numDigits = std::numeric_limits::digits10; if (std::fabs(result) >= std::fabs(std::pow(10.0, numDigits))) throw ParserError(ErrorContext(ecOVERFLOW, GetExprPos(), GetIdent())); if (result > 0) { *ret = std::floor(result); } else { *ret = std::ceil(result); } } //----------------------------------------------------------------------------------------------- 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) { MUP_VERIFY(num == 2); if (!a_pArg[0]->IsScalar()) throw ParserError(ErrorContext(ecTYPE_CONFLICT_FUN, GetExprPos(), GetIdent(), a_pArg[0]->GetType(), 'i', 1)); if (!a_pArg[1]->IsScalar()) throw ParserError(ErrorContext(ecTYPE_CONFLICT_FUN, GetExprPos(), 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, GetExprPos(), a_pArg[0]->GetIdent(), a_pArg[0]->GetType(), 'i', 1)); if (b != (int_type)b) throw ParserError(ErrorContext(ecTYPE_CONFLICT_FUN, GetExprPos(), a_pArg[1]->GetIdent(), a_pArg[1]->GetType(), 'i', 2)); float_type result = a*std::pow(2, -b); int numDigits = std::numeric_limits::digits10; if (std::fabs(result) >= std::fabs(std::pow(10.0, numDigits))) throw ParserError(ErrorContext(ecOVERFLOW, GetExprPos(), GetIdent())); if (result > 0) *ret = std::floor(result); else *ret = std::ceil(result); } //----------------------------------------------------------------------------------------------- const char_type* OprtShr::GetDesc() const { return _T("shift right"); } //----------------------------------------------------------------------------------------------- IToken* OprtShr::Clone() const { return new OprtShr(*this); } //----------------------------------------------------------------------------------------------- // // Cast To Float // //----------------------------------------------------------------------------------------------- OprtCastToFloat::OprtCastToFloat() :IOprtInfix(_T("(float)"), prINFIX) {} //----------------------------------------------------------------------------------------------- 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)"), prINFIX) {} //----------------------------------------------------------------------------------------------- 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 = (float_type)((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); } } muparserx-4.0.11/parser/mpOprtBinCommon.h000066400000000000000000000211441414723276500203700ustar00rootroot00000000000000/* __________ ____ ___ _____ __ _\______ \_____ _______ ______ __________\ \/ / / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ / | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \ \/ \/ \/ \/ \_/ Copyright (C) 2021 Ingo Berg, et al. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #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 #include "mpIOprt.h" #include "mpValue.h" #include "mpError.h" MUP_NAMESPACE_START //----------------------------------------------------------------------------------------------- class OprtStrAdd : public IOprtBin { public: OprtStrAdd(); virtual void Eval(ptr_val_type& ret, const ptr_val_type *arg, int argc) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; //----------------------------------------------------------------------------------------------- /** \brief Callback object for testing if two values are equal. \ingroup binop */ class OprtEQ : public IOprtBin { public: OprtEQ(); virtual void Eval(ptr_val_type& ret, const ptr_val_type *a_pArg, int) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; //------------------------------------------------------------------------------ /** \brief Callback object for testing if two values are not equal. \ingroup binop */ class OprtNEQ : public IOprtBin { public: OprtNEQ(); virtual void Eval(ptr_val_type& ret, const ptr_val_type *a_pArg, int) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; //------------------------------------------------------------------------------ /** \brief Callback object class for the "Less than" operator. \ingroup binop */ class OprtLT : public IOprtBin { public: OprtLT(); virtual void Eval(ptr_val_type& ret, const ptr_val_type *a_pArg, int) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; //------------------------------------------------------------------------------ /** \brief Callback object class for the "Greater than" operator. \ingroup binop */ class OprtGT : public IOprtBin { public: OprtGT(); virtual void Eval(ptr_val_type& ret, const ptr_val_type *a_pArg, int) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; //------------------------------------------------------------------------------ /** \brief Callback object class for the "Less or equal" operator. \ingroup binop */ class OprtLE : public IOprtBin { public: OprtLE(); virtual void Eval(ptr_val_type& ret, const ptr_val_type *a_pArg, int) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; //------------------------------------------------------------------------------ /** \brief Callback object class for the "Greater or or equal" operator. \ingroup binop */ class OprtGE : public IOprtBin { public: OprtGE(); virtual void Eval(ptr_val_type& ret, const ptr_val_type *a_pArg, int) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; //------------------------------------------------------------------------------ /** \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) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; //------------------------------------------------------------------------------ /** \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) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; //------------------------------------------------------------------------------ /** \brief Callback class for a logical or operator. \ingroup binop */ class OprtLogicOr : public IOprtBin { public: OprtLogicOr(const char_type* szIdent = _T("||")); virtual void Eval(ptr_val_type& ret, const ptr_val_type* a_pArg, int) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; //------------------------------------------------------------------------------ /** \brief Callback class for a logical and operator. \ingroup binop */ class OprtLogicAnd : public IOprtBin { public: OprtLogicAnd(const char_type* szIdent = _T("&&")); virtual void Eval(ptr_val_type& ret, const ptr_val_type* a_pArg, int) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; //------------------------------------------------------------------------------ /** \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) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; //------------------------------------------------------------------------------ /** \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) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; //--------------------------------------------------------------------------- /** \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) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; // 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) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; // class OprtCastToInt } // namespace mu #endif muparserx-4.0.11/parser/mpOprtBinShortcut.cpp000066400000000000000000000100171414723276500213030ustar00rootroot00000000000000/* __________ ____ ___ _____ __ _\______ \_____ _______ ______ __________\ \/ / / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ / | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \ \/ \/ \/ \/ \_/ Copyright (C) 2021 Ingo Berg, et al. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "mpOprtBinShortcut.h" MUP_NAMESPACE_START //----------------------------------------------------------------------------------------------- // // class OprtShortcutLogicOrBegin // //----------------------------------------------------------------------------------------------- OprtShortcutLogicOrBegin::OprtShortcutLogicOrBegin(const char_type* szIdent) :IOprtBinShortcut(cmSHORTCUT_BEGIN, szIdent, (int)prLOGIC_OR, oaLEFT) {} //----------------------------------------------------------------------------------------------- IToken* OprtShortcutLogicOrBegin::Clone() const { return new OprtShortcutLogicOrBegin(*this); } //----------------------------------------------------------------------------------------------- // // class OprtShortcutLogicOrEnd // //----------------------------------------------------------------------------------------------- OprtShortcutLogicOrEnd::OprtShortcutLogicOrEnd(const char_type* szIdent) :IOprtBinShortcut(cmSHORTCUT_END, szIdent, (int)prLOGIC_OR, oaLEFT) {} //----------------------------------------------------------------------------------------------- IToken* OprtShortcutLogicOrEnd::Clone() const { return new OprtShortcutLogicOrEnd(*this); } //----------------------------------------------------------------------------------------------- // // class OprtShortcutLogicAndBegin // //----------------------------------------------------------------------------------------------- OprtShortcutLogicAndBegin::OprtShortcutLogicAndBegin(const char_type* szIdent) :IOprtBinShortcut(cmSHORTCUT_BEGIN, szIdent, (int)prLOGIC_AND, oaLEFT) {} //----------------------------------------------------------------------------------------------- IToken* OprtShortcutLogicAndBegin::Clone() const { return new OprtShortcutLogicAndBegin(*this); } //----------------------------------------------------------------------------------------------- // // class OprtShortcutLogicAndEnd // //----------------------------------------------------------------------------------------------- OprtShortcutLogicAndEnd::OprtShortcutLogicAndEnd(const char_type* szIdent) :IOprtBinShortcut(cmSHORTCUT_END, szIdent, (int)prLOGIC_AND, oaLEFT) {} //----------------------------------------------------------------------------------------------- IToken* OprtShortcutLogicAndEnd::Clone() const { return new OprtShortcutLogicAndEnd(*this); } }muparserx-4.0.11/parser/mpOprtBinShortcut.h000066400000000000000000000066001414723276500207530ustar00rootroot00000000000000 /* __________ ____ ___ _____ __ _\______ \_____ _______ ______ __________\ \/ / / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ / | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \ \/ \/ \/ \/ \_/ Copyright (C) 2021, Ingo Berg, et al. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef MP_SC_OPRT_BIN_H #define MP_SC_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 #include "mpIOprtBinShortcut.h" #include "mpValue.h" #include "mpError.h" MUP_NAMESPACE_START //------------------------------------------------------------------------------ /** \brief Callback class for a logical or operator. begin \ingroup binop */ class OprtShortcutLogicOrBegin : public IOprtBinShortcut { public: OprtShortcutLogicOrBegin(const char_type* szIdent = _T("||")); virtual IToken* Clone() const override; }; //------------------------------------------------------------------------------ /** \brief Callback class for a logical or operator. end \ingroup binop */ class OprtShortcutLogicOrEnd : public IOprtBinShortcut { public: OprtShortcutLogicOrEnd(const char_type* szIdent = _T("||")); virtual IToken* Clone() const override; }; //------------------------------------------------------------------------------ /** \brief Callback class for a logical and operator. begin \ingroup binop */ class OprtShortcutLogicAndBegin : public IOprtBinShortcut { public: OprtShortcutLogicAndBegin(const char_type* szIdent = _T("&&")); virtual IToken* Clone() const override; }; //------------------------------------------------------------------------------ /** \brief Callback class for a logical and operator. begin \ingroup binop */ class OprtShortcutLogicAndEnd : public IOprtBinShortcut { public: OprtShortcutLogicAndEnd(const char_type* szIdent = _T("&&")); virtual IToken* Clone() const override; }; } // namespace mu #endif muparserx-4.0.11/parser/mpOprtCmplx.cpp000066400000000000000000000263421414723276500201320ustar00rootroot00000000000000/* __________ ____ ___ _____ __ _\______ \_____ _______ ______ __________\ \/ / / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ / | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \ \/ \/ \/ \/ \_/ Copyright (C) 2016 Ingo Berg All rights reserved. muParserX - A C++ math parser library with array and string support Copyright (c) 2016, Ingo Berg All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "mpOprtCmplx.h" #include #include MUP_NAMESPACE_START //------------------------------------------------------------------------------------------------- // // class OprtSignCmplx // //------------------------------------------------------------------------------------------------- OprtSignCmplx::OprtSignCmplx() :IOprtInfix(_T("-"), prINFIX) {} //----------------------------------------------------------------------------------------------- void OprtSignCmplx::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc) { MUP_VERIFY(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() * (float_type)-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("negative sign operator"); } //----------------------------------------------------------------------------------------------- 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); if (arg[0]->IsComplex() || arg[1]->IsComplex() || (arg[0]->GetFloat() < 0 && !arg[1]->IsInteger())) { *ret = std::pow(arg[0]->GetComplex(), arg[1]->GetComplex());; } else { *ret = std::pow(arg[0]->GetFloat(), arg[1]->GetFloat()); } } //----------------------------------------------------------------------------------------------- const char_type* OprtPowCmplx::GetDesc() const { return _T("raise x to the power of y"); } //----------------------------------------------------------------------------------------------- IToken* OprtPowCmplx::Clone() const { return new OprtPowCmplx(*this); } } // namespace muparserx-4.0.11/parser/mpOprtCmplx.h000066400000000000000000000117201414723276500175710ustar00rootroot00000000000000/* __________ ____ ___ _____ __ _\______ \_____ _______ ______ __________\ \/ / / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ / | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \ \/ \/ \/ \/ \_/ Copyright (C) 2016, Ingo Berg All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #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 #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) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; // 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) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; //------------------------------------------------------------------------------ /** \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) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; //------------------------------------------------------------------------------ /** \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) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; //------------------------------------------------------------------------------ /** \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) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; //------------------------------------------------------------------------------ /** \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) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; } // namespace mu #endif muparserx-4.0.11/parser/mpOprtIndex.cpp000066400000000000000000000116661414723276500201210ustar00rootroot00000000000000/* __________ ____ ___ _____ __ _\______ \_____ _______ ______ __________\ \/ / / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ / | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \ \/ \/ \/ \/ \_/ Copyright (C) 2016, Ingo Berg All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "mpOprtIndex.h" #include "mpVariable.h" MUP_NAMESPACE_START //----------------------------------------------------------------------------------------------- // // class OprtIndex // //----------------------------------------------------------------------------------------------- OprtIndex::OprtIndex() :ICallback(cmIC, _T("Index operator"), -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::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc) { try { int rows = a_pArg[-1]->GetRows(); int cols = a_pArg[-1]->GetCols(); bool bArgIsVariable = a_pArg[-1]->IsVariable(); // If the index operator is applied to a variable the return value is also a variable // pointing to a specific cell in the matrix. If the operator is applied to a value // the return value is also a value. switch (a_iArgc) { case 1: if (cols == 1) { if (bArgIsVariable) ret.Reset(new Variable(&(ret->At(*a_pArg[0], Value(0.0))))); else *ret = ret->At(*a_pArg[0], Value(0.0)); } else if (rows == 1) { if (bArgIsVariable) ret.Reset(new Variable(&(ret->At(Value(0.0), *a_pArg[0])))); else *ret = ret->At(Value(0.0), *a_pArg[0]); } else { throw ParserError(ErrorContext(ecINDEX_DIMENSION, -1, GetIdent())); } break; case 2: if (bArgIsVariable) ret.Reset(new Variable(&(ret->At(*a_pArg[0], *a_pArg[1])))); else *ret = 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 muparserx-4.0.11/parser/mpOprtIndex.h000066400000000000000000000052311414723276500175550ustar00rootroot00000000000000/* __________ ____ ___ _____ __ _\______ \_____ _______ ______ __________\ \/ / / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ / | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \ \/ \/ \/ \/ \_/ Copyright (C) 2016, Ingo Berg All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #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 #include "mpIOprt.h" #include "mpValue.h" #include "mpError.h" MUP_NAMESPACE_START //----------------------------------------------------------------------------------------------- /** \brief Default implementation of a multidimensional index operator. */ class OprtIndex : public ICallback { public: OprtIndex(); virtual void Eval(ptr_val_type& ret, const ptr_val_type *arg, int argc) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; MUP_NAMESPACE_END #endif muparserx-4.0.11/parser/mpOprtMatrix.cpp000066400000000000000000000147341414723276500203150ustar00rootroot00000000000000/* __________ ____ ___ _____ __ _\______ \_____ _______ ______ __________\ \/ / / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ / | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \ \/ \/ \/ \/ \_/ Copyright (C) 2016, Ingo Berg All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "mpOprtMatrix.h" MUP_NAMESPACE_START //------------------------------------------------------------------------------------------------- // // class OprtTranspose // //------------------------------------------------------------------------------------------------- OprtTranspose::OprtTranspose() :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 OprtCreateArray // //----------------------------------------------------------------------------------------------- OprtCreateArray::OprtCreateArray() :ICallback(cmCBC, _T("Array constructor"), -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 OprtCreateArray::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc) { try { // The index is -1. if (a_iArgc <= 0) { throw ParserError(ErrorContext(ecINVALID_PARAMETER, -1, GetIdent())); } matrix_type m(a_iArgc, 1, 0.0); for (int i = 0; i < a_iArgc; ++i) { if (a_pArg[i]->GetDim() != 0) { // Prevent people from using this constructor for matrix creation. // This would not work as expected and i dont't want them // to get used to awkward workarounds. It's just not working right now ok? ErrorContext errc(ecINVALID_PARAMETER, -1, GetIdent()); errc.Arg = i+1; throw ParserError(errc); } m.At(i) = *a_pArg[i]; } m.Transpose(); *ret = m; } catch (ParserError &exc) { exc.GetContext().Pos = GetExprPos(); throw exc; } } //----------------------------------------------------------------------------------------------- const char_type* OprtCreateArray::GetDesc() const { return _T("{,} - Array construction operator."); } //----------------------------------------------------------------------------------------------- IToken* OprtCreateArray::Clone() const { return new OprtCreateArray(*this); } //----------------------------------------------------------- // // class OprtColon // //----------------------------------------------------------- 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 = (int)(argMax->GetFloat() - argMin->GetFloat()) + 1; matrix_type arr(n); for (int i=0; iGetFloat() + i; *ret = arr; } //----------------------------------------------------------- const char_type* OprtColon::GetDesc() const { return _T(": - Colon operator"); } //----------------------------------------------------------- IToken* OprtColon::Clone() const { return new OprtColon(*this); } MUP_NAMESPACE_END muparserx-4.0.11/parser/mpOprtMatrix.h000066400000000000000000000064571414723276500177650ustar00rootroot00000000000000/* __________ ____ ___ _____ __ _\______ \_____ _______ ______ __________\ \/ / / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ / | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \ \/ \/ \/ \/ \_/ Copyright (C) 2016, Ingo Berg All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef MP_OPRT_MATRIX_H #define MP_OPRT_MATRIX_H /** \file \brief Definitions of classes used as callbacks for matrix operators. */ #include #include "mpIOprt.h" #include "mpValue.h" #include "mpError.h" MUP_NAMESPACE_START //----------------------------------------------------------------------------------------------- class OprtTranspose : public IOprtPostfix { public: OprtTranspose(); virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; //----------------------------------------------------------------------------------------------- /** \brief On the fly array creation using the curly bracket operator. */ class OprtCreateArray : public ICallback { public: OprtCreateArray(); virtual void Eval(ptr_val_type& ret, const ptr_val_type *arg, int argc) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; //----------------------------------------------------------------------------------------------- class OprtColon : public IOprtBin { public: OprtColon(); virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; MUP_NAMESPACE_END #endif muparserx-4.0.11/parser/mpOprtNonCmplx.cpp000066400000000000000000000323271414723276500206050ustar00rootroot00000000000000/* __________ ____ ___ _____ __ _\______ \_____ _______ ______ __________\ \/ / / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ / | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \ \/ \/ \/ \/ \_/ Copyright (C) 2016 Ingo Berg All rights reserved. muParserX - A C++ math parser library with array and string support Copyright (c) 2016, Ingo Berg All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "mpOprtNonCmplx.h" MUP_NAMESPACE_START //------------------------------------------------------------------------------ // // Sign operator // //------------------------------------------------------------------------------ OprtSign::OprtSign() :IOprtInfix( _T("-"), prINFIX) {} //------------------------------------------------------------------------------ void OprtSign::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc) { MUP_VERIFY(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; iGetRows(); ++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("-x - negative sign operator"); } //------------------------------------------------------------------------------ IToken* OprtSign::Clone() const { return new OprtSign(*this); } //------------------------------------------------------------------------------ // // Sign operator // //------------------------------------------------------------------------------ OprtSignPos::OprtSignPos() :IOprtInfix( _T("+"), prINFIX) {} //------------------------------------------------------------------------------ void OprtSignPos::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc) { MUP_VERIFY(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; iGetRows(); ++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* OprtSignPos::GetDesc() const { return _T("+x - positive sign operator"); } //------------------------------------------------------------------------------ IToken* OprtSignPos::Clone() const { return new OprtSignPos(*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; iIsNonComplexScalar()) 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; iIsNonComplexScalar()) 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; iGetType()=='m' && arg2->IsNonComplexScalar()) { // Skalar * Vector matrix_type out(a_pArg[0]->GetArray()); for (int i=0; iGetFloat(); *ret = out; } else if (arg2->GetType()=='m' && arg1->IsNonComplexScalar()) { // Vector * Skalar matrix_type out(arg2->GetArray()); for (int i=0; iGetFloat(); *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 = std::pow(a, ib); return; } } else *ret = std::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); } } muparserx-4.0.11/parser/mpOprtNonCmplx.h000066400000000000000000000127561414723276500202560ustar00rootroot00000000000000/* __________ ____ ___ _____ __ _\______ \_____ _______ ______ __________\ \/ / / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ / | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \ \/ \/ \/ \/ \_/ Copyright (C) 2016, Ingo Berg All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #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 #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) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; // class OprtSign //--------------------------------------------------------------------------- /** \brief Callback for the positive sign operator for noncomplex values. \ingroup infix */ class OprtSignPos : public IOprtInfix { public: OprtSignPos(); virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; // class OprtSignPos //------------------------------------------------------------------------------ /** \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) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; //------------------------------------------------------------------------------ /** \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) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; //------------------------------------------------------------------------------ /** \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) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; //------------------------------------------------------------------------------ /** \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) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; //------------------------------------------------------------------------------ /** \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) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; } // namespace mu #endif muparserx-4.0.11/parser/mpOprtPostfixCommon.cpp000077500000000000000000000063351414723276500216570ustar00rootroot00000000000000#include #include "mpOprtPostfixCommon.h" MUP_NAMESPACE_START //----------------------------------------------------------- // // class OprtFact // //----------------------------------------------------------- OprtFact::OprtFact() :IOprtPostfix(_T("!")) {} //----------------------------------------------------------- void OprtFact::Eval(ptr_val_type& ret, const ptr_val_type *arg, int) { if (!arg[0]->IsInteger()) throw ParserError(ErrorContext(ecTYPE_CONFLICT_FUN, GetExprPos(), GetIdent(), arg[0]->GetType(), 'i', 1)); int_type input = arg[0]->GetInteger(); float_type input_long = float_type(input); if (input < 0) { throw ParserError(ErrorContext(ecDOMAIN_ERROR, GetExprPos(), GetIdent())); } float_type result = 1; for (float_type i = 1.0; i <= input_long; i += 1.0) { result *= i; // Only throw exceptions if IEEE 754 is not supported. The // Prefered way of dealing with overflows is relying on: // // http://en.wikipedia.org/wiki/IEEE_754-1985 // // If the compiler does not support IEEE 754, chances are // you are running on a pretty fucked up system. // #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable:4127) #endif /* _MSC_VER */ if ( !std::numeric_limits::is_iec559 && (result>std::numeric_limits::max() || result < 1.0) ) #ifdef _MSC_VER #pragma warning(pop) #endif /* _MSC_VER */ { throw ParserError(ErrorContext(ecOVERFLOW, GetExprPos(), GetIdent())); } // } *ret = result; } //----------------------------------------------------------- const char_type* OprtFact::GetDesc() const { return _T("x! - Returns factorial of a non-negative integer."); } //----------------------------------------------------------- IToken* OprtFact::Clone() const { return new OprtFact(*this); } //----------------------------------------------------------- // // class OprtPercentage // //----------------------------------------------------------- OprtPercentage::OprtPercentage() :IOprtPostfix(_T("%")) {} //----------------------------------------------------------- void OprtPercentage::Eval(ptr_val_type& ret, const ptr_val_type *arg, int) { switch (arg[0]->GetType()) { case 'i': case 'f': { float_type input = arg[0]->GetFloat(); *ret = input / 100.0; break; } default: throw ParserError(ErrorContext(ecTYPE_CONFLICT_FUN, GetExprPos(), GetIdent(), arg[0]->GetType(), 'f', 1)); break; } } //----------------------------------------------------------- const char_type* OprtPercentage::GetDesc() const { return _T("x% - Returns percentage of integer/float."); } //----------------------------------------------------------- IToken* OprtPercentage::Clone() const { return new OprtPercentage(*this); } } muparserx-4.0.11/parser/mpOprtPostfixCommon.h000077500000000000000000000024561414723276500213240ustar00rootroot00000000000000#ifndef MP_OPRT_POSTFIX_COMMON_H #define MP_OPRT_POSTFIX_COMMON_H /** \file \brief Definitions of classes used as callbacks for standard postfix operators. */ /** \defgroup postop Postfix operator callbacks This group lists the objects representing the postfix operators of muParserX. */ #include "mpIOprt.h" #include "mpValue.h" #include "mpError.h" MUP_NAMESPACE_START //------------------------------------------------------------------------------ /** \brief Calculate factorial of a non-negative integer. \ingroup postop */ class OprtFact : public IOprtPostfix { public: OprtFact(); virtual void Eval(ptr_val_type& ret, const ptr_val_type *arg, int) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; //------------------------------------------------------------------------------ /** \brief Returns percentage of given number. \ingroup postop */ class OprtPercentage : public IOprtPostfix { public: OprtPercentage(); virtual void Eval(ptr_val_type& ret, const ptr_val_type *arg, int) override; virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; } // namespace mu #endif muparserx-4.0.11/parser/mpPackageCmplx.cpp000066400000000000000000000100051414723276500205260ustar00rootroot00000000000000/* __________ ____ ___ _____ __ _\______ \_____ _______ ______ __________\ \/ / / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ / | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \ \/ \/ \/ \/ \_/ Copyright (C) 2016, Ingo Berg All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "mpPackageCmplx.h" #include "mpParserBase.h" #include "mpFuncCmplx.h" #include "mpOprtCmplx.h" #include "mpOprtBinCommon.h" MUP_NAMESPACE_START //------------------------------------------------------------------------------ std::unique_ptr PackageCmplx::s_pInstance; //------------------------------------------------------------------------------ IPackage* PackageCmplx::Instance() { if (s_pInstance.get()==nullptr) { 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()); pParser->DefineFun(new FunCmplxPow()); // 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 muparserx-4.0.11/parser/mpPackageCmplx.h000066400000000000000000000047521414723276500202070ustar00rootroot00000000000000#ifndef MU_PACKAGE_CMPLX_H #define MU_PACKAGE_CMPLX_H /* __________ ____ ___ _____ __ _\______ \_____ _______ ______ __________\ \/ / / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ / | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \ \/ \/ \/ \/ \_/ Copyright (C) 2016, Ingo Berg All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include "mpIPackage.h" #include "mpIOprt.h" MUP_NAMESPACE_START //------------------------------------------------------------------------------ /** \brief Package for installing complex functions and operators. */ class PackageCmplx: public IPackage { friend class std::unique_ptr; public: static IPackage* Instance(); virtual void AddToParser(ParserXBase *pParser); virtual string_type GetDesc() const; virtual string_type GetPrefix() const; private: static std::unique_ptr s_pInstance; }; MUP_NAMESPACE_END #endif muparserx-4.0.11/parser/mpPackageCommon.cpp000066400000000000000000000122471414723276500207050ustar00rootroot00000000000000/* __________ ____ ___ _____ __ _\______ \_____ _______ ______ __________\ \/ / / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ / | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \ \/ \/ \/ \/ \_/ Copyright (C) 2016, Ingo Berg All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "mpPackageCommon.h" #include "mpParserBase.h" #include "mpFuncNonCmplx.h" #include "mpFuncCommon.h" #include "mpOprtBinCommon.h" #include "mpOprtBinShortcut.h" #include "mpOprtBinAssign.h" #include "mpOprtPostfixCommon.h" #include "mpValReader.h" /** \brief Pi (what else?). */ #define MUP_CONST_PI 3.141592653589793238462643 //#define MUP_CONST_PI 3.14159265358979323846264338327950288419716939937510L /** \brief The eulerian number. */ #define MUP_CONST_E 2.718281828459045235360287 MUP_NAMESPACE_START //------------------------------------------------------------------------------ std::unique_ptr PackageCommon::s_pInstance; //------------------------------------------------------------------------------ IPackage* PackageCommon::Instance() { if (s_pInstance.get() == nullptr) { 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 BinValReader); pParser->AddValueReader(new DblValReader); pParser->AddValueReader(new BoolValReader); // 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 OprtLogicAnd); // pParser->DefineOprt(new OprtLogicOr); 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 OprtLogicAnd(_T("and"))); // add logic and with a different identifier // pParser->DefineOprt(new OprtLogicOr(_T("or"))); // add logic and with a different identifier // 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); // postfix operators pParser->DefinePostfixOprt(new OprtFact); // locic short circit operators pParser->DefineOprt(new OprtShortcutLogicOrBegin); pParser->DefineOprt(new OprtShortcutLogicOrBegin(_T("or"))); pParser->DefineOprt(new OprtShortcutLogicAndBegin); pParser->DefineOprt(new OprtShortcutLogicAndBegin(_T("and"))); } //------------------------------------------------------------------------------ string_type PackageCommon::GetDesc() const { return _T(""); } //------------------------------------------------------------------------------ string_type PackageCommon::GetPrefix() const { return _T(""); } MUP_NAMESPACE_END muparserx-4.0.11/parser/mpPackageCommon.h000066400000000000000000000050511414723276500203450ustar00rootroot00000000000000#ifndef MU_PACKAGE_COMMON_H #define MU_PACKAGE_COMMON_H /* __________ ____ ___ _____ __ _\______ \_____ _______ ______ __________\ \/ / / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ / | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \ \/ \/ \/ \/ \_/ Copyright (C) 2016, Ingo Berg All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #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::unique_ptr; public: static IPackage* Instance(); virtual void AddToParser(ParserXBase *pParser) override; virtual string_type GetDesc() const override; virtual string_type GetPrefix() const override; private: static std::unique_ptr s_pInstance; }; MUP_NAMESPACE_END #endif muparserx-4.0.11/parser/mpPackageMatrix.cpp000066400000000000000000000063401414723276500207160ustar00rootroot00000000000000/* __________ ____ ___ _____ __ _\______ \_____ _______ ______ __________\ \/ / / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ / | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \ \/ \/ \/ \/ \_/ Copyright (C) 2016, Ingo Berg All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "mpPackageMatrix.h" #include "mpParserBase.h" #include "mpFuncMatrix.h" #include "mpOprtMatrix.h" MUP_NAMESPACE_START //------------------------------------------------------------------------------ std::unique_ptr PackageMatrix::s_pInstance; //------------------------------------------------------------------------------ IPackage* PackageMatrix::Instance() { if (s_pInstance.get()==nullptr) { s_pInstance.reset(new PackageMatrix); } return s_pInstance.get(); } //------------------------------------------------------------------------------ void PackageMatrix::AddToParser(ParserXBase *pParser) { // Matrix functions pParser->DefineFun(new FunMatrixOnes()); pParser->DefineFun(new FunMatrixZeros()); pParser->DefineFun(new FunMatrixEye()); pParser->DefineFun(new FunMatrixSize()); // Matrix Operators pParser->DefinePostfixOprt(new OprtTranspose()); // Colon operator //pParser->DefineOprt(new OprtColon()); //pParser->DefineAggregator(new AggColon()); } //------------------------------------------------------------------------------ string_type PackageMatrix::GetDesc() const { return _T("Operators and functions for matrix operations"); } //------------------------------------------------------------------------------ string_type PackageMatrix::GetPrefix() const { return _T(""); } MUP_NAMESPACE_END muparserx-4.0.11/parser/mpPackageMatrix.h000066400000000000000000000047601414723276500203670ustar00rootroot00000000000000#ifndef MU_PACKAGE_MATRIX_H #define MU_PACKAGE_MATRIX_H /* __________ ____ ___ _____ __ _\______ \_____ _______ ______ __________\ \/ / / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ / | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \ \/ \/ \/ \/ \_/ Copyright (C) 2016, Ingo Berg All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include "mpIPackage.h" #include "mpIOprt.h" MUP_NAMESPACE_START //------------------------------------------------------------------------------ /** \brief Package for installing complex functions and operators. */ class PackageMatrix : public IPackage { friend class std::unique_ptr; public: static IPackage* Instance(); virtual void AddToParser(ParserXBase *pParser); virtual string_type GetDesc() const; virtual string_type GetPrefix() const; private: static std::unique_ptr s_pInstance; }; MUP_NAMESPACE_END #endif muparserx-4.0.11/parser/mpPackageNonCmplx.cpp000066400000000000000000000101551414723276500212070ustar00rootroot00000000000000/* __________ ____ ___ _____ __ _\______ \_____ _______ ______ __________\ \/ / / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ / | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \ \/ \/ \/ \/ \_/ Copyright (C) 2016, Ingo Berg All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "mpPackageNonCmplx.h" #include "mpParserBase.h" #include "mpFuncNonCmplx.h" #include "mpOprtNonCmplx.h" #include "mpOprtBinCommon.h" MUP_NAMESPACE_START //------------------------------------------------------------------------------ std::unique_ptr PackageNonCmplx::s_pInstance; //------------------------------------------------------------------------------ IPackage* PackageNonCmplx::Instance() { if (s_pInstance.get()==nullptr) { 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 FunCbrt()); pParser->DefineFun(new FunAbs()); // binary functions pParser->DefineFun(new FunPow()); pParser->DefineFun(new FunHypot()); pParser->DefineFun(new FunAtan2()); pParser->DefineFun(new FunFmod()); pParser->DefineFun(new FunRemainder()); // Operator callbacks pParser->DefineInfixOprt(new OprtSign()); pParser->DefineInfixOprt(new OprtSignPos()); 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 muparserx-4.0.11/parser/mpPackageNonCmplx.h000066400000000000000000000047751414723276500206670ustar00rootroot00000000000000#ifndef MU_PACKAGE_NON_CMPLX_H #define MU_PACKAGE_NON_CMPLX_H /* __________ ____ ___ _____ __ _\______ \_____ _______ ______ __________\ \/ / / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ / | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \ \/ \/ \/ \/ \_/ Copyright (C) 2016, Ingo Berg All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include "mpIPackage.h" #include "mpIOprt.h" MUP_NAMESPACE_START //------------------------------------------------------------------------------ /** \brief Package for installing complex functions and operators. */ class PackageNonCmplx: public IPackage { friend class std::unique_ptr; public: static IPackage* Instance(); virtual void AddToParser(ParserXBase *pParser); virtual string_type GetDesc() const; virtual string_type GetPrefix() const; private: static std::unique_ptr s_pInstance; }; MUP_NAMESPACE_END #endif muparserx-4.0.11/parser/mpPackageStr.cpp000066400000000000000000000061671414723276500202310ustar00rootroot00000000000000/* __________ ____ ___ _____ __ _\______ \_____ _______ ______ __________\ \/ / / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ / | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \ \/ \/ \/ \/ \_/ Copyright (C) 2016, Ingo Berg All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "mpPackageStr.h" #include "mpParserBase.h" #include "mpFuncStr.h" #include "mpOprtBinCommon.h" #include "mpValReader.h" MUP_NAMESPACE_START //------------------------------------------------------------------------------ std::unique_ptr PackageStr::s_pInstance; //------------------------------------------------------------------------------ IPackage* PackageStr::Instance() { if (s_pInstance.get()==nullptr) { 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()); pParser->DefineFun(new FunStrToLower()); // 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 muparserx-4.0.11/parser/mpPackageStr.h000066400000000000000000000047511414723276500176730ustar00rootroot00000000000000#ifndef MU_PACKAGE_STR_H #define MU_PACKAGE_STR_H /* __________ ____ ___ _____ __ _\______ \_____ _______ ______ __________\ \/ / / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ / | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \ \/ \/ \/ \/ \_/ Copyright (C) 2016, Ingo Berg All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #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::unique_ptr; public: static IPackage* Instance(); virtual void AddToParser(ParserXBase *pParser); virtual string_type GetDesc() const; virtual string_type GetPrefix() const; private: static std::unique_ptr s_pInstance; }; MUP_NAMESPACE_END #endif muparserx-4.0.11/parser/mpPackageUnit.cpp000066400000000000000000000133721414723276500203740ustar00rootroot00000000000000/* __________ ____ ___ _____ __ _\______ \_____ _______ ______ __________\ \/ / / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ / | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \ \/ \/ \/ \/ \_/ Copyright (C) 2016, Ingo Berg All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #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*) \ :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, "u", (float_type)1e-6, "u - 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::unique_ptr PackageUnit::s_pInstance; //------------------------------------------------------------------------------ IPackage* PackageUnit::Instance() { if (s_pInstance.get()==nullptr) { 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 muparserx-4.0.11/parser/mpPackageUnit.h000066400000000000000000000064631414723276500200440ustar00rootroot00000000000000#ifndef MU_PACKAGE_UNIT_H #define MU_PACKAGE_UNIT_H /* __________ ____ ___ _____ __ _\______ \_____ _______ ______ __________\ \/ / / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ / | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \ \/ \/ \/ \/ \_/ Copyright (C) 2016, Ingo Berg All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include "mpIPackage.h" #include "mpIOprt.h" MUP_NAMESPACE_START #define MUP_POSTFIX_DEF(CLASS) \ class CLASS : public IOprtPostfix \ { \ public: \ CLASS(IPackage* pPackage=nullptr); \ 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::unique_ptr; public: static IPackage* Instance(); virtual void AddToParser(ParserXBase *pParser); virtual string_type GetDesc() const; virtual string_type GetPrefix() const; private: static std::unique_ptr s_pInstance; }; MUP_NAMESPACE_END #endif muparserx-4.0.11/parser/mpParser.cpp000066400000000000000000000072041414723276500174320ustar00rootroot00000000000000/* __________ ____ ___ _____ __ _\______ \_____ _______ ______ __________\ \/ / / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ / | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \ \/ \/ \/ \/ \_/ Copyright (C) 2016, Ingo Berg All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "mpParser.h" //--- Standard includes ---------------------------------------------------- #include #include #include //--- 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(unsigned 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()); } //------------------------------------------------------------------------------ void ParserX::ResetErrorMessageProvider(ParserMessageProviderBase *pProvider) { ParserErrorMsg::Reset(pProvider); } } // namespace mu muparserx-4.0.11/parser/mpParser.h000066400000000000000000000047751414723276500171110ustar00rootroot00000000000000#ifndef MUP_PARSERX_H #define MUP_PARSERX_H /** \file \brief Definition of the parser class
               __________                                 ____  ___
    _____  __ _\______   \_____ _______  ______ __________\   \/  /
   /     \|  |  \     ___/\__  \\_  __ \/  ___// __ \_  __ \     / 
  |  Y Y  \  |  /    |     / __ \|  | \/\___ \\  ___/|  | \/     \ 
  |__|_|  /____/|____|    (____  /__|  /____  >\___  >__| /___/\  \
        \/                     \/           \/     \/           \_/
                                       Copyright (C) 2016, Ingo Berg
                                       All rights reserved.

  Redistribution and use in source and binary forms, with or without 
  modification, are permitted provided that the following conditions are met:

   * Redistributions of source code must retain the above copyright notice, 
     this list of conditions and the following disclaimer.
   * Redistributions in binary form must reproduce the above copyright notice, 
     this list of conditions and the following disclaimer in the documentation 
     and/or other materials provided with the distribution.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
  POSSIBILITY OF SUCH DAMAGE.
*/ //--- 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(unsigned ePackages = pckALL_COMPLEX); static void ResetErrorMessageProvider(ParserMessageProviderBase *pProvider); }; } // namespace mu #endif muparserx-4.0.11/parser/mpParserBase.cpp000066400000000000000000001164011414723276500202250ustar00rootroot00000000000000/** \file \brief Implementation of the muParserX engine.
			   __________                                 ____  ___
	 _____  __ _\______   \_____ _______  ______ __________\   \/  /
	/     \|  |  \     ___/\__  \\_  __ \/  ___// __ \_  __ \     /
	|  Y Y  \  |  /    |     / __ \|  | \/\___ \\  ___/|  | \/     \
	|__|_|  /____/|____|    (____  /__|  /____  >\___  >__| /___/\  \
		  \/                     \/           \/     \/           \_/
	Copyright (C) 2021 Ingo Berg
	All rights reserved.

	Redistribution and use in source and binary forms, with or without
	modification, are permitted provided that the following conditions are met:

	* Redistributions of source code must retain the above copyright notice,
	this list of conditions and the following disclaimer.
	* Redistributions in binary form must reproduce the above copyright notice,
	this list of conditions and the following disclaimer in the documentation
	and/or other materials provided with the distribution.

	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
	ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
	WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
	IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
	INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
	NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
	PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
	WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
	POSSIBILITY OF SUCH DAMAGE.
	
*/ #include "mpParserBase.h" #include #include #include #include #include "utGeneric.h" #include "mpDefines.h" #include "mpIfThenElse.h" #include "mpScriptTokens.h" #include "mpOprtBinShortcut.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("CURLY BRCK. OPEN "), _T("CURLY BRCK. CLOSE"), _T("ARG_SEP "), _T("IF "), _T("ELSE "), _T("ENDIF "), _T("JMP "), _T("VAL "), _T("FUNC "), _T("OPRT_BIN "), _T("OPRT_IFX "), _T("OPRT_PFX "), _T("SC_BEGIN "), _T("SC_END "), _T("END "), _T("SCR_ENDL "), _T("SCR_CMT "), _T("SCR_WHILE "), _T("SCR_GOTO "), _T("SCR_LABEL "), _T("SCR_FOR "), _T("SCR_IF "), _T("SCR_ELSE "), _T("SCR_ELIF "), _T("SCR_ENDIF "), _T("SCR_FUNC "), _T("UNKNOWN "), nullptr }; //------------------------------------------------------------------------------ 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(","), _T("?"), _T(":"), 0 }; //------------------------------------------------------------------------------ /** \brief Default constructor. */ ParserXBase::ParserXBase() :m_FunDef() , m_PostOprtDef() , m_InfixOprtDef() , m_OprtDef() , m_OprtShortcutDef() , m_valDef() , m_varDef() , m_pParserEngine(&ParserXBase::ParseFromString) , m_pTokenReader() , m_valDynVarShadow() , m_sNameChars() , m_sOprtChars() , m_sInfixOprtChars() , 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_FunDef() , m_PostOprtDef() , m_InfixOprtDef() , m_OprtDef() , m_OprtShortcutDef() , m_valDef() , m_varDef() , m_pParserEngine(&ParserXBase::ParseFromString) , m_pTokenReader() , m_valDynVarShadow() , m_sNameChars() , m_sOprtChars() , m_sInfixOprtChars() , 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_OprtShortcutDef = ref.m_OprtShortcutDef; m_FunDef = ref.m_FunDef; m_PostOprtDef = ref.m_PostOprtDef; m_InfixOprtDef = ref.m_InfixOprtDef; m_valDef = ref.m_valDef; m_valDynVarShadow = ref.m_valDynVarShadow; m_varDef = ref.m_varDef; // Copy user defined variables // 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 { MUP_VERIFY(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 { MUP_VERIFY(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 { MUP_VERIFY(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(); m_nPos = 0; } //--------------------------------------------------------------------------- /** \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); } //--------------------------------------------------------------------------- /** \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 variable. \param a_sName The variable name \param a_Var The variable to be added to muParserX */ void ParserXBase::DefineVar(const string_type& ident, const Variable& var) { CheckName(ident, ValidNameChars()); CheckForEntityExistence(ident, ecVARIABLE_DEFINED); m_varDef[ident] = ptr_tok_type(var.Clone()); } void ParserXBase::CheckForEntityExistence(const string_type& ident, EErrorCodes error_code) { if (IsVarDefined(ident) || IsConstDefined(ident) || IsFunDefined(ident) || IsOprtDefined(ident) || IsPostfixOprtDefined(ident) || IsInfixOprtDefined(ident)) throw ParserError(ErrorContext(error_code, 0, ident)); } //--------------------------------------------------------------------------- /** \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& ident, const Value& val) { CheckName(ident, ValidNameChars()); CheckForEntityExistence(ident, ecCONSTANT_DEFINED); m_valDef[ident] = ptr_tok_type(val.Clone()); } //--------------------------------------------------------------------------- /** \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(const ptr_cal_type& fun) { if (IsFunDefined(fun->GetIdent())) throw ParserError(ErrorContext(ecFUNOPRT_DEFINED, 0, fun->GetIdent())); fun->SetParent(this); m_FunDef[fun->GetIdent()] = ptr_tok_type(fun->Clone()); } //--------------------------------------------------------------------------- /** \brief Define a binary operator. \param a_pCallback Pointer to the callback object */ void ParserXBase::DefineOprt(const TokenPtr& oprt) { if (IsOprtDefined(oprt->GetIdent())) throw ParserError(ErrorContext(ecFUNOPRT_DEFINED, 0, oprt->GetIdent())); oprt->SetParent(this); m_OprtDef[oprt->GetIdent()] = ptr_tok_type(oprt->Clone()); } //--------------------------------------------------------------------------- /** \brief Define a short circuit operator. \param a_pCallback Pointer to the callback object */ void ParserXBase::DefineOprt(const TokenPtr &oprt) { if (IsOprtDefined(oprt->GetIdent())) throw ParserError(ErrorContext(ecFUNOPRT_DEFINED, 0, oprt->GetIdent())); //oprt->SetParent(this); m_OprtShortcutDef[oprt->GetIdent()] = ptr_tok_type(oprt->Clone()); } //--------------------------------------------------------------------------- /** \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(const TokenPtr& oprt) { if (IsPostfixOprtDefined(oprt->GetIdent())) throw ParserError(ErrorContext(ecFUNOPRT_DEFINED, 0, oprt->GetIdent())); // Operator is not added yet, add it. oprt->SetParent(this); m_PostOprtDef[oprt->GetIdent()] = ptr_tok_type(oprt->Clone()); } //--------------------------------------------------------------------------- /** \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(const TokenPtr& oprt) { if (IsInfixOprtDefined(oprt->GetIdent())) throw ParserError(ErrorContext(ecFUNOPRT_DEFINED, 0, oprt->GetIdent())); // Function is not added yet, add it. oprt->SetParent(this); m_InfixOprtDef[oprt->GetIdent()] = ptr_tok_type(oprt->Clone()); } //--------------------------------------------------------------------------- void ParserXBase::RemoveVar(const string_type& ident) { m_varDef.erase(ident); ReInit(); } //--------------------------------------------------------------------------- void ParserXBase::RemoveConst(const string_type& ident) { m_valDef.erase(ident); ReInit(); } //--------------------------------------------------------------------------- void ParserXBase::RemoveFun(const string_type& ident) { m_FunDef.erase(ident); ReInit(); } //--------------------------------------------------------------------------- void ParserXBase::RemoveOprt(const string_type& ident) { m_OprtDef.erase(ident); m_OprtShortcutDef.erase(ident); ReInit(); } //--------------------------------------------------------------------------- void ParserXBase::RemovePostfixOprt(const string_type& ident) { m_PostOprtDef.erase(ident); ReInit(); } //--------------------------------------------------------------------------- void ParserXBase::RemoveInfixOprt(const string_type& ident) { m_InfixOprtDef.erase(ident); ReInit(); } //--------------------------------------------------------------------------- bool ParserXBase::IsVarDefined(const string_type& ident) const { return m_varDef.find(ident) != m_varDef.end(); } //--------------------------------------------------------------------------- bool ParserXBase::IsConstDefined(const string_type& ident) const { return m_valDef.find(ident) != m_valDef.end(); } //--------------------------------------------------------------------------- bool ParserXBase::IsFunDefined(const string_type& ident) const { return m_FunDef.find(ident) != m_FunDef.end(); } //--------------------------------------------------------------------------- bool ParserXBase::IsOprtDefined(const string_type& ident) const { return m_OprtDef.find(ident) != m_OprtDef.end() || m_OprtShortcutDef.find(ident) != m_OprtShortcutDef.end(); } //--------------------------------------------------------------------------- bool ParserXBase::IsPostfixOprtDefined(const string_type& ident) const { return m_PostOprtDef.find(ident) != m_PostOprtDef.end(); } //--------------------------------------------------------------------------- bool ParserXBase::IsInfixOprtDefined(const string_type& ident) const { return m_InfixOprtDef.find(ident) != m_InfixOprtDef.end(); } //--------------------------------------------------------------------------- /** \brief Return a map containing the used variables only. */ const var_maptype& ParserXBase::GetExprVar() const { utils::scoped_setter guard(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_valDef; } //--------------------------------------------------------------------------- /** \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& stOpt) const { while (stOpt.size() && stOpt.top()->GetCode() != cmBO && stOpt.top()->GetCode() != cmIO && stOpt.top()->GetCode() != cmCBO && stOpt.top()->GetCode() != cmIF) { ptr_tok_type& op = stOpt.top(); switch (op->GetCode()) { case cmOPRT_INFIX: case cmOPRT_BIN: ApplyFunc(stOpt, 2); break; case cmSHORTCUT_END: ApplyOprtShortcut(stOpt); break; case cmELSE: ApplyIfElse(stOpt); break; default: Error(ecINTERNAL_ERROR); } // switch operator token type } // While operator stack not empty } //--------------------------------------------------------------------------- /** \brief Simulates the call of 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& a_stOpt, 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; pFun->SetNumArgsPresent(iArgCount); m_nPos -= (iArgCount - 1); m_rpn.Add(tok); } void ParserXBase::ApplyOprtShortcut(Stack &a_stOpt) const { if (a_stOpt.empty()) return; ptr_tok_type tok = a_stOpt.pop(); m_nPos -= 1; m_rpn.Add(tok); } //--------------------------------------------------------------------------- /** \brief Simulates the effect of the execution of an if-then-else block. */ void ParserXBase::ApplyIfElse(Stack& a_stOpt) const { while (a_stOpt.size() && a_stOpt.top()->GetCode() == cmELSE) { MUP_VERIFY(a_stOpt.size() > 0); MUP_VERIFY(m_nPos >= 3); MUP_VERIFY(a_stOpt.top()->GetCode() == cmELSE); ptr_tok_type opElse = a_stOpt.pop(); ptr_tok_type opIf = a_stOpt.pop(); MUP_VERIFY(opElse->GetCode() == cmELSE) if (opIf->GetCode() != cmIF) { ErrorContext err; err.Expr = m_pTokenReader->GetExpr(); err.Errc = ecMISPLACED_COLON; err.Pos = m_pTokenReader->GetPos(); throw ParserError(err); } // If then else hat 3 argumente und erzeugt einen rückgabewert (3-1=2) m_nPos -= 2; 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 stOpt; Stack stArgCount; Stack stIdxCount; ptr_tok_type pTok, pTokPrev; Value val; ReInit(); for (;;) { pTokPrev = pTok; pTok = m_pTokenReader->ReadNextToken(); #if defined(MUP_DUMP_TOKENS) console() << pTok->AsciiDump() << endl; #endif ECmdCode eCmd = pTok->GetCode(); switch (eCmd) { case cmVAL: m_nPos++; m_rpn.Add(pTok); break; case cmCBC: case cmIC: { ECmdCode eStarter = (ECmdCode)(eCmd - 1); MUP_VERIFY(eStarter == cmCBO || eStarter == cmIO); // 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() != nullptr && pTokPrev->GetCode() == eStarter) --stArgCount.top(); ApplyRemainingOprt(stOpt); // if opt is "]" and opta is "[" the bracket content has been evaluated. // Now check whether there is an index operator on the stack. if (stOpt.size() && stOpt.top()->GetCode() == eStarter) { // // Find out how many dimensions were used in the index operator. // int iArgc = stArgCount.pop(); stOpt.pop(); // Take opening bracket from stack ICallback* pOprtIndex = pTok->AsICallback(); MUP_VERIFY(pOprtIndex != nullptr); pOprtIndex->SetNumArgsPresent(iArgc); m_rpn.Add(pOprtIndex); // If this is an index operator there must be something else in the register (the variable to index) MUP_VERIFY(eCmd != cmIC || m_nPos >= (int)iArgc + 1); // Reduce the index into the value registers accordingly m_nPos -= iArgc; if (eCmd == cmCBC) { ++m_nPos; } } // 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() != nullptr && pTokPrev->GetCode() == cmBO) --stArgCount.top(); ApplyRemainingOprt(stOpt); // 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(); 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); // Apply function, if present if (stOpt.size() && stOpt.top()->GetCode() != cmOPRT_INFIX && stOpt.top()->GetCode() != cmOPRT_BIN) { ApplyFunc(stOpt, iArgc); } } } break; case cmELSE: ApplyRemainingOprt(stOpt); m_rpn.Add(pTok); stOpt.push(pTok); break; case cmSCRIPT_NEWLINE: ApplyRemainingOprt(stOpt); m_rpn.AddNewline(pTok, m_nPos); stOpt.clear(); m_nPos = 0; break; case cmARG_SEP: if (stArgCount.empty()) Error(ecUNEXPECTED_COMMA, m_pTokenReader->GetPos() - 1); ++stArgCount.top(); ApplyRemainingOprt(stOpt); break; case cmEOE: ApplyRemainingOprt(stOpt); m_rpn.Finalize(); break; case cmIF: case cmOPRT_BIN: case cmSHORTCUT_BEGIN: { while (stOpt.size() && stOpt.top()->GetCode() != cmBO && stOpt.top()->GetCode() != cmIO && stOpt.top()->GetCode() != cmCBO && stOpt.top()->GetCode() != cmELSE && stOpt.top()->GetCode() != cmIF) { IToken* pOprt1 = stOpt.top().Get(); IToken* pOprt2 = pTok.Get(); MUP_VERIFY(pOprt1 != nullptr && pOprt2 != nullptr); MUP_VERIFY(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; } if (pOprt1->GetCode() == cmSHORTCUT_END) { ApplyOprtShortcut(stOpt); break; } // apply the operator now // (binary operators are identic to functions with two arguments) ApplyFunc(stOpt, 2); } // while ( ... ) if (pTok->GetCode() == cmIF || pTok->GetCode() == cmSHORTCUT_BEGIN) m_rpn.Add(pTok); if (pTok->GetCode() == cmSHORTCUT_BEGIN) { if(pTok->AsIPrecedence()->GetPri() == prLOGIC_OR) { stOpt.push(ptr_tok_type(new OprtShortcutLogicOrEnd)); } else { stOpt.push(ptr_tok_type(new OprtShortcutLogicAndEnd)); } } else { stOpt.push(pTok); } } break; // // Postfix Operators // case cmOPRT_POSTFIX: MUP_VERIFY(m_nPos); m_rpn.Add(pTok); break; case cmCBO: case cmIO: case cmBO: stOpt.push(pTok); stArgCount.push(1); break; // // Functions // case cmOPRT_INFIX: case cmFUNC: { ICallback* pFunc = pTok->AsICallback(); MUP_VERIFY(pFunc != nullptr); stOpt.push(pTok); } break; default: Error(ecINTERNAL_ERROR); } // switch Code if (ParserXBase::s_bDumpStack) { StackDump(stOpt); } if (pTok->GetCode() == cmEOE) break; } // for (all tokens) if (ParserXBase::s_bDumpRPN) { m_rpn.AsciiDump(); } if (m_nPos > 1) { Error(ecUNEXPECTED_COMMA, -1); } } //--------------------------------------------------------------------------- /** \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]; if (m_rpn.GetSize() == 0) { // Passiert bei leeren strings oder solchen, die nur Leerzeichen enthalten ErrorContext err; err.Expr = m_pTokenReader->GetExpr(); err.Errc = ecUNEXPECTED_EOF; err.Pos = 0; throw ParserError(err); } 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; continue; case cmVAL: { IValue* pVal = static_cast(pTok); sidx++; MUP_VERIFY(sidx < (int)m_vStackBuffer.size()); if (pVal->IsVariable()) { pStack[sidx].Reset(pVal); } else { ptr_val_type& val = pStack[sidx]; if (val->IsVariable()) val.Reset(m_cache.CreateFromCache()); *val = *(static_cast(pTok)); } } continue; case cmIC: { ICallback* pIdxOprt = static_cast(pTok); int nArgs = pIdxOprt->GetArgsPresent(); sidx -= nArgs - 1; MUP_VERIFY(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->Eval(val, &idx, nArgs); } continue; case cmCBC: case cmOPRT_POSTFIX: case cmFUNC: case cmOPRT_BIN: case cmOPRT_INFIX: { ICallback* pFun = static_cast(pTok); int nArgs = pFun->GetArgsPresent(); sidx -= nArgs - 1; // most likely cause: Comma in if-then-else sum(false?1,0,0:3) if (sidx < 0) { ErrorContext err; err.Expr = m_pTokenReader->GetExpr(); err.Errc = ecUNEXPECTED_COMMA; err.Pos = m_pTokenReader->GetPos(); throw ParserError(err); } ptr_val_type& val = pStack[sidx]; try { if (val->IsVariable()) { ptr_val_type buf(m_cache.CreateFromCache()); pFun->Eval(buf, &val, nArgs); val = buf; } else { pFun->Eval(val, &val, nArgs); } } catch (ParserError& exc) { // Not too happy about that: // Multiarg functions may throw specific error codes when evaluating. // These codes would be converted to ecEVAL here. I omit the conversion // for certain handpicked errors. (The reason this catch block exists is // that not all exceptions contain proper metadata when thrown out of // a function.) if (exc.GetCode() == ecTOO_FEW_PARAMS || exc.GetCode() == ecDOMAIN_ERROR || exc.GetCode() == ecOVERFLOW || exc.GetCode() == ecINVALID_NUMBER_OF_PARAMETERS || exc.GetCode() == ecASSIGNEMENT_TO_VALUE) { exc.GetContext().Pos = pFun->GetExprPos(); throw; } // else { 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 = ecMATRIX_DIMENSION_MISMATCH; err.Pos = pFun->GetExprPos(); throw ParserError(err); } } continue; case cmIF: MUP_VERIFY(sidx >= 0); if (pStack[sidx--]->GetBool() == false) i += static_cast(pTok)->GetOffset(); continue; case cmELSE: case cmJMP: i += static_cast(pTok)->GetOffset(); continue; case cmENDIF: continue; case cmSHORTCUT_BEGIN: if (pTok->AsIPrecedence()->GetPri() == prLOGIC_OR) { // occur short circuit feature if (pStack[sidx]->GetBool() == true) { i += static_cast(pTok)->GetOffset(); } else { // pop stack ,becuase this value had used --sidx; } } else // logic and { // occur short circuit feature if (pStack[sidx]->GetBool() == false) { i += static_cast(pTok)->GetOffset(); } else { // pop stack ,becuase this value had used --sidx; } } continue; case cmSHORTCUT_END: continue; default: Error(ecINTERNAL_ERROR); } // switch token } // for all RPN tokens return *pStack[0]; } //--------------------------------------------------------------------------- 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 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_valDef.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(); m_OprtShortcutDef.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& a_stOprt) const { using std::cout; Stack stOprt(a_stOprt); string_type sInfo = _T("StackDump> "); console() << sInfo; 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 muparserx-4.0.11/parser/mpParserBase.h000066400000000000000000000211771414723276500176770ustar00rootroot00000000000000#ifndef MUP_PARSERBASE_H #define MUP_PARSERBASE_H /** \file \brief Definition of the muParserX engine.
               __________                                 ____  ___
    _____  __ _\______   \_____ _______  ______ __________\   \/  /
   /     \|  |  \     ___/\__  \\_  __ \/  ___// __ \_  __ \     / 
  |  Y Y  \  |  /    |     / __ \|  | \/\___ \\  ___/|  | \/     \ 
  |__|_|  /____/|____|    (____  /__|  /____  >\___  >__| /___/\  \
        \/                     \/           \/     \/           \_/
                                       Copyright (C) 2016, Ingo Berg
                                       All rights reserved.

  Redistribution and use in source and binary forms, with or without 
  modification, are permitted provided that the following conditions are met:

   * Redistributions of source code must retain the above copyright notice, 
     this list of conditions and the following disclaimer.
   * Redistributions in binary form must reproduce the above copyright notice, 
     this list of conditions and the following disclaimer in the documentation 
     and/or other materials provided with the distribution.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
  POSSIBILITY OF SUCH DAMAGE.
*/ #include #include #include #include #include #include "mpIOprt.h" #include "mpIOprtBinShortcut.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 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 DefineConst(const string_type &ident, const Value &val); void DefineVar(const string_type &ident, const Variable &var); void DefineFun(const ptr_cal_type &fun); void DefineOprt(const TokenPtr &oprt); void DefineOprt(const TokenPtr &oprt); void DefinePostfixOprt(const TokenPtr &oprt); void DefineInfixOprt(const TokenPtr &oprt); bool IsVarDefined(const string_type &ident) const; bool IsConstDefined(const string_type &ident) const; bool IsFunDefined(const string_type &ident) const; bool IsOprtDefined(const string_type &ident) const; bool IsPostfixOprtDefined(const string_type &ident) const; bool IsInfixOprtDefined(const string_type &ident) const; void RemoveVar(const string_type &ident) ; void RemoveConst(const string_type &ident); void RemoveFun(const string_type &ident); void RemoveOprt(const string_type &ident); void RemovePostfixOprt(const string_type &ident); void RemoveInfixOprt(const string_type &ident); // Clear user defined variables, constants or functions void ClearVar(); void ClearFun(); void ClearConst(); void ClearInfixOprt(); void ClearPostfixOprt(); void ClearOprt(); void DumpRPN() const; 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; // Allow clients to check syntacticaly correctnes of name against character set. void CheckName(const string_type &a_sName, const string_type &a_CharSet) const; protected: fun_maptype m_FunDef; ///< Function definitions oprt_pfx_maptype m_PostOprtDef; ///< Postfix operator callbacks oprt_ifx_maptype m_InfixOprtDef; ///< Infix operator callbacks. oprt_bin_maptype m_OprtDef; ///< Binary operator callbacks oprt_bin_shortcut_maptype m_OprtShortcutDef; ///< short circuit operator definitions val_maptype m_valDef; ///< Definition of parser constants var_maptype m_varDef; ///< user defind variables. private: void ReInit() const; void ClearExpr(); void CreateRPN() const; void StackDump(const Stack &a_stOprt) const; // Used by by DefineVar and DefineConst methods // for better checking of var/const/oprt/fun existence. void CheckForEntityExistence(const string_type & ident, EErrorCodes error_code); void Assign(const ParserXBase &a_Parser); void InitTokenReader(); void ApplyFunc(Stack &a_stOpt, int a_iArgCount) const; void ApplyOprtShortcut(Stack &a_stOpt) const; void ApplyIfElse(Stack &a_stOpt) const; void ApplyRemainingOprt(Stack &a_stOpt) const; const IValue& ParseFromString() const; const IValue& ParseFromRPN() 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::unique_ptr m_pTokenReader; val_vec_type m_valDynVarShadow; ///< Value objects referenced by variables created at parser runtime string_type m_sNameChars; ///< Charset for names string_type m_sOprtChars; ///< Charset for postfix/ binary operator tokens string_type m_sInfixOprtChars; ///< Charset for infix operator tokens mutable int m_nPos; /** \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 muparserx-4.0.11/parser/mpParserMessageProvider.cpp000066400000000000000000000323211414723276500224500ustar00rootroot00000000000000#include "mpParserMessageProvider.h" #include #include "mpError.h" MUP_NAMESPACE_START //------------------------------------------------------------------------------------------------- // // class ParserMessageProviderBase - Base class for message providers // //------------------------------------------------------------------------------------------------- ParserMessageProviderBase::ParserMessageProviderBase() :m_vErrMsg(0) {} //----------------------------------------------------------------------------------------------- ParserMessageProviderBase::~ParserMessageProviderBase() {} //----------------------------------------------------------------------------------------------- void ParserMessageProviderBase::Init() { InitErrorMessages(); for (int i=0; i #include #include "mpDefines.h" #include "mpTypes.h" MUP_NAMESPACE_START //----------------------------------------------------------------------------------------------- /** \brief Base class for Parser Message providing classes. */ class ParserMessageProviderBase { friend class std::unique_ptr; public: ParserMessageProviderBase(); virtual ~ParserMessageProviderBase(); void Init(); string_type GetErrorMsg(EErrorCodes errc) const; private: // Disable CC and assignment operator for this class and derivatives ParserMessageProviderBase(const ParserMessageProviderBase &ref); ParserMessageProviderBase& operator=(const ParserMessageProviderBase &ref); protected: std::vector m_vErrMsg; virtual void InitErrorMessages() = 0; }; //----------------------------------------------------------------------------------------------- /** \brief English versions of parser messages. */ class ParserMessageProviderEnglish : public ParserMessageProviderBase { public: ParserMessageProviderEnglish(); protected: virtual void InitErrorMessages(); }; //----------------------------------------------------------------------------------------------- /** \brief German versions of parser messages. */ class ParserMessageProviderGerman : public ParserMessageProviderBase { public: ParserMessageProviderGerman(); protected: virtual void InitErrorMessages(); }; MUP_NAMESPACE_END #endif muparserx-4.0.11/parser/mpRPN.cpp000066400000000000000000000127521414723276500166410ustar00rootroot00000000000000/* __________ ____ ___ _____ __ _\______ \_____ _______ ______ __________\ \/ / / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ / | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \ \/ \/ \/ \/ \_/ Copyright (C) 2016, Ingo Berg All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include "mpRPN.h" #include "mpIToken.h" #include "mpICallback.h" #include "mpIOprtBinShortcut.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() != nullptr) { m_nStackPos++; } else if (tok->AsICallback()) { ICallback *pFun = tok->AsICallback(); MUP_VERIFY(pFun != nullptr); m_nStackPos -= pFun->GetArgsPresent() - 1; } MUP_VERIFY(m_nStackPos >= 0); m_nMaxStackPos = std::max(m_nStackPos, m_nMaxStackPos); } //--------------------------------------------------------------------------- void RPN::AddNewline(ptr_tok_type tok, int n) { static_cast(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 stIf, stElse; Stack stScBeg; int idx; for (int i = 0; i < static_cast(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(m_vRPN[idx].Get())->SetOffset(i - idx); break; case cmENDIF: idx = stElse.pop(); static_cast(m_vRPN[idx].Get())->SetOffset(i - idx); break; case cmSHORTCUT_BEGIN: stScBeg.push(i); break; case cmSHORTCUT_END: idx = stScBeg.pop(); static_cast(m_vRPN[idx].Get())->SetOffset(i - idx); break; default: continue; } } } //--------------------------------------------------------------------------- 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() << std::setw(2) << i << " : " << std::setw(2) << pTok->GetExprPos() << " : " << pTok->AsciiDump() << std::endl; } } MUP_NAMESPACE_END muparserx-4.0.11/parser/mpRPN.h000066400000000000000000000052521414723276500163030ustar00rootroot00000000000000#ifndef MUP_RPN_H #define MUP_RPN_H /* __________ ____ ___ _____ __ _\______ \_____ _______ ______ __________\ \/ / / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ / | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \ \/ \/ \/ \/ \_/ Copyright (C) 2016, Ingo Berg All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #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 muparserx-4.0.11/parser/mpScriptTokens.cpp000066400000000000000000000057161414723276500206340ustar00rootroot00000000000000/* __________ ____ ___ _____ __ _\______ \_____ _______ ______ __________\ \/ / / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ / | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \ \/ \/ \/ \/ \_/ Copyright (C) 2016, Ingo Berg All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #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 << g_sCmdCode[ GetCode() ]; ss << _T(" [addr=0x") << std::hex << this << std::dec; ss << _T("; pos=") << GetExprPos(); ss << _T("; offset=") << m_nOffset; ss << _T("]"); return ss.str(); } MUP_NAMESPACE_END muparserx-4.0.11/parser/mpScriptTokens.h000066400000000000000000000051351414723276500202740ustar00rootroot00000000000000#ifndef MUP_SCRIPT_TOKENS_H #define MUP_SCRIPT_TOKENS_H /** \file \brief Definition of basic types used by muParserX
               __________                                 ____  ___
    _____  __ _\______   \_____ _______  ______ __________\   \/  /
   /     \|  |  \     ___/\__  \\_  __ \/  ___// __ \_  __ \     / 
  |  Y Y  \  |  /    |     / __ \|  | \/\___ \\  ___/|  | \/     \ 
  |__|_|  /____/|____|    (____  /__|  /____  >\___  >__| /___/\  \
        \/                     \/           \/     \/           \_/
                                       Copyright (C) 2016, Ingo Berg
                                       All rights reserved.

  Redistribution and use in source and binary forms, with or without 
  modification, are permitted provided that the following conditions are met:

   * Redistributions of source code must retain the above copyright notice, 
     this list of conditions and the following disclaimer.
   * Redistributions in binary form must reproduce the above copyright notice, 
     this list of conditions and the following disclaimer in the documentation 
     and/or other materials provided with the distribution.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
  POSSIBILITY OF SUCH DAMAGE.
*/ #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 muparserx-4.0.11/parser/mpStack.h000066400000000000000000000122641414723276500167120ustar00rootroot00000000000000#ifndef MUP_STACK_H #define MUP_STACK_H /* __________ ____ ___ _____ __ _\______ \_____ _______ ______ __________\ \/ / / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ / | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \ \/ \/ \/ \/ \_/ Copyright (C) 2016, Ingo Berg All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #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 > 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 __________ ____ ___ _____ __ _\______ \_____ _______ ______ __________\ \/ / / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ / | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \ \/ \/ \/ \/ \_/ Copyright (C) 2016 Ingo Berg All rights reserved. muParserX - A C++ math parser library with array and string support Copyright (c) 2016, Ingo Berg All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "mpTest.h" #include "mpValue.h" #include #include #include #include #include #include #define MUP_CONST_PI 3.141592653589793238462643 #define MUP_CONST_E 2.718281828459045235360287 using namespace std; MUP_NAMESPACE_START //----------------------------------------------------------------------------------------------- // // class OprtStrAdd // //----------------------------------------------------------------------------------------------- class DbgSillyAdd : public IOprtBin { public: DbgSillyAdd() :IOprtBin(_T("++"), (int)prADD_SUB, oaLEFT) {} //----------------------------------------------------------------------------------------------- void 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(); *ret = a + b; } //----------------------------------------------------------------------------------------------- const char_type* GetDesc() const { return _T("internally used operator without special meaning for unit testing"); } //----------------------------------------------------------------------------------------------- IToken* Clone() const { return new DbgSillyAdd(*this); } }; //------------------------------------------------------------------------------ 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*/) { *ret = 0.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::TestStringFun); AddTest(&ParserTester::TestMatrix); AddTest(&ParserTester::TestComplex); AddTest(&ParserTester::TestVector); AddTest(&ParserTester::TestBinOp); AddTest(&ParserTester::TestPostfix); AddTest(&ParserTester::TestInfix); AddTest(&ParserTester::TestMultiArg); AddTest(&ParserTester::TestScript); AddTest(&ParserTester::TestValReader); AddTest(&ParserTester::TestIssueReports); ParserTester::c_iCount = 0; } //--------------------------------------------------------------------------- int ParserTester::TestIssueReports() { int iNumErr = 0; *m_stream << _T("testing github issue reports..."); // Github: Issue 55 iNumErr += ThrowTest(_T("{0,{0}}*{0,{0}}*{,{0}}*{0,{0}0,{0}}*{0,{0}}*{,{0}}*{0}*{000}"), ecUNEXPECTED_COMMA); // Github: Issue 56 iNumErr += ThrowTest(_T("0M[,1][0/1M[0M]M]"), ecUNEXPECTED_COMMA); // Github Issue 57: iNumErr += ThrowTest(_T("{?{{{{:44"), ecUNEXPECTED_CONDITIONAL); // Github Issue 60 iNumErr += ThrowTest(_T("0<01?1=:1"), ecMISPLACED_COLON); iNumErr += ThrowTest(_T("0<01?1<:1"), ecMISPLACED_COLON); iNumErr += ThrowTest(_T("0<01?1>:1"), ecMISPLACED_COLON); iNumErr += ThrowTest(_T("0<01?1-:1"), ecMISPLACED_COLON); iNumErr += ThrowTest(_T("0<01?1-:1"), ecMISPLACED_COLON); iNumErr += ThrowTest(_T("0<01?1-:1"), ecMISPLACED_COLON); iNumErr += ThrowTest(_T("0<01?1-:1"), ecMISPLACED_COLON); iNumErr += ThrowTest(_T("0<01?1-:1"), ecMISPLACED_COLON); iNumErr += ThrowTest(_T("0<01?1+:1"), ecMISPLACED_COLON); iNumErr += ThrowTest(_T("0<01?1*:1"), ecMISPLACED_COLON); iNumErr += ThrowTest(_T("0<01?1/:1"), ecMISPLACED_COLON); iNumErr += ThrowTest(_T("0<01?1&:1"), ecMISPLACED_COLON); iNumErr += ThrowTest(_T("0<01?1<<:1"), ecMISPLACED_COLON); iNumErr += ThrowTest(_T("0<01?1>>:1"), ecMISPLACED_COLON); iNumErr += ThrowTest(_T("{ ? 0 : 7m}-{7, -00007m}-{7M}"), ecUNEXPECTED_CONDITIONAL); iNumErr += ThrowTest(_T("{ { { ? 2 }, 7:2 }*7m }"), ecUNEXPECTED_CONDITIONAL); // Not too happy about the undefined code, but better than a crash of an assertion at runtime iNumErr += ThrowTest(_T("{0<0?0,0:0<0}"), ecUNEXPECTED_COMMA); // Github Issue 63 iNumErr += ThrowTest(_T("0<0-0--eye()"), ecINVALID_NUMBER_OF_PARAMETERS); Assessment(iNumErr); return iNumErr; } //--------------------------------------------------------------------------- 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.0, 2.0, 3.0, 4.0 }; 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.0; unity.At(1, 1) = 1.0; unity.At(2, 2) = 1.0; Value va(3, 0); va.At(0) = 1.0; va.At(1) = 2.0; va.At(2) = 3.0; //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.0; m1_plus_m2.At(0, 1) = 2.0; m1_plus_m2.At(0, 2) = 3.0; m1_plus_m2.At(1, 0) = 4.0; m1_plus_m2.At(1, 1) = 6.0; m1_plus_m2.At(1, 2) = 6.0; m1_plus_m2.At(2, 0) = 7.0; m1_plus_m2.At(2, 1) = 8.0; m1_plus_m2.At(2, 2) = 10.0; Value m2_minus_m1(3, 3, 0); m2_minus_m1.At(0, 0) = 0.0; m2_minus_m1.At(0, 1) = 2.0; m2_minus_m1.At(0, 2) = 3.0; m2_minus_m1.At(1, 0) = 4.0; m2_minus_m1.At(1, 1) = 4.0; m2_minus_m1.At(1, 2) = 6.0; m2_minus_m1.At(2, 0) = 7.0; m2_minus_m1.At(2, 1) = 8.0; m2_minus_m1.At(2, 2) = 8.0; Value m2_times_10(3, 3, 0); m2_times_10.At(0, 0) = 10.0; m2_times_10.At(0, 1) = 20.0; m2_times_10.At(0, 2) = 30.0; m2_times_10.At(1, 0) = 40.0; m2_times_10.At(1, 1) = 50.0; m2_times_10.At(1, 2) = 60.0; m2_times_10.At(2, 0) = 70.0; m2_times_10.At(2, 1) = 80.0; m2_times_10.At(2, 2) = 90.0; Value va_times_vb_transp(3, 3, 0); va_times_vb_transp.At(0, 0) = 4.0; va_times_vb_transp.At(0, 1) = 3.0; va_times_vb_transp.At(0, 2) = 2.0; va_times_vb_transp.At(1, 0) = 8.0; va_times_vb_transp.At(1, 1) = 6.0; va_times_vb_transp.At(1, 2) = 4.0; va_times_vb_transp.At(2, 0) = 12.0; va_times_vb_transp.At(2, 1) = 9.0; va_times_vb_transp.At(2, 2) = 6.0; Value size_3x6(1, 2, 0); size_3x6.At(0, 0) = 3.0; size_3x6.At(0, 1) = 6.0; Value size_3x3(1, 2, 0); size_3x3.At(0, 0) = 3.0; size_3x3.At(0, 1) = 3.0; Value size_3x1(1, 2, 0); size_3x1.At(0, 0) = 3.0; size_3x1.At(0, 1) = 1.0; Value size_1x3(1, 2, 0); size_1x3.At(0, 0) = 1.0; size_1x3.At(0, 1) = 3.0; // Check matrix dimension mismatch error iNumErr += ThrowTest(_T("\"hallo\"+m1"), ecEVAL); iNumErr += ThrowTest(_T("m1+\"hallo\""), ecEVAL); iNumErr += ThrowTest(_T("va+m1"), ecMATRIX_DIMENSION_MISMATCH); iNumErr += ThrowTest(_T("m1+va"), ecMATRIX_DIMENSION_MISMATCH); iNumErr += ThrowTest(_T("va-m1"), ecMATRIX_DIMENSION_MISMATCH); iNumErr += ThrowTest(_T("m1-va"), ecMATRIX_DIMENSION_MISMATCH); iNumErr += ThrowTest(_T("va*m1"), ecMATRIX_DIMENSION_MISMATCH); iNumErr += ThrowTest(_T("va+eye(2)"), ecMATRIX_DIMENSION_MISMATCH); // Issue 63: iNumErr += ThrowTest(_T("0-0-eye()"), ecINVALID_NUMBER_OF_PARAMETERS); iNumErr += ThrowTest(_T("m1[1]"), ecINDEX_DIMENSION); iNumErr += ThrowTest(_T("m1[1,2,3]"), ecINDEX_DIMENSION); iNumErr += ThrowTest(_T("va[1,2]"), ecINDEX_OUT_OF_BOUNDS); // va has 1 column, 3 rows -> the coulumn index is referencing the third column iNumErr += ThrowTest(_T("a+m1"), ecEVAL); iNumErr += ThrowTest(_T("m1+a"), ecEVAL); iNumErr += ThrowTest(_T("a-m1"), ecEVAL); iNumErr += ThrowTest(_T("m1-a"), ecEVAL); iNumErr += ThrowTest(_T("va[,1]"), ecUNEXPECTED_COMMA); iNumErr += ThrowTest(_T("va[{1]"), ecMISSING_CURLY_BRACKET); iNumErr += ThrowTest(_T("{,1}"), ecUNEXPECTED_COMMA); // 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)"), ecINVALID_NUMBER_OF_PARAMETERS); iNumErr += ThrowTest(_T("ones()"), ecINVALID_NUMBER_OF_PARAMETERS); iNumErr += EqnTest(_T("ones(1,1)"), 1.0, true); iNumErr += EqnTest(_T("ones(1)"), 1.0, 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); iNumErr += EqnTest(_T("size(ones(3,3))"), size_3x3, true); // check return value dimension iNumErr += EqnTest(_T("size(ones(1,3))"), size_1x3, true); // check return value dimension iNumErr += EqnTest(_T("size(ones(3,1))"), size_3x1, true); // check return value dimension iNumErr += EqnTest(_T("size(ones(3))"), size_3x3, true); // check return value dimension // zeros iNumErr += ThrowTest(_T("zeros()"), ecINVALID_NUMBER_OF_PARAMETERS); iNumErr += EqnTest(_T("size(zeros(3,3))"), size_3x3, true); // check return value dimension iNumErr += EqnTest(_T("size(zeros(1,3))"), size_1x3, true); // check return value dimension iNumErr += EqnTest(_T("size(zeros(3,1))"), size_3x1, true); // check return value dimension iNumErr += EqnTest(_T("size(zeros(3))"), size_3x3, true); // check return value dimension // eye iNumErr += ThrowTest(_T("eye()"), ecINVALID_NUMBER_OF_PARAMETERS); iNumErr += EqnTest(_T("size(eye(3,3))"), size_3x3, true); // check return value dimension iNumErr += EqnTest(_T("size(eye(1,3))"), size_1x3, true); // check return value dimension iNumErr += EqnTest(_T("size(eye(3,1))"), size_3x1, true); // check return value dimension iNumErr += EqnTest(_T("size(eye(3))"), size_3x3, true); // check return value dimension iNumErr += EqnTest(_T("size(eye(3,6))"), size_3x6, true); // check return value dimension // transposition iNumErr += EqnTest(_T("va'*vb"), 16.0, true); iNumErr += EqnTest(_T("2*va'*vb"), 32.0, true); iNumErr += EqnTest(_T("va*vb'"), va_times_vb_transp, true); // index operator // erster index: Zeilenindex, zweiter index: Spaltenindex iNumErr += EqnTest(_T("va[0]"), 1.0, true); iNumErr += EqnTest(_T("va[1]"), 2.0, true); iNumErr += EqnTest(_T("va[2]"), 3.0, true); // Use two dimensional index operator on a vector iNumErr += EqnTest(_T("va[0,0]"), 1.0, true); iNumErr += EqnTest(_T("va[1,0]"), 2.0, true); iNumErr += EqnTest(_T("va[2,0]"), 3.0, true); // Now test the same with a transposed vector: iNumErr += EqnTest(_T("va'[0]"), 1.0, true); iNumErr += EqnTest(_T("va'[1]"), 2.0, true); iNumErr += EqnTest(_T("va'[2]"), 3.0, true); // Use two dimensional index operator on a vector iNumErr += EqnTest(_T("va'[0,0]"), 1.0, true); iNumErr += EqnTest(_T("va'[0,1]"), 2.0, true); iNumErr += EqnTest(_T("va'[0,2]"), 3.0, true); iNumErr += EqnTest(_T("(va')[0,2]"), 3.0, true); // <- Index operator after closing bracket is ok // vector creation iNumErr += EqnTest(_T("{1,2,3}'"), va, true); iNumErr += EqnTest(_T("{a,2,3}'"), va, true); // that was an actual bug: variable a was overwritten // assignment to element: iNumErr += ThrowTest(_T("va'[0]=123"), ecASSIGNEMENT_TO_VALUE); 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); // Issue #107 (https://github.com/beltoforion/muparserx/issues/107) iNumErr += EqnTest(_T("cb*=cc"), cmplx_type(-6, 17), true, 2, true); // complex numbers iNumErr += EqnTest(_T("i*i"), -1.0, true, 0); iNumErr += EqnTest(_T("1i"), cmplx_type(0, 1), true, 0); iNumErr += EqnTest(_T("norm(3+4i)"), 25.0, true, 0); iNumErr += EqnTest(_T("norm(4i+3)"), 25.0, true, 0); iNumErr += EqnTest(_T("norm(3i+4)"), 25.0, 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("(-1)^0.5"), cmplx_type(0, 1), true, 0); iNumErr += EqnTest(_T("(-3)^(4/3)"), std::pow(cmplx_type(-3, 0), cmplx_type(4.0 / 3, 0)), true, 0); // Issue 41: Complex pow of small numbers zeros out the imaginary part // https://code.google.com/p/muparserx/issues/detail?id=41 iNumErr += EqnTest(_T("(1e-15 + 1e-15*i) ^ 2"), std::pow(cmplx_type(1e-15, 1e-15), 2), 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); // Issue 17: Wrong result on complex power. iNumErr += EqnTest(_T("(-0.27 + 0.66*i)^2"), cmplx_type(-0.3627, -0.3564), true, 0); iNumErr += EqnTest(_T("(-1+5i)^2"), cmplx_type(-24, -10), true, 0); iNumErr += EqnTest(_T("c=(a=1+2i)"), cmplx_type(1, 2), 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 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), 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(static_cast(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 (!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 (!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++; // Issue 33: https://code.google.com/p/muparserx/issues/detail?id=33 // Remark: Type information was not properly set when invoking +=, -= operators { Value x = 1.0; Value y = cmplx_type(0, 1); x += y; if (x.GetImag() != 1 || x.GetFloat() != 1 || x.GetType() != 'c') { *m_stream << _T("\nValue::operator+=(...) failed."); iNumErr++; } x = 1.0; y = cmplx_type(0, 1); x -= y; if (x.GetImag() != -1 || x.GetFloat() != 1 || x.GetType() != 'c') { *m_stream << _T("\nValue::operator-=(...) failed."); 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..."); iNumErr += ThrowTest(_T("a,b"), ecUNEXPECTED_COMMA); iNumErr += ThrowTest(_T("(a,b)"), ecUNEXPECTED_COMMA); iNumErr += ThrowTest(_T("((a,b))"), ecUNEXPECTED_COMMA); iNumErr += ThrowTest(_T("2*1,2"), ecUNEXPECTED_COMMA); iNumErr += ThrowTest(_T("sin(1,2)"), ecTOO_MANY_PARAMS); // Invalid expression // Issue 20: http://code.google.com/p/muparserx/issues/detail?id=20 iNumErr += ThrowTest(_T(" "), ecUNEXPECTED_EOF); iNumErr += ThrowTest(_T("sin(nonexistent_var)"), ecUNASSIGNABLE_TOKEN, 4, _T("nonexistent_var")); // 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); iNumErr += ThrowTest(_T("-m"), ecUNASSIGNABLE_TOKEN); iNumErr += ThrowTest(_T("m4"), ecUNASSIGNABLE_TOKEN); iNumErr += ThrowTest(_T("sin(m)"), ecUNASSIGNABLE_TOKEN); iNumErr += ThrowTest(_T("m m"), ecUNASSIGNABLE_TOKEN); iNumErr += ThrowTest(_T("m(8)"), ecUNASSIGNABLE_TOKEN); iNumErr += ThrowTest(_T("4 + m"), ecUNASSIGNABLE_TOKEN); // unexpected 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); // unexpected variable iNumErr += ThrowTest(_T("a _xxx_ b"), ecUNASSIGNABLE_TOKEN, 2); // if a variable factory is installed ecUNEXPECTED_VAR 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("3n[1]"), ecINDEX_OUT_OF_BOUNDS); // Indexing a scalar is ok, but this index is out of bounds (0 would be ok) 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("[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..."); // escape sequences iNumErr += EqnTest(_T("\"\\\"quoted_string\\\"\""), _T("\"quoted_string\""), true); // "\"quoted_string\"" -> "quoted_string" iNumErr += EqnTest(_T("\"\\\"\\\"\""), _T("\"\""), true); // "\"\"" -> "" iNumErr += EqnTest(_T("\"\\\\\""), _T("\\"), true); // "\\" -> \ (single backslash) // String functions iNumErr += EqnTest(_T("strlen(\"12345\")"), 5.0, true); iNumErr += EqnTest(_T("strlen(toupper(\"abcde\"))"), 5.0, 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("1n"), (float_type)1e-9, true); iNumErr += EqnTest(_T("8n"), (float_type)8e-9, true); iNumErr += EqnTest(_T("8n"), (float_type)123.0, false); iNumErr += EqnTest(_T("3m+5"), (float_type)5.003, true); iNumErr += EqnTest(_T("1000m"), (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("-2m"), (float_type)-2e-3, true); iNumErr += EqnTest(_T("a++b"), 3.0, true); iNumErr += EqnTest(_T("a ++ b"), 3.0, true); iNumErr += EqnTest(_T("1++2"), 3.0, true); iNumErr += EqnTest(_T("1 ++ 2"), 3.0, true); iNumErr += EqnTest(_T("2+(a*1000)m"), (float_type)3.0, true); // some incorrect results iNumErr += EqnTest(_T("1000m"), (float_type)0.1, false); iNumErr += EqnTest(_T("(a)m"), (float_type)2.0, false); // factorial operator iNumErr += EqnTest(_T("5!"), 120.0, true); iNumErr += EqnTest(_T("-5!"), -120.0, true); iNumErr += ThrowTest(_T("(-5)!"), ecDOMAIN_ERROR); // Special tests for systems not supporting IEEE 754 if (!std::numeric_limits::is_iec559) { iNumErr += ThrowTest(_T("123456!"), ecOVERFLOW); } Assessment(iNumErr); return iNumErr; } //--------------------------------------------------------------------------- int ParserTester::TestInfix() { int iNumErr = 0; *m_stream << _T("testing infix operators..."); float_type a = 1; float_type b = 2; 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"), -a, true); iNumErr += EqnTest(_T("-(a)"), -(a), true); iNumErr += EqnTest(_T("-(-a)"), -(-a), true); iNumErr += EqnTest(_T("-(-a)*2"), -(-a) * 2, 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); // sign precedence // Issue 14: https://code.google.com/p/muparserx/issues/detail?id=14 iNumErr += EqnTest(_T("-3^2"), -9.0, true); iNumErr += EqnTest(_T("-b^2^3-b^8"), -std::pow(b, std::pow(2.0, 3.0)) - std::pow(b, 8), true); Assessment(iNumErr); return iNumErr; } //--------------------------------------------------------------------------- int ParserTester::TestMultiArg() { int iNumErr = 0; *m_stream << _T("testing multiarg functions..."); // Multiarg functions being called without any parameters iNumErr += ThrowTest(_T("min()"), ecTOO_FEW_PARAMS); iNumErr += ThrowTest(_T("max()"), ecTOO_FEW_PARAMS); iNumErr += ThrowTest(_T("sum()"), ecTOO_FEW_PARAMS); // 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"), ecMATRIX_DIMENSION_MISMATCH); // fail: vectors of different size iNumErr += ThrowTest(_T("va-vc"), ecMATRIX_DIMENSION_MISMATCH); // fail: vectors of different size iNumErr += ThrowTest(_T("va*vc"), ecMATRIX_DIMENSION_MISMATCH); // fail: vectors of different size iNumErr += ThrowTest(_T("va*vb"), ecMATRIX_DIMENSION_MISMATCH); // fail: matrix dimension mismatch iNumErr += ThrowTest(_T("va*va"), ecMATRIX_DIMENSION_MISMATCH); // fail: matrix dimension mismatch iNumErr += ThrowTest(_T("(va*vb)*b"), ecMATRIX_DIMENSION_MISMATCH); // 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_OUT_OF_BOUNDS); // indexing a scalar is ok, but this index is out of bounds (0 would be ok...) 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) = (float_type)5.0; v.At(1) = (float_type)5.0; v.At(2) = (float_type)5.0; iNumErr += EqnTest(_T("va+vb"), v, true); v.At(0) = (float_type)5.0; v.At(1) = (float_type)5.0; v.At(2) = (float_type)6.0; iNumErr += EqnTest(_T("va+vb"), v, false); v.At(0) = (float_type)-1.0; v.At(1) = (float_type)-2.0; v.At(2) = (float_type)-3.0; iNumErr += EqnTest(_T("-va"), v, true); iNumErr += EqnTest(_T("sizeof(va+vb)"), 3.0, true); iNumErr += EqnTest(_T("sizeof(va-vb)"), 3.0, true); iNumErr += EqnTest(_T("va==vb"), false, true); iNumErr += EqnTest(_T("va!=vb"), true, true); //iNumErr += EqnTest(_T("vavb"), true, true); //iNumErr += EqnTest(_T("va<=vb"), false, true); //iNumErr += EqnTest(_T("va>=vb"), true, true); iNumErr += EqnTest(_T("vb[va[0]]"), 3.0, true); iNumErr += EqnTest(_T("m1[0,0]+m1[1,1]+m1[2,2]"), 3.0, true); iNumErr += EqnTest(_T("vb[m1[0,0]]"), 3.0, true); iNumErr += EqnTest(_T("m1[0,0]=2"), 2.0, true); iNumErr += EqnTest(_T("m1[1,1]=2"), 2.0, true); iNumErr += EqnTest(_T("m1[2,2]=2"), 2.0, 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.0, true); iNumErr += EqnTest(_T("va[1]"), 2.0, true); iNumErr += EqnTest(_T("va[2]"), 3.0, true); iNumErr += EqnTest(_T("(va[2])"), 3.0, true); iNumErr += EqnTest(_T("va[a]"), 2.0, true); iNumErr += EqnTest(_T("(va[a])"), 2.0, true); iNumErr += EqnTest(_T("va[b]"), 3.0, true); iNumErr += EqnTest(_T("va[(2)]"), 3.0, true); iNumErr += EqnTest(_T("va[-(-2)]"), 3.0, true); iNumErr += EqnTest(_T("(va[(2)])"), 3.0, true); iNumErr += EqnTest(_T("(va[-(-2)])"), 3.0, true); iNumErr += EqnTest(_T("va[1+1]"), 3.0, true); iNumErr += EqnTest(_T("va[(int)sin(8)+1]"), 2.0, true); iNumErr += EqnTest(_T("va[2]+4"), 7.0, true); iNumErr += EqnTest(_T("4+va[2]"), 7.0, true); iNumErr += EqnTest(_T("va[2]*4"), 12.0, true); iNumErr += EqnTest(_T("4*va[2]"), 12.0, true); iNumErr += EqnTest(_T("va[2]+a"), 4.0, true); iNumErr += EqnTest(_T("a+va[2]"), 4.0, true); iNumErr += EqnTest(_T("va[2]*b"), 6.0, true); iNumErr += EqnTest(_T("b*va[2]"), 6.0, true); // Issue 68 (and related issues): iNumErr += EqnTest(_T("(abs(-3)+2)>=min(6,5)"), true, true); iNumErr += EqnTest(_T("(abs(-3))>abs(2)"), true, true); iNumErr += EqnTest(_T("min(1,2,-3)>-4"), true, true); iNumErr += EqnTest(_T("(abs(-3))>-2"), true, true); iNumErr += EqnTest(_T("abs(-3)>abs(2)"), true, true); // Issue 42: // https://code.google.com/p/muparserx/issues/detail?id=42 v.At(0) = (float_type)1.0; v.At(1) = (float_type)0.0; v.At(2) = (float_type)0.0; iNumErr += EqnTest(_T("{1,0,0}'"), v, true); iNumErr += EqnTest(_T("{(1),0,0}'"), v, true); Assessment(iNumErr); return iNumErr; } //--------------------------------------------------------------------------- int ParserTester::TestBinOp() { int iNumErr = 0; *m_stream << _T("testing binary operators..."); float_type a = 1; // 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.0, true); iNumErr += EqnTest(_T("2+2&(a+b+c)"), 4.0, true); iNumErr += EqnTest(_T("3&3"), 3.0, true); iNumErr += EqnTest(_T("c&3"), 3.0, true); iNumErr += EqnTest(_T("(c)&3"), 3.0, true); iNumErr += EqnTest(_T("(a+b)&3"), 3.0, true); iNumErr += EqnTest(_T("(a+b+c)&6"), 6.0, true); iNumErr += EqnTest(_T("(1+2+3)&6"), 6.0, true); iNumErr += EqnTest(_T("3&c"), 3.0, true); iNumErr += EqnTest(_T("(a<<1)+2"), 4.0, true); iNumErr += EqnTest(_T("(a<<2)+2"), 6.0, true); iNumErr += EqnTest(_T("(a<<3)+2"), 10.0, true); iNumErr += EqnTest(_T("(a<<4)+2"), 18.0, true); iNumErr += EqnTest(_T("(a<<5)+2"), 34.0, true); iNumErr += EqnTest(_T("1<<31"), (float_type)2147483648, true); iNumErr += EqnTest(_T("-1<<31"), (float_type)-2147483648.0, true); iNumErr += EqnTest(_T("1<<45"), (float_type)35184372088832.0, true); iNumErr += EqnTest(_T("-1<<45"), (float_type)-35184372088832.0, true); iNumErr += EqnTest(_T("8<<-2"), 2.0, true); iNumErr += EqnTest(_T("8<<-4"), 0.0, true); // Issue 25: http://code.google.com/p/muparserx/issues/detail?id=25 iNumErr += ThrowTest(_T("55<<2222222"), ecOVERFLOW); // Issue 16: http://code.google.com/p/muparserx/issues/detail?id=16 iNumErr += EqnTest(_T("true == true && false"), true == true && false, true); iNumErr += EqnTest(_T("false == true && false"), false == true && false, true); iNumErr += EqnTest(_T("a==1.0 && a==1.0"), a == 1.0 && a == 1.0, true); // bool operators for comparing values iNumErr += EqnTest(_T("aa"), true, true); iNumErr += EqnTest(_T("a>a"), false, true); iNumErr += EqnTest(_T("aa"), 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)"), 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"), (float_type)2.01, true); iNumErr += EqnTest(_T("sqrt(a)-1.01"), (float_type)-0.01, true); // interaction with sign operator iNumErr += EqnTest(_T("3-(-a)"), 4.0, true); iNumErr += EqnTest(_T("3--a"), 4.0, true); // Problems with small bogus real/imag values introduced due to limited floating point accuracy iNumErr += EqnTest(_T("(-2)^3"), -8.0, true); // may introduce incorrect imaginary value (When computed with the log/exp formula: -8 + 2.93e-15i) iNumErr += EqnTest(_T("imag((-2)^3)==0"), true, true); // may introduce incorrect imaginary value (When computed with the log/exp formula: -8 + 2.93e-15i) Assessment(iNumErr); return iNumErr; } //--------------------------------------------------------------------------- int ParserTester::TestIfElse() { int iNumErr = 0; *m_stream << _T("testing if-else conditional..."); float_type a = 1; // test case copied from muparser (https://oss-fuzz.com/testcase-detail/4777121158529024) iNumErr += ThrowTest(_T("3!=min(false?2>2,2>5,1:6)"), ecUNEXPECTED_COMMA); // test case copied from muparser (https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=22922#c1) iNumErr += ThrowTest(_T("1?2:0?(7:1)"), ecMISPLACED_COLON); // test case copied from muparser (https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=23410) // with variations iNumErr += ThrowTest(_T(R"(false ? 4 : "", ? 4 : "", ? 4 : "")"), ecUNEXPECTED_COMMA); iNumErr += EqnTest(_T(R"(false ? "four" : 4)"), (int_type)4, true); iNumErr += EqnTest(_T(R"(true ? "four" : 4)"), "four", true); iNumErr += EqnTest(_T(R"(true ? "foo" : "bar")"), "foo", true); // test case and variations copied from muparser https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=22938 iNumErr += ThrowTest(_T("sum(false?1,0,0:3)"), ecUNEXPECTED_COMMA); iNumErr += ThrowTest(_T("sum(false?(1,0,0):3)"), ecUNEXPECTED_COMMA); iNumErr += ThrowTest(_T("sum(2>3?2,4,2:4)"), ecUNEXPECTED_COMMA); iNumErr += ThrowTest(_T("sum(2>3?2,4,sin(2):4)"), ecUNEXPECTED_COMMA); iNumErr += ThrowTest(_T("sum(2>3?sin(2),4,2:4)"), ecUNEXPECTED_COMMA); iNumErr += ThrowTest(_T("sum(2>3?sin(a),4,2:4)"), ecUNEXPECTED_COMMA); iNumErr += ThrowTest(_T("sum(2>3?sin(2),4,2:4)"), ecUNEXPECTED_COMMA); // Test error detection iNumErr += ThrowTest(_T(": 2"), ecMISPLACED_COLON); iNumErr += ThrowTest(_T("? 1 : 2"), ecUNEXPECTED_CONDITIONAL); iNumErr += ThrowTest(_T("(ab) ? true : false) ? 1 : 2"), 2.0, true); iNumErr += EqnTest(_T("((a>b) ? true : false) ? 1 : sum((a>b) ? 1 : 2)"), 2.0, true); iNumErr += EqnTest(_T("((a>b) ? false : true) ? 1 : sum((a>b) ? 1 : 2)"), 1.0, true); iNumErr += EqnTest(_T("(true) ? 10 : 11"), 10.0, true); iNumErr += EqnTest(_T("(true) ? a+b : c+d"), 3.0, true); iNumErr += EqnTest(_T("(true) ? false : true"), false, true); iNumErr += EqnTest(_T("(false) ? 10 : 11"), 11.0, true); iNumErr += EqnTest(_T("(false) ? a+b : c+d"), 1.0, true); iNumErr += EqnTest(_T("(false) ? false : true"), true, true); iNumErr += EqnTest(_T("(ab) ? 10 : 11"), 11.0, true); iNumErr += EqnTest(_T("(ab) ? c : d"), -2.0, true); iNumErr += EqnTest(_T("(a>b) ? true : false"), false, true); // With multiarg functions iNumErr += EqnTest(_T("sum((a>b) ? 1 : 2)"), 2.0, true); iNumErr += EqnTest(_T("sum((a>b) ? 1 : 2, 100)"), 102.0, true); iNumErr += EqnTest(_T("sum((true) ? 1 : 2)"), 1.0, true); iNumErr += EqnTest(_T("sum((true) ? 1 : 2, 100)"), 101.0, true); iNumErr += EqnTest(_T("sum(3, (a>b) ? 3 : 10)"), 13.0, true); iNumErr += EqnTest(_T("sum(3, (ab) ? 3 : 10)*10"), 130.0, true); iNumErr += EqnTest(_T("sum(3, (ab) ? 3 : 10)"), 130.0, true); iNumErr += EqnTest(_T("10*sum(3, (ab) ? sum(3, (ab) ? sum(3, (ab) ? sum(3, (ab)&&(a2)&&(1<2) ? 128 : 255"), 255.0, true); iNumErr += EqnTest(_T("((1<2)&&(1<2)) ? 128 : 255"), 128.0, true); iNumErr += EqnTest(_T("((1>2)&&(1<2)) ? 128 : 255"), 255.0, true); iNumErr += EqnTest(_T("((ab)&&(ac) ? 1 : 2) : 3"), 2., true); iNumErr += EqnTest(_T("(a>b) ? ((bb) ? ((b>c) ? 1 : 2) : 3"), 3., true); // nested conditionals without brackets iNumErr += EqnTest(_T("(ac) ? 1 : 2 : 3"), 2., true); iNumErr += EqnTest(_T("(a>b) ? (bb) ? (b>c) ? 1 : 2 : 3"), 3., true); // Neue Tests iNumErr += EqnTest(_T("(ab)&&(a2)&&(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("((ab)&&(a0 ? 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"), 255., true); iNumErr += EqnTest(_T("a=((a>b)&&(a // 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::TestScript() { int iNumErr = 0; *m_stream << _T("testing script features..."); // 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("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); // Ending an expression with a newline iNumErr += EqnTest(_T("3\n"), 3., true); iNumErr += EqnTest(_T("1+2\n"), 3., true); iNumErr += EqnTest(_T("\n1+2\n"), 3., true); iNumErr += EqnTest(_T("\n1+2\n\na+b"), 3., true); // Testing comments /* 20130107 Not yet... iNumErr += EqnTest(_T("a=10 % this is a comment\n") _T("b=23 % this is another comment\n") _T("a+b"), 33, true); */ Assessment(iNumErr); return iNumErr; } //--------------------------------------------------------------------------- int ParserTester::TestValReader() { int iNumErr = 0; *m_stream << _T("testing value reader..."); // Hex value reader iNumErr += EqnTest(_T("0x1"), 1., true); iNumErr += EqnTest(_T("0x1+0x2"), 3., true); iNumErr += EqnTest(_T("0xff"), 255., true); // Reading of binary values iNumErr += EqnTest(_T("0b1"), 1., true); iNumErr += EqnTest(_T("0b01"), 1., true); iNumErr += EqnTest(_T("0b11"), 3., true); iNumErr += EqnTest(_T("0b011"), 3., true); iNumErr += EqnTest(_T("0b11111111"), 255., true); iNumErr += EqnTest(_T("b*0b011"), 6.0, true); iNumErr += EqnTest(_T("0b1111111111111111111111111111111"), 2147483647., true); iNumErr += EqnTest(_T("0b10000000000000000000000000000000"), -2147483647. - 1, true); iNumErr += EqnTest(_T("0b11111111111111111111111111111111"), -1., true); iNumErr += ThrowTest(_T("0b100000000000000000000000000000000"), ecUNDEFINED); // string value reader iNumErr += EqnTest(_T("\"hallo\""), _T("hallo"), true); // boolean value reader iNumErr += EqnTest(_T("true"), true, true); iNumErr += EqnTest(_T("false"), false, true); // boolean value reader iNumErr += EqnTest(_T("true"), true, true); iNumErr += EqnTest(_T("false"), false, true); // mixed iNumErr += EqnTest(_T("0b011+0xef"), 242., true); Assessment(iNumErr); return iNumErr; } //--------------------------------------------------------------------------- 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, string_type a_sIdent) { 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; } if (a_sIdent.length() && a_sIdent != e.GetContext().Ident) { *m_stream << _T("\n ") << _T("Invalid identifier: \"") << a_sExpr << _T("\" Ident:") << e.GetContext().Ident << _T(" Expected:") << a_sIdent; } 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, bool evaluateOnce) { 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::unique_ptr 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("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(); if (evaluateOnce) { // Equations with assignments will have differen results each time fVal[1] = fVal[0]; fVal[2] = fVal[0]; fVal[3] = fVal[0]; fVal[4] = fVal[0]; } else { // Test copy and assignement operators std::vector 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) { std::size_t n2 = p2.GetExprVar().size(); std::size_t n3 = p3.GetExprVar().size(); if (n2 + n3 != 2 * n2 || int(n2) != nExprVar) { *m_stream << _T(" Number of expression variables is incorrect. (expected: ") << nExprVar << _T("; detected: ") << n2 << _T(")"); } } } // Check the three results // 1.) computed results must have identic type char_type cType = fVal[0].GetType(); bool bStat = cType == fVal[1].GetType() && cType == fVal[2].GetType() && cType == fVal[3].GetType() && cType == fVal[4].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; } if ((cType == 'c' || a_val.GetType() == 'c') && cType != a_val.GetType()) { *m_stream << _T("\n ") << a_str << _T(" : Complex value sliced!"); 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()) { for (int i = 0; i < v1.GetRows(); ++i) { for (int j = 0; j < v1.GetCols(); ++j) { if (!Check(v1.At(i, j), v2.At(i, j))) 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 muparserx-4.0.11/parser/mpTest.h000066400000000000000000000071271414723276500165660ustar00rootroot00000000000000/* __________ ____ ___ _____ __ _\______ \_____ _______ ______ __________\ \/ / / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ / | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \ \/ \/ \/ \/ \_/ Copyright (C) 2016, Ingo Berg All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef MU_PARSER_TEST_H #define MU_PARSER_TEST_H #include #include // for accumulate #include "mpParser.h" #include "mpOprtBinCommon.h" MUP_NAMESPACE_START /** \brief Test cases for unit testing the parser framework. */ class ParserTester // final { private: static int c_iCount; int TestParserValue(); int TestErrorCodes(); int TestStringFun(); int TestVector(); int TestBinOp(); int TestPostfix(); int TestInfix(); int TestEqn(); int TestMultiArg(); int TestUndefVar(); int TestIfElse(); int TestMatrix(); int TestComplex(); int TestScript(); int TestValReader(); int TestIssueReports(); 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 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, bool evaluateOnce = false); int ThrowTest(const string_type &a_str, int a_nErrc, int a_nPos = -1, string_type a_sIdent = string_type()); }; // ParserTester } // namespace mu #endif muparserx-4.0.11/parser/mpTokenReader.cpp000066400000000000000000000746171414723276500204150ustar00rootroot00000000000000/** \file \brief Implementation of the token reader used to break the expression string up into tokens.
				__________                                 ____  ___
	 _____  __ _\______   \_____ _______  ______ __________\   \/  /
	/     \|  |  \     ___/\__  \\_  __ \/  ___// __ \_  __ \     /
	|  Y Y  \  |  /    |     / __ \|  | \/\___ \\  ___/|  | \/     \
	|__|_|  /____/|____|    (____  /__|  /____  >\___  >__| /___/\  \
		  \/                     \/           \/     \/           \_/
	Copyright (C) 2021 Ingo Berg, et al.
	All rights reserved.

	Redistribution and use in source and binary forms, with or without
	modification, are permitted provided that the following conditions are met:

	* Redistributions of source code must retain the above copyright notice,
	this list of conditions and the following disclaimer.
	* Redistributions in binary form must reproduce the above copyright notice,
	this list of conditions and the following disclaimer in the documentation
	and/or other materials provided with the distribution.

	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
	ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
	WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
	IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
	INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
	NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
	PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
	WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
	POSSIBILITY OF SUCH DAMAGE.
	
*/ #include "mpTokenReader.h" #include #include #include "mpParserBase.h" #include "mpIValReader.h" #include "mpIfThenElse.h" #include "mpScriptTokens.h" #include "mpOprtIndex.h" #include "mpOprtMatrix.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_nNumCurly = obj.m_nNumCurly; 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_pOprtShortcutDef = obj.m_pOprtShortcutDef; 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 nullptr \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_nNumCurly(0) , m_nNumIfElse(0) , m_nSynFlags(0) , m_vTokens() , m_eLastTokCode(cmUNKNOWN) , m_pFunDef(nullptr) , m_pOprtDef(nullptr) , m_pOprtShortcutDef(nullptr) , m_pInfixOprtDef(nullptr) , m_pPostOprtDef(nullptr) , m_pConstDef(nullptr) , m_pDynVarShadowValues(nullptr) , m_pVarDef(nullptr) , 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::unique_ptr 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_sExpr) { if (a_sExpr.empty()) throw ParserError(_T("Expression is empty!"), ecUNEXPECTED_EOF); if (a_sExpr.find_first_not_of(' ') == std::string::npos) throw ParserError(_T("Expression is empty!"), ecUNEXPECTED_EOF); if (std::all_of(a_sExpr.begin(), a_sExpr.end(), [](char_type c) { return !std::isgraph(c); })) throw ParserError(_T("Non printable characters in expression found!")); // Check maximum allowed expression length. An arbitrary value small enough so i can debug expressions sent to me if (a_sExpr.length() >= 10000) throw ParserError(_T("Expression longer than 10000 characters!")); m_sExpr = a_sExpr; 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_nNumCurly = 0; m_nNumIfElse = 0; m_nSynFlags = noOPT | noBC | noCBC | noPFX | noCOMMA | noIO | noIC | noIF | noELSE; m_UsedVar.clear(); m_eLastTokCode = cmUNKNOWN; m_vTokens.clear(); } //--------------------------------------------------------------------------- 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; } //--------------------------------------------------------------------------- void TokenReader::SkipCommentsAndWhitespaces() { bool bSkip = true; while (m_nPos < static_cast(m_sExpr.length()) && bSkip) { switch (m_sExpr[m_nPos]) { // skip comments case '#': { std::size_t i = m_sExpr.find_first_of('\n', m_nPos + 1); m_nPos = static_cast((i != string_type::npos) ? i : m_sExpr.length()); } break; // skip whitespaces case ' ': ++m_nPos; break; default: bSkip = false; } // switch } // while comment or whitespace } //--------------------------------------------------------------------------- /** \brief Read the next token from the string. */ ptr_tok_type TokenReader::ReadNextToken() { assert(m_pParser); SkipCommentsAndWhitespaces(); 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 (IsScOprt(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 // // 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_pOprtShortcutDef = &a_pParent->m_OprtShortcutDef; m_pInfixOprtDef = &a_pParent->m_InfixOprtDef; m_pPostOprtDef = &a_pParent->m_PostOprtDef; m_pVarDef = &a_pParent->m_varDef; m_pConstDef = &a_pParent->m_valDef; 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::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 | noCBC | 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 ecMISPLACED_COLON; m_nNumIfElse--; if (m_nNumIfElse < 0) throw ecMISPLACED_COLON; m_nSynFlags = noBC | noCBC | 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 | noCBC | 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 | noCBC; } else { m_nSynFlags = noBC | noOPT | noEND | noNEWLINE | noCOMMA | noPFX | noIC | noIO | noIF | noELSE | noCBC; } 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 | noCBO; 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 | noCBC | noCOMMA; 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 | noCBO; m_nNumIndex--; if (m_nNumIndex < 0) throw ecUNEXPECTED_SQR_BRACKET; a_Tok = ptr_tok_type(new OprtIndex()); break; case cmCBO: if (m_nSynFlags & noVAL) throw ecUNEXPECTED_CURLY_BRACKET; m_nSynFlags = noCBC | noIC | noIO | noOPT | noPFX | noBC | noNEWLINE | noCOMMA | noIF; m_nNumCurly++; a_Tok = ptr_tok_type(new GenericToken((ECmdCode)i, pOprtDef[i])); break; case cmCBC: if (m_nSynFlags & noIC) throw ecUNEXPECTED_CURLY_BRACKET; m_nSynFlags = noBO | noCBO | noIFX; m_nNumCurly--; if (m_nNumCurly < 0) throw ecUNEXPECTED_CURLY_BRACKET; a_Tok = ptr_tok_type(new OprtCreateArray()); 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_nNumCurly > 0) throw ecMISSING_CURLY_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_nNumCurly > 0) throw ecMISSING_CURLY_BRACKET; 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 | noIF | noELSE; 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) { if (m_nSynFlags & noPFX) { // Only look for postfix operators if they are allowed at the given position. // This will prevent conflicts with variable names such as: // "sin(n)" where n is the postfix for "nano" return false; // } // 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*/ | noIF; 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_maptype::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 | noIF | noELSE; 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 if a string position contains a binary operator. */ bool TokenReader::IsScOprt(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_shortcut_maptype::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_pOprtShortcutDef->rbegin(); item != m_pOprtShortcutDef->rend(); ++item) { if (sTok.find(item->first) != 0) continue; // operator found, check if we expect one... 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 | noIF | noELSE; 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 || (sTok.size() > 0 && sTok[0] >= _T('0') && sTok[0] <= _T('9'))) 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 = ptr_tok_type(item->second->Clone()); 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 = ptr_tok_type(item->second->Clone()); a_Tok->SetIdent(sTok); return true; } } catch (EErrorCodes e) { ErrorContext err; err.Errc = e; err.Pos = m_nPos; err.Ident = sTok; err.Expr = m_sExpr; throw ParserError(err); } return false; } //--------------------------------------------------------------------------- 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 || (sTok.size() > 0 && sTok[0] >= _T('0') && sTok[0] <= _T('9'))) return false; if (m_nSynFlags & noVAR) { ErrorContext err; err.Errc = ecUNEXPECTED_VAR; err.Ident = sTok; err.Expr = m_sExpr; err.Pos = m_nPos; 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(nullptr)); // 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 muparserx-4.0.11/parser/mpTokenReader.h000066400000000000000000000123751414723276500200530ustar00rootroot00000000000000/** \file \brief Definition of the token reader used to break the expression string up into tokens.
               __________                                 ____  ___
    _____  __ _\______   \_____ _______  ______ __________\   \/  /
   /     \|  |  \     ___/\__  \\_  __ \/  ___// __ \_  __ \     / 
  |  Y Y  \  |  /    |     / __ \|  | \/\___ \\  ___/|  | \/     \ 
  |__|_|  /____/|____|    (____  /__|  /____  >\___  >__| /___/\  \
        \/                     \/           \/     \/           \_/
  Copyright (C) 2021 Ingo Berg, et al.
  All rights reserved.

  Redistribution and use in source and binary forms, with or without 
  modification, are permitted provided that the following conditions are met:

   * Redistributions of source code must retain the above copyright notice, 
     this list of conditions and the following disclaimer.
   * Redistributions in binary form must reproduce the above copyright notice, 
     this list of conditions and the following disclaimer in the documentation 
     and/or other materials provided with the distribution.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
  POSSIBILITY OF SUCH DAMAGE.
  
*/ #ifndef MUP_TOKEN_READER_H #define MUP_TOKEN_READER_H //--- Standard includes ---------------------------------------------------- #include #include #include #include #include #include //--- 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 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; void SkipCommentsAndWhitespaces(); 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 IsScOprt(ptr_tok_type &a_Tok); 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_nNumCurly; ///< Number of open curly brackets 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_maptype *m_pOprtDef; mutable oprt_bin_shortcut_maptype *m_pOprtShortcutDef; 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); 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 muparserx-4.0.11/parser/mpTypes.h000066400000000000000000000404711414723276500167520ustar00rootroot00000000000000/** \file \brief Definition of basic types used by muParserX
               __________                                 ____  ___
    _____  __ _\______   \_____ _______  ______ __________\   \/  /
   /     \|  |  \     ___/\__  \\_  __ \/  ___// __ \_  __ \     /
  |  Y Y  \  |  /    |     / __ \|  | \/\___ \\  ___/|  | \/     \
  |__|_|  /____/|____|    (____  /__|  /____  >\___  >__| /___/\  \
	    \/                     \/           \/     \/           \_/
				       Copyright (C) 2016, Ingo Berg
				       All rights reserved.

  Redistribution and use in source and binary forms, with or without
  modification, are permitted provided that the following conditions are met:

   * Redistributions of source code must retain the above copyright notice,
     this list of conditions and the following disclaimer.
   * Redistributions in binary form must reproduce the above copyright notice,
     this list of conditions and the following disclaimer in the documentation
     and/or other materials provided with the distribution.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  POSSIBILITY OF SUCH DAMAGE.
*/ #ifndef MUP_TYPES_H #define MUP_TYPES_H //--- Standard include ------------------------------------------------------ #include #include #include #include #include #include //--- muParserX framework --------------------------------------------------- #include "suSortPred.h" // We need the string utils sorting predicates #include "mpDefines.h" #include "mpMatrix.h" #include "mpCompat.h" MUP_NAMESPACE_START // Forward declarations class IValueReader; class IOprtBin; class IOprtPostfix; class IOprtInfix; class IFunction; class IToken; class ICallback; class IValue; class ParserXBase; class Value; class Variable; class TokenReader; class IOprtBinShortcut; // smart pointer types template class TokenPtr; /** \brief Type of a managed pointer storing parser tokens. */ typedef TokenPtr ptr_tok_type; /** \brief Type of a managed pointer storing callback tokens. */ typedef TokenPtr ptr_cal_type; /** \brief Type of a managed pointer storing value tokens. */ typedef TokenPtr ptr_val_type; /** \brief Type of a managed pointer storing binary operator tokens. */ typedef TokenPtr ptr_binop_type; /** \brief Type for a vector of tokens. */ typedef std::vector token_vec_type; /** \brief Type for a vector of value items. */ typedef std::vector val_vec_type; // parser type definitions /** \brief Parser datatype for floating point value. */ typedef MUP_FLOAT_TYPE float_type; /** \brief Parser datatype for integer valuse. */ typedef MUP_INT_TYPE int_type; /** \brief The basic type used for representing complex numbers. */ typedef std::complex 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 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, std::allocator > stringstream_type; /** \brief Type of a vector holding pointers to value reader objects. */ typedef std::vector readervec_type; /** \brief type for the parser variable storage. */ typedef std::map var_maptype; /** \brief type of a container used to store parser values. */ typedef std::map val_maptype; /** \brief Type of a container that binds Callback object pointer to operator identifiers. */ typedef std::map fun_maptype; /** \breief Type of a container that short circuit operator object pointer*/ typedef std::map oprt_bin_shortcut_maptype; /** \brief Type of a container that binds Callback object pointer to operator identifiers. */ typedef std::map > oprt_bin_maptype; /** \brief Type of a map for storing postfix operators by their name. */ typedef std::map oprt_pfx_maptype; /** \brief Type of a map for storing infix operators by their name. */ typedef std::map 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 cmCBO = 4, ///< Operator item: curly bracket (opening) cmCBC = 5, ///< Operator item: curly bracket (closing) cmARG_SEP = 6, ///< Operator item: comma cmIF = 7, ///< Ternary if then else operator cmELSE = 8, ///< Ternary if then else operator cmENDIF = 9, ///< Ternary if then else operator cmJMP = 10, ///< Reserved for future use cmVAL = 11, ///< value item cmFUNC = 12, ///< Code for a function item cmOPRT_BIN = 13, ///< Binary operator cmOPRT_INFIX = 14, ///< Infix operator cmOPRT_POSTFIX = 15, ///< Postfix operator cmSHORTCUT_BEGIN = 16, ///< Short circuit operator && / || cmSHORTCUT_END = 17, ///< Short circuit operator && / || cmEOE = 18, ///< End of expression // The following codes are reserved in case i will ever turn this // into a scripting language cmSCRIPT_NEWLINE = 19, ///< Newline cmSCRIPT_COMMENT = 20, cmSCRIPT_WHILE = 21, ///< Reserved for future use cmSCRIPT_GOTO = 22, ///< Reserved for future use cmSCRIPT_LABEL = 23, ///< Reserved for future use cmSCRIPT_FOR = 24, ///< Reserved for future use cmSCRIPT_IF = 25, ///< Reserved for future use cmSCRIPT_ELSE = 26, ///< Reserved for future use cmSCRIPT_ELSEIF = 27, ///< Reserved for future use cmSCRIPT_ENDIF = 28, ///< Reserved for future use cmSCRIPT_FUNCTION = 29, ///< Reserved for future use // misc codes cmUNKNOWN = 30, ///< uninitialized item cmCOUNT ///< 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 "]" noCBO = 1 << 4, ///< No opening curly bracket noCBC = 1 << 5, ///< No opening closing bracket noVAL = 1 << 6, ///< to avoid i.e. "tan 2" or "sin(8)3.14" noVAR = 1 << 7, ///< to avoid i.e. "sin a" or "sin(8)a" noCOMMA = 1 << 8, ///< to avoid i.e. ",," or "+," ... noFUN = 1 << 9, ///< to avoid i.e. "sqrt cos" or "(1)sin" noOPT = 1 << 10, ///< to avoid i.e. "(+)" noPFX = 1 << 11, ///< to avoid i.e. "(5!!)" "sin!" noIFX = 1 << 12, ///< to avoid i.e. "++4" "!!4" noEND = 1 << 13, ///< to avoid unexpected end of expression noIF = 1 << 14, noELSE = 1 << 15, noNEWLINE = 1 << 16, ///< 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_XOR = 2, prLOGIC_AND = 3, prBIT_OR = 4, prBIT_XOR = 5, prBIT_AND = 6, prRELATIONAL1 = 7, ///< For "==", "!=" prRELATIONAL2 = 8, ///< Relational operators "<", "<=", ">", ">=" prSHIFT = 9, ///< Shift operators "<<", ">>" prCOLON = 10, ///< Colon operator prADD_SUB = 11, ///< addition prMUL_DIV = 12, ///< multiplication/division prPOW = 13, ///< power operator priority (highest) // infix operators prINFIX = 12, ///< Signs have a higher priority than ADD_SUB, but lower than power operator prPOSTFIX = 12 ///< Postfix operator priority (currently unused) }; /** \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 ecUNEXPECTED_CURLY_BRACKET = 27, ///< Invalid use of the index operator ecINVALID_NAME = 28, ///< Invalid function, variable or constant name. ecBUILTIN_OVERLOAD = 29, ///< Trying to overload builtin operator ecINVALID_FUN_PTR = 30, ///< Invalid callback function pointer ecINVALID_VAR_PTR = 31, ///< Invalid variable pointer ecINVALID_PARAMETER = 32, ///< Invalid function parameter ecINVALID_NUMBER_OF_PARAMETERS = 33, ecNAME_CONFLICT = 34, ///< Name conflict ecOPT_PRI = 35, ///< Invalid operator priority ecASSIGNEMENT_TO_VALUE = 36, ///< Assignment to operator (3=4 instead of a=4) // ecDOMAIN_ERROR = 37, ///< Trying to use func/oprtr with out-of-domain input args ecDIV_BY_ZERO = 38, ///< Division by zero (currently unused) ecGENERIC = 39, ///< Generic error ecINDEX_OUT_OF_BOUNDS = 40, ///< Array index is out of bounds ecINDEX_DIMENSION = 41, ecMISSING_SQR_BRACKET = 42, ///< The index operator was not closed properly (i.e. "v[3") ecMISSING_CURLY_BRACKET = 43, ecEVAL = 44, ///< Error while evaluating function / operator ecOVERFLOW = 45, ///< Overflow (possibly) occurred // Matrix errors ecMATRIX_DIMENSION_MISMATCH = 46, // string related errors ecUNKNOWN_ESCAPE_SEQUENCE = 47, // already-defined item errors ecVARIABLE_DEFINED = 48, ///< Variable is already defined ecCONSTANT_DEFINED = 49, ///< Constant is already defined ecFUNOPRT_DEFINED = 50, ///< Function/operator is already defined // internal errors ecINTERNAL_ERROR = 51, ///< 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 }; #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 muparserx-4.0.11/parser/mpValReader.cpp000066400000000000000000000247611414723276500200520ustar00rootroot00000000000000/** \file \brief Implementation of classes that interpret values in a string.
                 __________                                 ____  ___
      _____  __ _\______   \_____ _______  ______ __________\   \/  /
     /     \|  |  \     ___/\__  \\_  __ \/  ___// __ \_  __ \     /
    |  Y Y  \  |  /    |     / __ \|  | \/\___ \\  ___/|  | \/     \
    |__|_|  /____/|____|    (____  /__|  /____  >\___  >__| /___/\  \
          \/                     \/           \/     \/           \_/
    Copyright (C) 2016, Ingo Berg
    All rights reserved.

    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice,
    this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright notice,
    this list of conditions and the following disclaimer in the documentation
    and/or other materials provided with the distribution.

    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
    IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
    INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
    NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
    WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    POSSIBILITY OF SUCH DAMAGE.
    
*/ #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 iEnd(0); stream >> fVal; if (stream.fail()) return false; if (stream.eof()) { // This part sucks but tellg will return -1 if eof is set, // so i need a special treatment for the case that the number // just read here is the last part of the string for (; a_szExpr[a_iPos] != 0; ++a_iPos); } else { iEnd = stream.tellg(); // Position after reading assert(iEnd > 0); 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::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; if (ss.fail()) return false; if (ss.eof()) { // This part sucks but tellg will return -1 if eof is set, // so i need a special treatment for those cases. for (; a_szExpr[a_iPos] != 0; ++a_iPos); } else { nPos = ss.tellg(); assert(nPos > 0); a_iPos += (int)(2 + nPos); } a_val = (float_type)iVal; return true; } //------------------------------------------------------------------------------ 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] != '0' || (szExpr[1] != 'b' && szExpr[1] != 'B')) return false; // Number of bits hardcoded to 32, i can't // store 64 bit integers in double values without // loss. There is no point in accepting them. unsigned iVal = 0, iBits = 32 /*sizeof(iVal)*8*/, i; for (i = 0; (szExpr[i + 2] == '0' || szExpr[i + 2] == '1') && i <= iBits; ++i) { iVal |= (unsigned)(szExpr[i + 2] == '1') << ((iBits - 1) - i); } if (i == 0) return false; if (i > iBits) { throw ParserError(_T("Binary to integer conversion error (overflow).")); } a_Val = (float_type)((int)(iVal >> (iBits - i))); a_iPos += i + 2; 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() {} //------------------------------------------------------------------------------ string_type StrValReader::Unescape(const char_type *szExpr, int &nPos) { string_type out; bool bEscape = false; for (char_type c = szExpr[nPos]; c != 0; c = szExpr[++nPos]) { switch (c) { case '\\': if (!bEscape) { bEscape = true; break; } [[gnu::fallthrough]]; case '"': if (!bEscape) { ++nPos; return out; } [[gnu::fallthrough]]; default: if (bEscape) { switch (c) { case 'n': out += '\n'; break; case 'r': out += '\r'; break; case 't': out += '\t'; break; case '"': out += '\"'; break; case '\\': out += '\\'; break; default: throw ParserError(ErrorContext(ecUNKNOWN_ESCAPE_SEQUENCE, nPos)); } bEscape = false; } else { out += c; } } } throw ParserError(ErrorContext(ecUNTERMINATED_STRING, nPos)); } //------------------------------------------------------------------------------ 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; a_Val = Unescape(a_pszExpr, ++a_iPos); return true; } //------------------------------------------------------------------------------ IValueReader* StrValReader::Clone(TokenReader *pTokenReader) const { IValueReader *pReader = new StrValReader(*this); pReader->SetParent(pTokenReader); return pReader; } } // namespace mu muparserx-4.0.11/parser/mpValReader.h000066400000000000000000000122171414723276500175100ustar00rootroot00000000000000/** \file \brief Definition of classes that interpret values in a string.
               __________                                 ____  ___
    _____  __ _\______   \_____ _______  ______ __________\   \/  /
   /     \|  |  \     ___/\__  \\_  __ \/  ___// __ \_  __ \     / 
  |  Y Y  \  |  /    |     / __ \|  | \/\___ \\  ___/|  | \/     \ 
  |__|_|  /____/|____|    (____  /__|  /____  >\___  >__| /___/\  \
        \/                     \/           \/     \/           \_/
                                       Copyright (C) 2016, Ingo Berg
                                       All rights reserved.

  Redistribution and use in source and binary forms, with or without 
  modification, are permitted provided that the following conditions are met:

   * Redistributions of source code must retain the above copyright notice, 
     this list of conditions and the following disclaimer.
   * Redistributions in binary form must reproduce the above copyright notice, 
     this list of conditions and the following disclaimer in the documentation 
     and/or other materials provided with the distribution.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
  POSSIBILITY OF SUCH DAMAGE.
  
*/ #ifndef MU_PARSER_IMPL_READER_H #define MU_PARSER_IMPL_READER_H #include "mpIValReader.h" MUP_NAMESPACE_START //------------------------------------------------------------------------------ // // Reader for floating point 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) override; virtual IValueReader* Clone(TokenReader *pTokenReader) const override; }; //------------------------------------------------------------------------------ // // 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) override; virtual IValueReader* Clone(TokenReader *pTokenReader) const override; }; //------------------------------------------------------------------------------ // // 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) override; virtual IValueReader* Clone(TokenReader *pTokenReader) const override; }; //------------------------------------------------------------------------------ // // 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) override; virtual IValueReader* Clone(TokenReader *pTokenReader) const override; }; //------------------------------------------------------------------------------ // // 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) override; virtual IValueReader* Clone(TokenReader *pTokenReader) const override; private: string_type Unescape(const char_type *szExpr, int &len); }; MUP_NAMESPACE_END #endif muparserx-4.0.11/parser/mpValue.cpp000066400000000000000000000473741414723276500172660ustar00rootroot00000000000000/*
			 __________                                 ____  ___
  _____  __ _\______   \_____ _______  ______ __________\   \/  /
 /     \|  |  \     ___/\__  \\_  __ \/  ___// __ \_  __ \     /
|  Y Y  \  |  /    |     / __ \|  | \/\___ \\  ___/|  | \/     \
|__|_|  /____/|____|    (____  /__|  /____  >\___  >__| /___/\  \
	  \/                     \/           \/     \/           \_/
Copyright (C) 2016, Ingo Berg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/ #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(nullptr) , m_pvVal(nullptr) , m_cType(cType) , m_iFlags(flNONE) , m_pCache(nullptr) { // 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.0)); break; } } //--------------------------------------------------------------------------- Value::Value(int_type a_iVal) :IValue(cmVAL) , m_val((float_type)a_iVal, 0) , m_psVal(nullptr) , m_pvVal(nullptr) , m_cType('i') , m_iFlags(flNONE) , m_pCache(nullptr) {} //--------------------------------------------------------------------------- Value::Value(bool_type a_bVal) :IValue(cmVAL) , m_val((float_type)a_bVal, 0) , m_psVal(nullptr) , m_pvVal(nullptr) , m_cType('b') , m_iFlags(flNONE) , m_pCache(nullptr) {} //--------------------------------------------------------------------------- Value::Value(string_type a_sVal) :IValue(cmVAL) , m_val() , m_psVal(new string_type(a_sVal)) , m_pvVal(nullptr) , m_cType('s') , m_iFlags(flNONE) , m_pCache(nullptr) {} //--------------------------------------------------------------------------- Value::Value(int_type array_size, float_type v) :IValue(cmVAL) , m_val() , m_psVal(nullptr) , m_pvVal(new matrix_type(array_size, Value(v))) , m_cType('m') , m_iFlags(flNONE) , m_pCache(nullptr) {} //--------------------------------------------------------------------------- /** \brief Create a m x n matrix */ Value::Value(int_type m, int_type n, float_type v) :IValue(cmVAL) , m_val() , m_psVal(nullptr) , m_pvVal(new matrix_type(m, n, Value(v))) , m_cType('m') , m_iFlags(flNONE) , m_pCache(nullptr) {} //--------------------------------------------------------------------------- Value::Value(const char_type* a_szVal) :IValue(cmVAL) , m_val() , m_psVal(new string_type(a_szVal)) , m_pvVal(nullptr) , m_cType('s') , m_iFlags(flNONE) , m_pCache(nullptr) {} //--------------------------------------------------------------------------- Value::Value(const cmplx_type& v) :IValue(cmVAL) , m_val(v) , m_psVal(nullptr) , m_pvVal(nullptr) , m_cType('c') , m_iFlags(flNONE) , m_pCache(nullptr) { // modified as suggested here: https://github.com/beltoforion/muparserx/issues/98 m_cType = (m_val.imag() == 0) ? ((std::floor(m_val.real()) == m_val.real()) ? 'i' : 'f') : 'c'; } //--------------------------------------------------------------------------- Value::Value(float_type val) :IValue(cmVAL) , m_val(val, 0) , m_psVal(nullptr) , m_pvVal(nullptr) , m_cType((val == (int_type)val) ? 'i' : 'f') , m_iFlags(flNONE) , m_pCache(nullptr) {} //--------------------------------------------------------------------------- Value::Value(const matrix_type& val) :IValue(cmVAL) , m_val() , m_psVal(nullptr) , m_pvVal(new matrix_type(val)) , m_cType('m') , m_iFlags(flNONE) , m_pCache(nullptr) {} //--------------------------------------------------------------------------- Value::Value(const Value& a_Val) :IValue(cmVAL) , m_psVal(nullptr) , m_pvVal(nullptr) , m_pCache(nullptr) { Assign(a_Val); } //--------------------------------------------------------------------------- Value::Value(const IValue& a_Val) :IValue(cmVAL) , m_psVal(nullptr) , m_pvVal(nullptr) , m_pCache(nullptr) { 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.Type1 = (!row.IsInteger()) ? row.GetType() : col.GetType(); errc.Type2 = 'i'; throw ParserError(errc); } int_type 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 = nullptr; } // allocate room for a vector if (ref.m_pvVal) { if (m_pvVal == nullptr) m_pvVal = new matrix_type(*ref.m_pvVal); else *m_pvVal = *ref.m_pvVal; } else { delete m_pvVal; m_pvVal = nullptr; } // 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 = nullptr; delete m_pvVal; m_pvVal = nullptr; m_cType = 'f'; m_iFlags = flNONE; } //--------------------------------------------------------------------------- IValue& Value::operator=(bool val) { m_val = cmplx_type((float_type)val, 0); delete m_psVal; m_psVal = nullptr; delete m_pvVal; m_pvVal = nullptr; 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 = nullptr; delete m_pvVal; m_pvVal = nullptr; 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 = nullptr; delete m_pvVal; m_pvVal = nullptr; 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 = nullptr; 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 = nullptr; 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 = nullptr; if (m_pvVal == nullptr) 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 = nullptr; delete m_pvVal; m_pvVal = nullptr; // modified as suggested here: https://github.com/beltoforion/muparserx/issues/98 m_cType = (m_val.imag() == 0) ? ((std::floor(m_val.real()) == 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(); // modified as suggested here: https://github.com/beltoforion/muparserx/issues/98 m_cType = (m_val.imag() == 0) ? ((std::floor(m_val.real()) == m_val.real()) ? 'i' : 'f') : 'c'; } 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(); // modified as suggested here: https://github.com/beltoforion/muparserx/issues/98 m_cType = (m_val.imag() == 0) ? ((std::floor(m_val.real()) == m_val.real()) ? 'i' : 'f') : 'c'; } 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(); // modified as suggested here: https://github.com/beltoforion/muparserx/issues/98 m_cType = (m_val.imag() == 0) ? ((std::floor(m_val.real()) == m_val.real()) ? 'i' : 'f') : 'c'; } 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') { 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 { 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 != nullptr); 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 != nullptr); return *m_pvVal; } //--------------------------------------------------------------------------- int Value::GetRows() const { return (GetType() != 'm') ? 1 : GetArray().GetRows(); } //--------------------------------------------------------------------------- int Value::GetCols() const { return (GetType() != 'm') ? 1 : GetArray().GetCols(); } //--------------------------------------------------------------------------- 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::IsVariable() const { return false; } //--------------------------------------------------------------------------- string_type Value::AsciiDump() const { stringstream_type ss; ss << g_sCmdCode[GetCode()]; ss << _T(" [addr=0x") << std::hex << this << std::dec; ss << _T("; pos=") << GetExprPos(); 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 != nullptr); ss << _T("\"") << m_psVal << _T("\""); break; } ss << ((IsFlagSet(IToken::flVOLATILE)) ? _T("; ") : _T("; not ")) << _T("vol"); 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; } //----------------------------------------------------------------------------------------------- Value::operator cmplx_type () { return GetComplex(); } //----------------------------------------------------------------------------------------------- Value::operator int_type() { return GetInteger(); } //----------------------------------------------------------------------------------------------- Value::operator string_type() { return GetString(); } //----------------------------------------------------------------------------------------------- Value::operator float_type() { return GetFloat(); } //----------------------------------------------------------------------------------------------- Value::operator bool() { return GetBool(); } } // namespace mu muparserx-4.0.11/parser/mpValue.h000066400000000000000000000124641414723276500167230ustar00rootroot00000000000000/** \file \brief Definition of basic types used by muParserX
               __________                                 ____  ___
    _____  __ _\______   \_____ _______  ______ __________\   \/  /
   /     \|  |  \     ___/\__  \\_  __ \/  ___// __ \_  __ \     / 
  |  Y Y  \  |  /    |     / __ \|  | \/\___ \\  ___/|  | \/     \ 
  |__|_|  /____/|____|    (____  /__|  /____  >\___  >__| /___/\  \
        \/                     \/           \/     \/           \_/
                                       Copyright (C) 2016, Ingo Berg
                                       All rights reserved.

  Redistribution and use in source and binary forms, with or without 
  modification, are permitted provided that the following conditions are met:

   * Redistributions of source code must retain the above copyright notice, 
     this list of conditions and the following disclaimer.
   * Redistributions in binary form must reproduce the above copyright notice, 
     this list of conditions and the following disclaimer in the documentation 
     and/or other materials provided with the distribution.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
  POSSIBILITY OF SUCH DAMAGE.
  
*/ #ifndef MUP_VALUE_H #define MUP_VALUE_H //--- Standard includes ------------------------------------------------------------ #include #include //--- 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) override; virtual IValue& At(const IValue &row, const IValue &col) override; virtual IValue& operator=(int_type a_iVal) override; virtual IValue& operator=(float_type a_fVal) override; virtual IValue& operator=(string_type a_sVal) override; virtual IValue& operator=(bool val) override; virtual IValue& operator=(const matrix_type &a_vVal) override; virtual IValue& operator=(const cmplx_type &val) override; virtual IValue& operator=(const char_type *a_szVal); virtual IValue& operator+=(const IValue &val) override; virtual IValue& operator-=(const IValue &val) override; virtual IValue& operator*=(const IValue &val) override; virtual char_type GetType() const override; virtual int_type GetInteger() const override; virtual float_type GetFloat() const override; virtual float_type GetImag() const override; virtual bool GetBool() const override; virtual const cmplx_type& GetComplex() const override; virtual const string_type& GetString() const override; virtual const matrix_type& GetArray() const override; virtual int GetRows() const override; virtual int GetCols() const override; virtual bool IsVariable() const override; virtual IToken* Clone() const override; virtual Value* AsValue() override; virtual string_type AsciiDump() const override; void BindToCache(ValueCache *pCache); // Conversion operators operator cmplx_type(); operator int_type(); operator string_type(); operator float_type(); operator bool(); 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 void CheckType(char_type a_cType) const; void Assign(const Value &a_Val); void Reset(); virtual void Release() override; }; // class Value MUP_NAMESPACE_END #endif muparserx-4.0.11/parser/mpValueCache.cpp000066400000000000000000000072071414723276500202010ustar00rootroot00000000000000/** \file \brief Definition of a class for caching unused value items and recycling them.
               __________                                 ____  ___
    _____  __ _\______   \_____ _______  ______ __________\   \/  /
   /     \|  |  \     ___/\__  \\_  __ \/  ___// __ \_  __ \     / 
  |  Y Y  \  |  /    |     / __ \|  | \/\___ \\  ___/|  | \/     \ 
  |__|_|  /____/|____|    (____  /__|  /____  >\___  >__| /___/\  \
        \/                     \/           \/     \/           \_/
                                       Copyright (C) 2016, Ingo Berg
                                       All rights reserved.

  Redistribution and use in source and binary forms, with or without 
  modification, are permitted provided that the following conditions are met:

   * Redistributions of source code must retain the above copyright notice, 
     this list of conditions and the following disclaimer.
   * Redistributions in binary form must reproduce the above copyright notice, 
     this list of conditions and the following disclaimer in the documentation 
     and/or other materials provided with the distribution.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
  POSSIBILITY OF SUCH DAMAGE.
*/ #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 nullptr gcc will go postal... {} //------------------------------------------------------------------------------ ValueCache::~ValueCache() { ReleaseAll(); } //------------------------------------------------------------------------------ void ValueCache::ReleaseAll() { for (std::size_t i=0; iGetRef()==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 = nullptr; if (m_nIdx>=0) { pValue = m_vCache[m_nIdx]; m_vCache[m_nIdx] = nullptr; m_nIdx--; } else { pValue = new Value(); pValue->BindToCache(this); } return pValue; } MUP_NAMESPACE_END muparserx-4.0.11/parser/mpValueCache.h000066400000000000000000000055101414723276500176410ustar00rootroot00000000000000#ifndef MUP_VALUE_CACHE_H #define MUP_VALUE_CACHE_H /** \file \brief Implementation of a cache for recycling unused value items.
               __________                                 ____  ___
    _____  __ _\______   \_____ _______  ______ __________\   \/  /
   /     \|  |  \     ___/\__  \\_  __ \/  ___// __ \_  __ \     / 
  |  Y Y  \  |  /    |     / __ \|  | \/\___ \\  ___/|  | \/     \ 
  |__|_|  /____/|____|    (____  /__|  /____  >\___  >__| /___/\  \
        \/                     \/           \/     \/           \_/
                                       Copyright (C) 2016, Ingo Berg
                                       All rights reserved.

  Redistribution and use in source and binary forms, with or without 
  modification, are permitted provided that the following conditions are met:

   * Redistributions of source code must retain the above copyright notice, 
     this list of conditions and the following disclaimer.
   * Redistributions in binary form must reproduce the above copyright notice, 
     this list of conditions and the following disclaimer in the documentation 
     and/or other materials provided with the distribution.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
  POSSIBILITY OF SUCH DAMAGE.
*/ #include #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 m_vCache; }; MUP_NAMESPACE_END #endif // include guard muparserx-4.0.11/parser/mpVariable.cpp000066400000000000000000000277561414723276500177410ustar00rootroot00000000000000/** \file \brief Implementation of the muParserX variable class.
               __________                                 ____  ___
    _____  __ _\______   \_____ _______  ______ __________\   \/  /
   /     \|  |  \     ___/\__  \\_  __ \/  ___// __ \_  __ \     / 
  |  Y Y  \  |  /    |     / __ \|  | \/\___ \\  ___/|  | \/     \ 
  |__|_|  /____/|____|    (____  /__|  /____  >\___  >__| /___/\  \
        \/                     \/           \/     \/           \_/
                                       Copyright (C) 2016, Ingo Berg
                                       All rights reserved.

  Redistribution and use in source and binary forms, with or without 
  modification, are permitted provided that the following conditions are met:

   * Redistributions of source code must retain the above copyright notice, 
     this list of conditions and the following disclaimer.
   * Redistributions in binary form must reproduce the above copyright notice, 
     this list of conditions and the following disclaimer in the documentation 
     and/or other materials provided with the distribution.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
  POSSIBILITY OF SUCH DAMAGE.
*/ #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 nullptr. Such variable objects must be bound later in order to be of any use. The parser does NOT assume ownership over the pointer! */ Variable::Variable(IValue *pVal) :IValue(cmVAL) ,m_pVal(pVal) { AddFlags(IToken::flVOLATILE); } //----------------------------------------------------------------------------------------------- Variable::Variable(const Variable &obj) :IValue(cmVAL) { 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 { try { return m_pVal->GetInteger(); } catch (ParserError &exc) { exc.GetContext().Ident = GetIdent(); throw; } } //----------------------------------------------------------------------------------------------- float_type Variable::GetFloat() const { try { return m_pVal->GetFloat(); } catch (ParserError &exc) { exc.GetContext().Ident = GetIdent(); throw; } } //----------------------------------------------------------------------------------------------- float_type Variable::GetImag() const { try { return m_pVal->GetImag(); } catch (ParserError &exc) { exc.GetContext().Ident = GetIdent(); throw; } } //----------------------------------------------------------------------------------------------- const cmplx_type& Variable::GetComplex() const { try { return m_pVal->GetComplex(); } catch (ParserError &exc) { exc.GetContext().Ident = GetIdent(); throw; } } //----------------------------------------------------------------------------------------------- const string_type& Variable::GetString() const { try { return m_pVal->GetString(); } catch (ParserError &exc) { exc.GetContext().Ident = GetIdent(); throw; } } //----------------------------------------------------------------------------------------------- bool Variable::GetBool() const { try { return m_pVal->GetBool(); } catch (ParserError &exc) { exc.GetContext().Ident = GetIdent(); throw; } } //----------------------------------------------------------------------------------------------- const matrix_type& Variable::GetArray() const { try { return m_pVal->GetArray(); } catch (ParserError &exc) { exc.GetContext().Ident = GetIdent(); throw; } } //----------------------------------------------------------------------------------------------- int Variable::GetRows() const { try { return m_pVal->GetRows(); } catch (ParserError &exc) { exc.GetContext().Ident = GetIdent(); throw; } } //----------------------------------------------------------------------------------------------- int Variable::GetCols() const { try { return m_pVal->GetCols(); } catch (ParserError &exc) { exc.GetContext().Ident = GetIdent(); throw; } } //----------------------------------------------------------------------------------------------- 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::IsVariable() const { return true; } //----------------------------------------------------------------------------------------------- IToken* Variable::Clone() const { return new Variable(*this); } //----------------------------------------------------------------------------------------------- Value* Variable::AsValue() { return nullptr; } //----------------------------------------------------------------------------------------------- string_type Variable::AsciiDump() const { stringstream_type ss; ss << g_sCmdCode[ GetCode() ]; ss << _T(" [addr=0x") << std::hex << this << std::dec; ss << _T("; pos=") << GetExprPos(); 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("vol"); ss << _T("]"); return ss.str(); } MUP_NAMESPACE_END muparserx-4.0.11/parser/mpVariable.h000066400000000000000000000100671414723276500173710ustar00rootroot00000000000000/** \file \brief Definition of the muParserX variable class.
               __________                                 ____  ___
    _____  __ _\______   \_____ _______  ______ __________\   \/  /
   /     \|  |  \     ___/\__  \\_  __ \/  ___// __ \_  __ \     / 
  |  Y Y  \  |  /    |     / __ \|  | \/\___ \\  ___/|  | \/     \ 
  |__|_|  /____/|____|    (____  /__|  /____  >\___  >__| /___/\  \
        \/                     \/           \/     \/           \_/
                                       Copyright (C) 2016, Ingo Berg
                                       All rights reserved.

  Redistribution and use in source and binary forms, with or without 
  modification, are permitted provided that the following conditions are met:

   * Redistributions of source code must retain the above copyright notice, 
     this list of conditions and the following disclaimer.
   * Redistributions in binary form must reproduce the above copyright notice, 
     this list of conditions and the following disclaimer in the documentation 
     and/or other materials provided with the distribution.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
  POSSIBILITY OF SUCH DAMAGE.
*/ #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 IsVariable() const; virtual IToken* Clone() const; virtual Value* AsValue(); 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 muparserx-4.0.11/parser/suSortPred.h000066400000000000000000000047411414723276500174230ustar00rootroot00000000000000#ifndef SU_PRED_H #define SU_PRED_H /* __________ ____ ___ _____ __ _\______ \_____ _______ ______ __________\ \/ / / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ / | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \ \/ \/ \/ \/ \_/ Copyright (C) 2016, Ingo Berg All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** \brief Namespace containing utility functions and classes for string processing. */ namespace su { namespace pred { /** \brief Sort two strings based on their length. */ template struct SortByLength { 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 muparserx-4.0.11/parser/suStringTokens.h000066400000000000000000000136711414723276500203150ustar00rootroot00000000000000/* __________ ____ ___ _____ __ _\______ \_____ _______ ______ __________\ \/ / / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ / | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \ \/ \/ \/ \/ \_/ Copyright (C) 2013 Ingo Berg All rights reserved. muParserX - A C++ math parser library with array and string support Copyright (c) 2013, Ingo Berg All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef SU_STRING_TOKENS_H #define SU_STRING_TOKENS_H #include #include #include #include namespace su { struct TokenNotFound : public std::runtime_error { TokenNotFound() : std::runtime_error("Token not found") {}; }; //--------------------------------------------------------------------------- // // Deklaration: StringTokens // // Zweck: Klasse zum Zerlegen eines durch beliebige Trennungszeichen // (Tokens) geteilten Strings. Die Teilstrings werden in einem // vector abgelegt und können über ihren Index, oder eine // Suchfunktion angesprochen werden. // // Einschränkungen: Die Klasse ist als Template geschrieben. Der Template // Parameter entspricht dem Typ des Ausgangsstringes. // //--------------------------------------------------------------------------- template /* final */ class StringTokens { public: typedef TData string_type; typedef typename TData::value_type char_type; private: typedef std::vector storage_type; public: //--- Konstruktor ----------------------------------------------------------- StringTokens(const string_type &a_sInput, const string_type &a_sDelim = " ") :m_delimiter(a_sDelim) ,m_tokens() { Tokenize(a_sInput, a_sDelim); } //--- Default Konstruktor --------------------------------------------------- StringTokens() :m_delimiter(string_type(" ")) ,m_tokens() {} //--- Destruktor ------------------------------------------------------------ ~StringTokens() {} //--------------------------------------------------------------------------- void Tokenize(const string_type &a_sInput, const string_type &a_sDelim = " ") { string_type buf(a_sInput); int j = 0; for (int i=0; i<(int)buf.length(); ++i) { if ( a_sDelim.find(buf[i])!=buf.npos ) { if (i!=j) m_tokens.push_back( TData(buf.substr(j, i-j).c_str()) ); j = i+1; } } if ( j < (int)(buf.length()) ) m_tokens.push_back( string_type(buf.substr(j).c_str()) ); } //--------------------------------------------------------------------------- typename const storage_type& Get() const { return m_tokens; } //--------------------------------------------------------------------------- unsigned int Count() const { return static_cast(m_tokens.size()); } //--------------------------------------------------------------------------- // Zweck: Rückgabe des Tokens, das an idx'ter Stelle gefunden wurde. // wird ein Index angegeben, der nicht der Tokenanzahl // entspricht, so wird eine Exception ausgelöst. const TData& operator[](unsigned int idx) const { try { return m_tokens.at(idx); } catch(std::out_of_range&) { throw TokenNotFound(); } } //--------------------------------------------------------------------------- TData& operator[](unsigned idx) { try { return m_tokens.at(idx); } catch(std::out_of_range&) { throw TokenNotFound(); } } //--------------------------------------------------------------------------- int IndexOf(const TData &str) const { storage_type::const_iterator item, b = m_tokens.begin(), e = m_tokens.end(); item = std::find(b, e, str); return (item == e) ? -1 : item-b; } private: StringTokens(const StringTokens &a_Tokens); StringTokens &operator=(const StringTokens &a_Tokens); string_type m_delimiter; storage_type m_tokens; }; } // end of namespace #endif muparserx-4.0.11/parser/utGeneric.h000066400000000000000000000045161414723276500172360ustar00rootroot00000000000000#ifndef _UT_GENERIC_H #define _UT_GENERIC_H /* __________ ____ ___ _____ __ _\______ \_____ _______ ______ __________\ \/ / / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ / | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \ \/ \/ \/ \/ \_/ Copyright (C) 2016, Ingo Berg All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ namespace utils { template 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; // Disable CC and assignment operator scoped_setter(const scoped_setter &ref); scoped_setter& operator=(const scoped_setter &ref); }; } #endif muparserx-4.0.11/sample/000077500000000000000000000000001414723276500151175ustar00rootroot00000000000000muparserx-4.0.11/sample/example.cpp000066400000000000000000000705561414723276500172730ustar00rootroot00000000000000/** \example example.cpp This is example code showing you how to use muparserx.
			   __________                                 ____  ___
	_____  __ _\______   \_____ _______  ______ __________\   \/  /
   /     \|  |  \     ___/\__  \\_  __ \/  ___// __ \_  __ \     /
  |  Y Y  \  |  /    |     / __ \|  | \/\___ \\  ___/|  | \/     \
  |__|_|  /____/|____|    (____  /__|  /____  >\___  >__| /___/\  \
		\/                     \/           \/     \/           \_/
  Copyright (C) 2021 Ingo Berg, et al.
  All rights reserved.

  Redistribution and use in source and binary forms, with or without
  modification, are permitted provided that the following conditions are met:

   * Redistributions of source code must retain the above copyright notice,
	 this list of conditions and the following disclaimer.
   * Redistributions in binary form must reproduce the above copyright notice,
	 this list of conditions and the following disclaimer in the documentation
	 and/or other materials provided with the distribution.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  POSSIBILITY OF SUCH DAMAGE.
*/ //--------------------------------------------------------------------------- // // muparserx // // example.cpp - Demonstrates how to use muparserx // //--------------------------------------------------------------------------- /** \brief This macro will enable mathematical constants like M_PI. */ #define _USE_MATH_DEFINES /** \brief Needed to ensure successfull compilation on Unicode systems with MinGW. */ #undef __STRICT_ANSI__ //--- Standard include ------------------------------------------------------ #if defined(_WIN32) // Memory leak dumping #if defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define CREATE_LEAKAGE_REPORT #endif // Needed for windows console UTF-8 support #include #include #endif #include #include #include #include #include #include #include #include #include //--- 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*/) { console() << a_pArg[0].Get()->ToString() << _T("\n"); *ret = (float_type)0.0; } virtual const char_type* GetDesc() const { return _T(""); } virtual IToken* Clone() const { return new FunPrint(*this); } }; // 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*/) { *ret = (float_type)0.0; } virtual const char_type* GetDesc() const { return _T(""); } virtual IToken* Clone() const { return new FunTest0(*this); } }; // 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 = (float_type)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(*this); } }; // 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 = (float_type)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(*this); } }; // 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(nullptr); #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(); double eval_per_sec = (double)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, (double)val.GetFloat(), diff, eval_per_sec, sExpr[i]); printf("Eqn_%d, %d, %lf, %lf, %lf, %s\n", i, iCount, (double)val.GetFloat(), diff, eval_per_sec, sExpr[i]); #else fwprintf(pFile, _T("Eqn_%d, %d, %lf, %lf, %lf, %s\n"), i, iCount, (double)val.GetFloat(), diff, eval_per_sec, sExpr[i]); wprintf(_T("Eqn_%d, %d, %lf, %lf, %lf, %s\n"), i, iCount, (double)val.GetFloat(), diff, eval_per_sec, sExpr[i]); #endif } avg_eval_per_sec /= (double)ct; fprintf(pFile, "# Eval per s: %ld", (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(*this); } }; // 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 = (float_type)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(*this); } }; // 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(*this); } }; // 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 = (float_type)0.0; } virtual const char_type* GetDesc() const { return _T("test() - Runs the unit test of muparserx."); } virtual IToken* Clone() const { return new FunSelfTest(*this); } }; // class FunSelfTest //------------------------------------------------------------------------------------------------- class FunEnableDebugDump : public ICallback { public: FunEnableDebugDump() : ICallback(cmFUNC, _T("debug"), 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()); if (a_pArg[0]->GetBool()) { console() << _T("Bytecode output activated.\n"); } else { console() << _T("Bytecode output deactivated.\n"); } if (a_pArg[1]->GetBool()) { console() << _T("Stack output activated.\n"); } else { console() << _T("Stack output deactivated.\n"); } *ret = (float_type)0.0; } virtual const char_type* GetDesc() const { return _T("debug(bDumpRPN, bDumpStack) - Enable dumping of RPN and stack content."); } virtual IToken* Clone() const { return new FunEnableDebugDump(*this); } }; // class FunEnableDebugDump #if defined(_UNICODE) //------------------------------------------------------------------------------------------------- class FunLang : public ICallback { public: FunLang() : ICallback(cmFUNC, _T("lang"), 1) {} virtual void Eval(ptr_val_type& ret, const ptr_val_type* a_pArg, int /*a_iArgc*/) { string_type sID = a_pArg[0]->GetString(); if (sID == _T("de")) { ParserX::ResetErrorMessageProvider(new mup::ParserMessageProviderGerman); } else if (sID == _T("en")) { ParserX::ResetErrorMessageProvider(new mup::ParserMessageProviderEnglish); } else { console() << _T("Invalid language ID\n"); } *ret = (float_type)0.0; } virtual const char_type* GetDesc() const { return _T("lang(sLang) - Set the language of error messages (i.e. \"de\" or \"en\")."); } virtual IToken* Clone() const { return new FunLang(*this); } }; // class FunLang #endif // #if defined(_UNICODE) /* //------------------------------------------------------------------------------------------------- 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(*this); } }; // class FunDefine */ //--------------------------------------------------------------------------- void Splash() { console() << _T("-------------------------------------------------------------------------\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) 2021 Ingo Berg, et al."); console() << _T("\n\n"); console() << _T("-------------------------------------------------------------------------\n\n"); console() << _T("Build configuration:\n\n"); #if defined(_DEBUG) console() << _T("- DEBUG build\n"); #else console() << _T("- RELEASE build\n"); #endif #if defined(_UNICODE) console() << _T("- UNICODE build\n"); #else console() << _T("- ASCII build\n"); #endif #if defined (__GNUC__) console() << _T("- compiled with GCC Version ") << __GNUC__ << "." << __GNUC_MINOR__ << "." << __GNUC_PATCHLEVEL__ << _T("\n"); #elif defined(_MSC_VER) console() << _T("- compiled with MSC Version ") << _MSC_VER << _T("\n"); #endif console() << _T("- IEEE 754 (IEC 559) is ") << ((std::numeric_limits::is_iec559) ? _T("available") : _T(" NOT AVAILABLE")) << _T("\n"); console() << _T("- ") << sizeof(void*) * 8 << _T(" bit\n"); console() << _T("- Floating point type is \"") << typeid(float_type).name() << _T("\" (") << std::numeric_limits::digits10 << _T(" Digits)") << _T("\n"); console() << _T("\n"); } //--------------------------------------------------------------------------- void SelfTest() { 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.0; m1.At(1, 1) = 1.0; m1.At(2, 2) = 1.0; Value m2(3, 3, 0); m2.At(0, 0) = 1.0; m2.At(0, 1) = 2.0; m2.At(0, 2) = 3.0; m2.At(1, 0) = 4.0; m2.At(1, 1) = 5.0; m2.At(1, 2) = 6.0; m2.At(2, 0) = 7.0; m2.At(2, 1) = 8.0; m2.At(2, 2) = 9.0; Value val[5]; val[0] = (float_type)1.1; val[1] = 1.0; val[2] = false; val[3] = _T("Hello"); val[4] = _T("World"); Value fVal[3]; fVal[0] = (int_type)1; fVal[1] = (float_type)2.22; fVal[2] = (float_type)3.33; 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("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); #if defined(_UNICODE) parser.DefineFun(new FunLang); #endif parser.EnableAutoCreateVar(true); #ifdef _DEBUG // ParserXBase::EnableDebugDump(1, 0); #endif Value x = 1.0; Value y = std::complex(0, 1); parser.DefineVar(_T("x"), Variable(&x)); parser.DefineVar(_T("y"), Variable(&y)); for (;;) { try { console() << sPrompt; string_type sLine; std::getline(mup::console_in(), sLine); if (sLine == _T("dbg")) { sLine = _T("{?{{{{:44"); 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(); { // Value supports C++ streaming like this: console() << _T("Result (type: '") << ans.GetType() << _T("'):\n"); console() << _T("ans = ") << ans << _T("\n"); /* // Or if you need the specific type use this: switch (ans.GetType()) { case 's': { std::string s = ans.GetString(); console() << s << " (string)" << "\n"; } break; case 'i': { int_type i = ans.GetInteger(); console() << i << " (int)" << "\n"; } break; case 'f': { float_type f = ans.GetFloat(); console() << f << " (float)" << "\n"; } break; case 'c': { std::complex c = ans.GetComplex(); console() << c << " (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: ") << std::dec << 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*/) { Splash(); SelfTest(); #if defined(_UNICODE) #if _MSC_VER // Set console to utf-8 mode, if this is not done language specific // characters will be rendered incorrectly if (_setmode(_fileno(stdout), _O_U8TEXT) == -1) throw std::runtime_error("Can't set \"stdout\" to UTF-8"); #endif //// Internationalization requires UNICODE as translations do contain non ASCII //// Characters. //ParserX::ResetErrorMessageProvider(new mup::ParserMessageProviderGerman); #endif 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; } muparserx-4.0.11/sample/timer.cpp000066400000000000000000000020041414723276500167370ustar00rootroot00000000000000#include "timer.h" #include #include #if defined(__WIN32__) || defined(_WIN32) #include DWORD tvs, tve; #else #include 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 } muparserx-4.0.11/sample/timer.h000066400000000000000000000001621414723276500164070ustar00rootroot00000000000000 #ifndef timer_H #define timer_H void StartTimer(void); double StopTimer(void); double PrintTimer(void); #endif