3 _____ __ _____________ _______ ______ ___________
4 / \| | \____ \__ \\_ __ \/ ___// __ \_ __ \
5 | Y Y \ | / |_> > __ \| | \/\___ \\ ___/| | \/
6 |__|_| /____/| __(____ /__| /____ >\___ >__|
8 Copyright (C) 2004 - 2020 Ingo Berg
10 Redistribution and use in source and binary forms, with or without modification, are permitted
11 provided that the following conditions are met:
13 * Redistributions of source code must retain the above copyright notice, this list of
14 conditions and the following disclaimer.
15 * Redistributions in binary form must reproduce the above copyright notice, this list of
16 conditions and the following disclaimer in the documentation and/or other materials provided
17 with the distribution.
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
20 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
21 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
22 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25 IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
26 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 #include "muParserDLL.h"
38 #define PARSER_CONST_PI 3.141592653589793238462643
39 #define PARSER_CONST_E 2.718281828459045235360287
40 #define PARSER_MAXVARS 10
44 #define myprintf printf
45 #define mystrlen strlen
47 #define mystrcmp strcmp
50 #define myprintf wprintf
51 #define mystrlen wcslen
52 #define myfgets fgetws
53 #define mystrcmp wcscmp
56 static void CalcBulk(void);
58 //---------------------------------------------------------------------------
59 // Callbacks for postfix operators
60 static muFloat_t Mega(muFloat_t a_fVal)
62 return a_fVal * 1.0e6;
65 static muFloat_t Milli(muFloat_t a_fVal)
67 return a_fVal / 1.0e3;
70 static muFloat_t ZeroArg(void)
72 myprintf(_T("i'm a function without arguments.\n"));
76 static muFloat_t BulkTest(int nBulkIdx, int nThreadIdx, muFloat_t v1)
78 myprintf(_T("%d,%2.2f\n"), nBulkIdx, v1);
79 return v1 / ((muFloat_t)nBulkIdx + 1);
82 //---------------------------------------------------------------------------
83 // Callbacks for infix operators
84 static muFloat_t Not(muFloat_t v) { return v == 0; }
86 //---------------------------------------------------------------------------
88 static muFloat_t Rnd(muFloat_t v) { return v * rand() / (muFloat_t)(RAND_MAX + 1.0); }
90 static muFloat_t Sum(const muFloat_t* a_afArg, int a_iArgc)
95 for (i = 0; i < a_iArgc; ++i)
101 //---------------------------------------------------------------------------
102 // Binarty operator callbacks
103 static muFloat_t Add(muFloat_t v1, muFloat_t v2)
108 static muFloat_t Mul(muFloat_t v1, muFloat_t v2)
113 //---------------------------------------------------------------------------
114 // Factory function for creating new parser variables
115 // This could as well be a function performing database queries.
116 static muFloat_t* AddVariable(const muChar_t* a_szName, void* pUserData)
118 static muFloat_t afValBuf[PARSER_MAXVARS]; // I don't want dynamic allocation here
119 static int iVal = 0; // so i used this buffer
121 myprintf(_T("Generating new variable \"%s\" (slots left: %d; context pointer: %") _T(PRIxPTR) _T(")\n"), a_szName, PARSER_MAXVARS - iVal, (intptr_t)pUserData);
124 if (iVal >= PARSER_MAXVARS - 1)
126 myprintf(_T("Variable buffer overflow."));
130 return &afValBuf[iVal++];
133 //---------------------------------------------------------------------------
134 static void Intro(muParserHandle_t hParser)
136 myprintf(_T(" __________ \n"));
137 myprintf(_T(" _____ __ __\\______ \\_____ _______ ______ ____ _______\n"));
138 myprintf(_T(" / \\ | | \\| ___/\\__ \\ \\_ __ \\/ ___/_/ __ \\\\_ __ \\ \n"));
139 myprintf(_T(" | Y Y \\| | /| | / __ \\_| | \\/\\___ \\ \\ ___/ | | \\/ \n"));
140 myprintf(_T(" |__|_| /|____/ |____| (____ /|__| /____ > \\___ >|__| \n"));
141 myprintf(_T(" \\/ \\/ \\/ \\/ \n"));
142 myprintf(_T(" Version %s (DLL)\n"), mupGetVersion(hParser));
144 myprintf(_T(" Sample build with UNICODE support\n"));
146 myprintf(_T(" Sample build with ASCII support\n"));
148 myprintf(_T(" (C) 2004 - 2020 Ingo Berg\n"));
149 myprintf(_T("---------------------------------------\n"));
150 myprintf(_T("Commands:\n"));
151 myprintf(_T(" list var - list parser variables\n"));
152 myprintf(_T(" list exprvar - list expression variables\n"));
153 myprintf(_T(" list const - list all numeric parser constants\n"));
154 myprintf(_T(" locale de - switch to german locale\n"));
155 myprintf(_T(" locale en - switch to english locale\n"));
156 myprintf(_T(" locale reset - reset locale\n"));
157 myprintf(_T(" test bulk - test bulk mode\n"));
158 myprintf(_T(" quit - exits the parser\n\n"));
159 myprintf(_T("---------------------------------------\n"));
160 myprintf(_T("Constants:\n"));
161 myprintf(_T(" \"_e\" 2.718281828459045235360287\n"));
162 myprintf(_T(" \"_pi\" 3.141592653589793238462643\n"));
163 myprintf(_T("---------------------------------------\n"));
164 myprintf(_T("Please enter an expression:\n"));
167 //---------------------------------------------------------------------------
168 // Callback function for parser errors
169 static void OnError(muParserHandle_t hParser)
171 myprintf(_T("\nError:\n"));
172 myprintf(_T("------\n"));
173 myprintf(_T("Message: \"%s\"\n"), mupGetErrorMsg(hParser));
174 myprintf(_T("Token: \"%s\"\n"), mupGetErrorToken(hParser));
175 myprintf(_T("Position: %d\n"), mupGetErrorPos(hParser));
176 myprintf(_T("Errc: %d\n"), mupGetErrorCode(hParser));
179 //---------------------------------------------------------------------------
180 static void ListVar(muParserHandle_t a_hParser)
182 int iNumVar = mupGetVarNum(a_hParser);
187 myprintf(_T("No variables defined\n"));
191 myprintf(_T("\nExpression variables:\n"));
192 myprintf(_T("---------------------\n"));
193 myprintf(_T("Number: %d\n"), iNumVar);
195 for (i = 0; i < iNumVar; ++i)
197 const muChar_t* szName = 0;
200 mupGetVar(a_hParser, i, &szName, &pVar);
201 myprintf(_T("Name: %s Address: [%") _T(PRIxPTR) _T("]\n"), szName, (uintptr_t)pVar);
205 //---------------------------------------------------------------------------
206 static void ListExprVar(muParserHandle_t a_hParser)
208 muInt_t iNumVar = mupGetExprVarNum(a_hParser),
213 myprintf(_T("Expression dos not contain variables\n"));
217 myprintf(_T("\nExpression variables:\n"));
218 myprintf(_T("---------------------\n"));
219 myprintf(_T("Expression: %s\n"), mupGetExpr(a_hParser));
220 myprintf(_T("Number: %d\n"), iNumVar);
222 for (i = 0; i < iNumVar; ++i)
224 const muChar_t* szName = 0;
227 mupGetExprVar(a_hParser, i, &szName, &pVar);
228 myprintf(_T("Name: %s Address: [%") _T(PRIxPTR) _T("]\n"), szName, (intptr_t)pVar);
232 //---------------------------------------------------------------------------
233 static void ListConst(muParserHandle_t a_hParser)
235 muInt_t iNumVar = mupGetConstNum(a_hParser),
240 myprintf(_T("No constants defined\n"));
244 myprintf(_T("\nParser constants:\n"));
245 myprintf(_T("---------------------\n"));
246 myprintf(_T("Number: %d"), iNumVar);
248 for (i = 0; i < iNumVar; ++i)
250 const muChar_t* szName = 0;
253 mupGetConst(a_hParser, i, &szName, &fVal);
254 myprintf(_T(" %s = %f\n"), szName, fVal);
258 //---------------------------------------------------------------------------
259 /** \brief Check for external keywords.
261 static int CheckKeywords(const muChar_t* a_szLine, muParserHandle_t a_hParser)
263 if (!mystrcmp(a_szLine, _T("quit")))
267 else if (!mystrcmp(a_szLine, _T("list var")))
272 else if (!mystrcmp(a_szLine, _T("list exprvar")))
274 ListExprVar(a_hParser);
277 else if (!mystrcmp(a_szLine, _T("list const")))
279 ListConst(a_hParser);
282 else if (!mystrcmp(a_szLine, _T("locale de")))
284 myprintf(_T("Setting german locale: ArgSep=';' DecSep=',' ThousandsSep='.'\n"));
285 mupSetArgSep(a_hParser, ';');
286 mupSetDecSep(a_hParser, ',');
287 mupSetThousandsSep(a_hParser, '.');
290 else if (!mystrcmp(a_szLine, _T("locale en")))
292 myprintf(_T("Setting english locale: ArgSep=',' DecSep='.' ThousandsSep=''\n"));
293 mupSetArgSep(a_hParser, ',');
294 mupSetDecSep(a_hParser, '.');
295 mupSetThousandsSep(a_hParser, 0);
298 else if (!mystrcmp(a_szLine, _T("locale reset")))
300 myprintf(_T("Resetting locale\n"));
301 mupResetLocale(a_hParser);
304 else if (!mystrcmp(a_szLine, _T("test bulk")))
306 myprintf(_T("Testing bulk mode\n"));
314 //---------------------------------------------------------------------------
315 static void CalcBulk(void)
317 int nBulkSize = 200, i;
318 muFloat_t* x = (muFloat_t*)malloc(nBulkSize * sizeof(muFloat_t));
319 muFloat_t* y = (muFloat_t*)malloc(nBulkSize * sizeof(muFloat_t));
320 muFloat_t* r = (muFloat_t*)malloc(nBulkSize * sizeof(muFloat_t));
322 muParserHandle_t hParser = mupCreate(muBASETYPE_FLOAT); // initialize the parser
324 for (i = 0; i < nBulkSize; ++i)
331 mupDefineVar(hParser, _T("x"), x);
332 mupDefineVar(hParser, _T("y"), y);
333 mupDefineBulkFun1(hParser, _T("bulktest"), BulkTest);
334 mupSetExpr(hParser, _T("bulktest(x+y)"));
335 mupEvalBulk(hParser, r, nBulkSize);
336 if (mupError(hParser))
338 myprintf(_T("\nError:\n"));
339 myprintf(_T("------\n"));
340 myprintf(_T("Message: %s\n"), mupGetErrorMsg(hParser));
341 myprintf(_T("Token: %s\n"), mupGetErrorToken(hParser));
342 myprintf(_T("Position: %d\n"), mupGetErrorPos(hParser));
343 myprintf(_T("Errc: %d\n"), mupGetErrorCode(hParser));
347 for (i = 0; i < nBulkSize; ++i)
349 myprintf(_T("%d: bulkfun(%2.2f + %2.2f) = %2.2f\n"), i, x[i], y[i], r[i]);
351 y[i] = (muFloat_t)i / 10;
359 //---------------------------------------------------------------------------
360 static void Calc(void)
362 muChar_t szLine[100];
364 afVarVal[] = { 1, 2 }; // Values of the parser variables
365 muParserHandle_t hParser;
367 hParser = mupCreate(muBASETYPE_FLOAT); // initialize the parser
370 // Set an error handler [optional]
371 // the only function that does not take a parser instance handle
372 mupSetErrorHandler(hParser, OnError);
374 //#define GERMAN_LOCALS
376 mupSetArgSep(hParser, ';');
377 mupSetDecSep(hParser, ',');
378 mupSetThousandsSep(hParser, '.');
380 mupSetArgSep(hParser, ',');
381 mupSetDecSep(hParser, '.');
384 // Set a variable factory
385 mupSetVarFactory(hParser, AddVariable, NULL);
387 // Define parser variables and bind them to C++ variables [optional]
388 mupDefineConst(hParser, _T("const1"), 1);
389 mupDefineConst(hParser, _T("const2"), 2);
390 mupDefineStrConst(hParser, _T("strBuf"), _T("Hallo welt"));
392 // Define parser variables and bind them to C++ variables [optional]
393 mupDefineVar(hParser, _T("a"), &afVarVal[0]);
394 mupDefineVar(hParser, _T("b"), &afVarVal[1]);
396 // Define postfix operators [optional]
397 mupDefinePostfixOprt(hParser, _T("M"), Mega, 0);
398 mupDefinePostfixOprt(hParser, _T("m"), Milli, 0);
400 // Define infix operator [optional]
401 mupDefineInfixOprt(hParser, _T("!"), Not, 0);
403 // Define functions [optional]
404 // mupDefineStrFun(hParser, "query", SampleQuery, 0); // Add an unoptimizeable function
405 mupDefineFun0(hParser, _T("zero"), ZeroArg, 0);
406 mupDefineFun1(hParser, _T("rnd"), Rnd, 0); // Add an unoptimizeable function
407 mupDefineFun1(hParser, _T("rnd2"), Rnd, 1);
408 mupDefineMultFun(hParser, _T("_sum"), Sum, 0); // "sum" is already a default function
410 // Define binary operators [optional]
411 mupDefineOprt(hParser, _T("add"), Add, 0, muOPRT_ASCT_LEFT, 0);
412 mupDefineOprt(hParser, _T("mul"), Mul, 1, muOPRT_ASCT_LEFT, 0);
414 while (myfgets(szLine, 99, stdin))
416 szLine[mystrlen(szLine) - 1] = 0; // overwrite the newline
418 switch (CheckKeywords(szLine, hParser))
420 case 0: break; // no keyword found; parse the line
421 case 1: continue; // A Keyword was found do not parse the line
422 case -1: return; // abort the application
425 mupSetExpr(hParser, szLine);
427 fVal = mupEval(hParser);
430 // Without an Error handler function
431 // you must use this for error treatment:
432 //if (mupError(hParser))
434 // printf("\nError:\n");
435 // printf("------\n");
436 // printf("Message: %s\n", mupGetErrorMsg(hParser) );
437 // printf("Token: %s\n", mupGetErrorToken(hParser) );
438 // printf("Position: %s\n", mupGetErrorPos(hParser) );
439 // printf("Errc: %d\n", mupGetErrorCode(hParser) );
443 if (!mupError(hParser))
444 myprintf(_T("%f\n"), fVal);
448 // finally free the parser resources
452 //---------------------------------------------------------------------------
453 int main(int argc, char* argv[])
455 // The next line is just for shutting up the compiler warning
456 // about unused variables without getting another warning about not
457 // being able to use type lists in function declarations.
458 myprintf(_T("Executing \"%s\" (argc=%d)\n"), argv[0], argc);
460 printf(_T("done..."));