From 9d7c8b7b9e1f27238fd9fef3d18d3f8a4870ed0a Mon Sep 17 00:00:00 2001 From: Pedro Pontes Date: Thu, 7 Dec 2023 09:43:37 -0300 Subject: [PATCH] Add files from equations parser --- core/src/main/cpp/parser/equationsParser.cpp | 140 +++++++++++++++++++ core/src/main/cpp/parser/equationsParser.h | 21 +++ core/src/main/cpp/parser/mpFuncCommon.cpp | 129 +++++++++++++++++ core/src/main/cpp/parser/mpFuncCommon.h | 26 ++++ core/src/main/cpp/parser/mpFuncStr.cpp | 135 +++++++++++------- core/src/main/cpp/parser/mpFuncStr.h | 15 +- core/src/main/cpp/parser/mpPackageCommon.cpp | 4 + core/src/main/cpp/parser/mpPackageStr.cpp | 31 ++-- core/src/main/cpp/parser/mpValue.cpp | 2 + 9 files changed, 436 insertions(+), 67 deletions(-) create mode 100644 core/src/main/cpp/parser/equationsParser.cpp create mode 100644 core/src/main/cpp/parser/equationsParser.h diff --git a/core/src/main/cpp/parser/equationsParser.cpp b/core/src/main/cpp/parser/equationsParser.cpp new file mode 100644 index 0000000..a053cc2 --- /dev/null +++ b/core/src/main/cpp/parser/equationsParser.cpp @@ -0,0 +1,140 @@ +#include "equationsParser.h" + +#include +#include +#include +#include + +using namespace std; +using namespace mup; + +EQUATIONS_PARSER_START + +/** + * @brief Evaluates an input string as a mathematical expression and returns the result + * @param input The string to be evaluated as a mathematical expression + */ +string Calc(string input) { + ParserX parser(pckALL_NON_COMPLEX); + + Value ans; + parser.DefineVar(_T("ans"), Variable(&ans)); + + try + { + parser.SetExpr(input); + ans = parser.Eval(); + + return ans.AsString(); + } + catch(ParserError &e) + { + if (e.GetPos() != -1) { + string_type error = "Error: "; + error.append(e.GetMsg()); + return error; + } + } + catch(std::runtime_error & ex) + { + string_type error = "Error: Runtime error - "; + error.append(ex.what()); + return error; + } + return ans.AsString(); +} + +/** + * @brief Replaces all occurrences of the substring @from in the source string with another the + * substring @to + * @param source A reference to the string to perform the replacement on + * @param from The substring to be replaced + * @param to The substring that will replace 'from' + */ +void ReplaceAll(std::string& source, const std::string& from, const std::string& to) { + std::string newString; + newString.reserve(source.length()); // avoids a few memory allocations + + std::string::size_type lastPos = 0; + std::string::size_type findPos; + + while(std::string::npos != (findPos = source.find(from, lastPos))) + { + newString.append(source, lastPos, findPos - lastPos); + newString += to; + lastPos = findPos + from.length(); + } + + // Care for the rest after last occurrence + newString += source.substr(lastPos); + + source.swap(newString); +} + +/** + * @brief Evaluates an input string as a mathematical expression and returns the result as a JSON + * @param input The string to be evaluated as a mathematical expression + * @return The result of the evaluation as a JSON string in the following format: + * { + * "val": "result_value", + * "type": "result_type" + * } + * or in case of error: + * { + * "error": "error_message" + * } + */ +string CalcJson(string input) { + ParserX parser(pckALL_NON_COMPLEX); + + Value ans; + parser.DefineVar(_T("ans"), Variable(&ans)); + + stringstream_type ss; + + ss << _T("{"); + + try + { + parser.SetExpr(input); + ans = parser.Eval(); + + std::string ansString = ans.AsString(); + + ReplaceAll(ansString, "\"", "\\\""); + + ss << _T("\"val\": \"") << ansString << _T("\""); + ss << _T(",\"type\": \"") << ans.GetType() << _T("\""); + } + catch(ParserError &e) + { + if (e.GetPos() != -1) { + string_type error = e.GetMsg(); + ss << _T("\"error\": \"") << error << _T("\""); + } + } + catch(std::runtime_error & ex) + { + string_type error = "Error: Runtime error - "; + error.append(ex.what()); + ss << _T("\"error\": \"") << error << _T("\""); + } + + ss << _T("}"); + + return ss.str(); +} + +/** + * Calculates the result of a list of equations and stores them in the 'out' vector. + * + * @param equations a vector of strings representing mathematical equations + * @param out a vector of strings where the results of the calculations will be stored + */ +void CalcArray(vector equations, vector &out) { + for(string equation : equations) { + out.push_back(CalcJson(equation)); + } +} + +EQUATIONS_PARSER_END diff --git a/core/src/main/cpp/parser/equationsParser.h b/core/src/main/cpp/parser/equationsParser.h new file mode 100644 index 0000000..7ea6317 --- /dev/null +++ b/core/src/main/cpp/parser/equationsParser.h @@ -0,0 +1,21 @@ +#ifndef EQUATIONS_PARSER_H +#define EQUATIONS_PARSER_H + +#include +//--- Parser framework ----------------------------------------------------- +#include "mpParser.h" +#include "mpDefines.h" + +#define EQUATIONS_PARSER_START namespace EquationsParser { +#define EQUATIONS_PARSER_END } + +EQUATIONS_PARSER_START + +void ReplaceAll(std::string& source, const std::string& from, const std::string& to); +std::string Calc(std::string input); +std::string CalcJson(std::string input); +void CalcArray(std::vector in, std::vector &out); + +EQUATIONS_PARSER_END + +#endif diff --git a/core/src/main/cpp/parser/mpFuncCommon.cpp b/core/src/main/cpp/parser/mpFuncCommon.cpp index ce41c63..685d82e 100755 --- a/core/src/main/cpp/parser/mpFuncCommon.cpp +++ b/core/src/main/cpp/parser/mpFuncCommon.cpp @@ -828,4 +828,133 @@ MUP_NAMESPACE_START return new FunTimeDiff(*this); } + //------------------------------------------------------------------------------ + // | + // Functions for regex matching | + // Usage: regex("string", "regex") | + // | + //------------------------------------------------------------------------------ + + FunRegex::FunRegex() + :ICallback(cmFUNC, _T("regex"), -1) + {} + + std::vector> capture_regex_groups(const std::string& input, const std::string& pattern) { + std::vector> captured_groups; + std::smatch match; + std::regex re(pattern); + std::string::const_iterator search_start(input.cbegin()); + + while (std::regex_search(search_start, input.cend(), match, re)) { + std::vector groups; + for (size_t i = 1; i < match.size(); ++i) { + groups.push_back(match[i].str()); + } + captured_groups.push_back(groups); + search_start = match.suffix().first; + } + + return captured_groups; + } + + void FunRegex::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc) + { + if (a_iArgc < 2) { + throw ParserError(ErrorContext(ecTOO_FEW_PARAMS, GetExprPos(), GetIdent())); + } else if (a_iArgc > 2) { + throw ParserError(ErrorContext(ecTOO_MANY_PARAMS, GetExprPos(), GetIdent())); + } + + string_type input = a_pArg[0]->GetString(); + string_type pattern = a_pArg[1]->GetString(); + + auto captured_groups = capture_regex_groups(input, pattern); + + if (captured_groups.size() == 0 || captured_groups[0].size() == 0) { + *ret = (string_type) ""; + } else { + *ret = (string_type) captured_groups[0][0]; + } + } + + ////------------------------------------------------------------------------------ + const char_type* FunRegex::GetDesc() const + { + return _T("regex(a,b) - Returns the first match of a regex pattern."); + } + + ////------------------------------------------------------------------------------ + IToken* FunRegex::Clone() const + { + return new FunRegex(*this); + } + + //------------------------------------------------------------------------------ + // | + // Function return the week of year of a date | + // Usage: weekyear("2022-04-20") | + // | + //------------------------------------------------------------------------------ + + FunWeekYear::FunWeekYear() + :ICallback(cmFUNC, _T("weekyear"), -1) + {} + + void FunWeekYear::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())); + } else if (a_iArgc > 1) { + throw ParserError(ErrorContext(ecTOO_MANY_PARAMS, GetExprPos(), GetIdent())); + } + + string_type date_time = a_pArg[0]->GetString(); + + struct tm date; + if (!strptime(date_time.c_str(), "%Y-%m-%d", &date)) { + raise_error(ecINVALID_DATE_FORMAT, 1, a_pArg); + } + + int year = date.tm_year + 1900; // tm_year is the number of years since 1900 + + // Get ordinal day of the year + int day_of_year = date.tm_yday + 1; // tm_yday is the number of days since January 1st + + // Get weekday number (0 is Sunday) + int weekday = date.tm_wday; + + // Calculate week number + int week_number = (day_of_year - weekday + 10) / 7; + + // Check if week belongs to previous year + if (week_number == 0) { + year--; + week_number = 52; + if (std::tm{0,0,0,1,0,year-1900}.tm_wday < 4) { // January 1st of the previous year is before Thursday + week_number = 53; + } + } + + // Check if week belongs to following year + if (week_number == 53) { + if (std::tm{0,0,0,1,0,year+1-1900}.tm_wday >= 4) { // January 1st of the following year is on or after Thursday + week_number = 1; + } + } + + *ret = week_number; + } + + ////------------------------------------------------------------------------------ + const char_type* FunWeekYear::GetDesc() const + { + return _T("weekyear(date) - Returns the week number of the year."); + } + + ////------------------------------------------------------------------------------ + IToken* FunWeekYear::Clone() const + { + return new FunWeekYear(*this); + } + MUP_NAMESPACE_END diff --git a/core/src/main/cpp/parser/mpFuncCommon.h b/core/src/main/cpp/parser/mpFuncCommon.h index adbd1bd..f208181 100755 --- a/core/src/main/cpp/parser/mpFuncCommon.h +++ b/core/src/main/cpp/parser/mpFuncCommon.h @@ -198,6 +198,32 @@ MUP_NAMESPACE_START virtual IToken* Clone() const override; }; // class FunTimeDiff + //------------------------------------------------------------------------------ + /** \brief Return the capture group of a regular expression. + \ingroup functions + */ + class FunRegex : public ICallback + { + public: + FunRegex(); + 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 FunRegex + + //------------------------------------------------------------------------------ + /** \brief Return the week of year of a date. + \ingroup functions + */ + class FunWeekYear: public ICallback + { + public: + FunWeekYear(); + 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 FunWeekYear + MUP_NAMESPACE_END #endif diff --git a/core/src/main/cpp/parser/mpFuncStr.cpp b/core/src/main/cpp/parser/mpFuncStr.cpp index d18b17b..59e587f 100755 --- a/core/src/main/cpp/parser/mpFuncStr.cpp +++ b/core/src/main/cpp/parser/mpFuncStr.cpp @@ -1,31 +1,31 @@ /* __________ ____ ___ _____ __ _\______ \_____ _______ ______ __________\ \/ / - / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ / - | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \ + / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ / + | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \ \/ \/ \/ \/ \_/ Copyright (C) 2016, Ingo Berg All rights reserved. - Redistribution and use in source and binary forms, with or without + 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, + * 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 + * 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 + 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" @@ -38,41 +38,10 @@ #include "mpValue.h" #include "mpError.h" +#include "equationsParser.h" MUP_NAMESPACE_START - - //------------------------------------------------------------------------------ - // - // Contains function - // - //------------------------------------------------------------------------------ - - FunStrContains::FunStrContains() - :ICallback(cmFUNC, _T("contains"), 2) - {} - - //------------------------------------------------------------------------------ - void FunStrContains::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int) - { - const string_type & str1 = a_pArg[0]->GetString(); - const string_type & str2 = a_pArg[1]->GetString(); - - *ret = str1.find(str2) != string_type::npos ? true : false; - } - - //------------------------------------------------------------------------------ - const char_type* FunStrContains::GetDesc() const - { - return _T("contains(str1, str2) - Returns if the str2 string is a sub string of str1."); - } - - //------------------------------------------------------------------------------ - IToken* FunStrContains::Clone() const - { - return new FunStrContains(*this); - } - //------------------------------------------------------------------------------ // // Concat function @@ -120,6 +89,7 @@ MUP_NAMESPACE_START throw ParserError(ErrorContext(ecTOO_FEW_PARAMS, GetExprPos(), GetIdent())); if (a_iArgc > 3) throw ParserError(ErrorContext(ecTOO_MANY_PARAMS, GetExprPos(), GetIdent())); + string_type str1 = a_pArg[0]->GetString(); string_type str2 = a_pArg[1]->GetString(); string_type opAttr = a_iArgc == 3 ? " download=\"" + a_pArg[2]->GetString() + "\">" : ">"; @@ -296,7 +266,7 @@ MUP_NAMESPACE_START if (a_pArg[0]->GetType() == 'i') { // NULL first parameter integer_value = a_pArg[0]->GetInteger(); *ret = default_value(integer_value, string_standard); - } else if (a_pArg[0]->GetType() == 's'){ // NOT NULL first parameter + } else if (a_pArg[0]->GetType() == 's') { // NOT NULL first parameter string_value = a_pArg[0]->GetString(); *ret = (string_type) default_value(string_value, string_standard); } @@ -434,7 +404,7 @@ MUP_NAMESPACE_START in = a_pArg[0]->GetString(); -#ifndef _UNICODE +#ifndef _UNICODE sscanf(in.c_str(), "%lf", &out); #else swscanf(in.c_str(), _T("%lf"), &out); @@ -482,9 +452,9 @@ MUP_NAMESPACE_START string_value = a_pArg[0]->GetString(); #ifndef _UNICODE - sscanf(string_value.c_str(), "%lf", &out); + sscanf(string_value.c_str(), "%lf", &out); #else - swscanf(string_value.c_str(), _T("%lf"), &out); + swscanf(string_value.c_str(), _T("%lf"), &out); #endif *ret = (float_type) out; @@ -587,4 +557,67 @@ MUP_NAMESPACE_START { return new FunString(*this); } + + //------------------------------------------------------------------------------ + // + // Contains function + // + //------------------------------------------------------------------------------ + + FunStrContains::FunStrContains() + :ICallback(cmFUNC, _T("contains"), 2) + {} + + //------------------------------------------------------------------------------ + void FunStrContains::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int) + { + const string_type & str1 = a_pArg[0]->GetString(); + const string_type & str2 = a_pArg[1]->GetString(); + + *ret = str1.find(str2) != string_type::npos; + } + + //------------------------------------------------------------------------------ + const char_type* FunStrContains::GetDesc() const + { + return _T("contains(str1, str2) - Returns if the str2 string is a sub string of str1."); + } + + //------------------------------------------------------------------------------ + IToken* FunStrContains::Clone() const + { + return new FunStrContains(*this); + } + + //------------------------------------------------------------------------------ + // + // Calculate function + // + //------------------------------------------------------------------------------ + + FunStrCalculate::FunStrCalculate() + :ICallback(cmFUNC, _T("calculate"), 1) + {} + + //------------------------------------------------------------------------------ + void FunStrCalculate::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int) + { + using namespace std; + + string_type equation = a_pArg[0]->GetString(); + + *ret = EquationsParser::Calc(equation); + } + + //------------------------------------------------------------------------------ + const char_type* FunStrCalculate::GetDesc() const + { + return _T("calculate(s) - Calculates an equation (Run equations-parser for the string input)."); + } + + //------------------------------------------------------------------------------ + IToken* FunStrCalculate::Clone() const + { + return new FunStrCalculate(*this); + } MUP_NAMESPACE_END diff --git a/core/src/main/cpp/parser/mpFuncStr.h b/core/src/main/cpp/parser/mpFuncStr.h index f2ef9bd..e11fcf4 100755 --- a/core/src/main/cpp/parser/mpFuncStr.h +++ b/core/src/main/cpp/parser/mpFuncStr.h @@ -179,7 +179,7 @@ MUP_NAMESPACE_START virtual IToken* Clone() const override; }; // class FunStrNumber - //------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ /** \brief Parse number/string to a string value. \ingroup functions */ @@ -191,6 +191,19 @@ MUP_NAMESPACE_START virtual const char_type* GetDesc() const override; virtual IToken* Clone() const override; }; // class FunString + +//------------------------------------------------------------------------------ + /** \brief Calculate equation string + \ingroup functions + */ + class FunStrCalculate : public ICallback + { + public: + FunStrCalculate (); + 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 FunStrCalculate MUP_NAMESPACE_END #endif diff --git a/core/src/main/cpp/parser/mpPackageCommon.cpp b/core/src/main/cpp/parser/mpPackageCommon.cpp index 5357f86..18332e1 100755 --- a/core/src/main/cpp/parser/mpPackageCommon.cpp +++ b/core/src/main/cpp/parser/mpPackageCommon.cpp @@ -99,6 +99,10 @@ void PackageCommon::AddToParser(ParserXBase *pParser) pParser->DefineFun(new FunHoursDiff()); pParser->DefineFun(new FunCurrentDate()); pParser->DefineFun(new FunAddDays()); + pParser->DefineFun(new FunWeekYear()); + + // String functions + pParser->DefineFun(new FunRegex()); // Time functions pParser->DefineFun(new FunTimeDiff()); diff --git a/core/src/main/cpp/parser/mpPackageStr.cpp b/core/src/main/cpp/parser/mpPackageStr.cpp index 2b179ce..14a9f36 100755 --- a/core/src/main/cpp/parser/mpPackageStr.cpp +++ b/core/src/main/cpp/parser/mpPackageStr.cpp @@ -1,31 +1,31 @@ /* __________ ____ ___ _____ __ _\______ \_____ _______ ______ __________\ \/ / - / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ / - | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \ + / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ / + | Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \ |__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \ \/ \/ \/ \/ \_/ Copyright (C) 2016, Ingo Berg All rights reserved. - Redistribution and use in source and binary forms, with or without + 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, + * 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 + * 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 + 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" @@ -69,6 +69,7 @@ void PackageStr::AddToParser(ParserXBase *pParser) pParser->DefineFun(new FunStrDefaultValue()); pParser->DefineFun(new FunString()); pParser->DefineFun(new FunStrContains()); + pParser->DefineFun(new FunStrCalculate()); // Operators pParser->DefineOprt(new OprtStrAdd); diff --git a/core/src/main/cpp/parser/mpValue.cpp b/core/src/main/cpp/parser/mpValue.cpp index fe5f752..1f77c05 100755 --- a/core/src/main/cpp/parser/mpValue.cpp +++ b/core/src/main/cpp/parser/mpValue.cpp @@ -34,6 +34,8 @@ POSSIBILITY OF SUCH DAMAGE. #include "mpError.h" #include "mpValueCache.h" #include +#include + MUP_NAMESPACE_START