1 #include <string.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <wchar.h>
5
6 #include "muParserDLL.h"
7
8 #define PARSER_CONST_PI 3.141592653589793238462643
9 #define PARSER_CONST_E 2.718281828459045235360287
10 #define PARSER_MAXVARS 10
11
12 #ifndef _UNICODE
13 #define _T(x) x
14 #define myprintf printf
15 #define mystrlen strlen
16 #define myfgets fgets
17 #define mystrcmp strcmp
18 #else
19 #define _T(x) L ##x
20 #define myprintf wprintf
21 #define mystrlen wcslen
22 #define myfgets fgetws
23 #define mystrcmp wcscmp
24 #endif
25
26 extern void CalcBulk();
27
28 //---------------------------------------------------------------------------
29 // Callbacks for postfix operators
Mega(muFloat_t a_fVal)30 muFloat_t Mega(muFloat_t a_fVal)
31 {
32 return a_fVal * 1.0e6;
33 }
34
Milli(muFloat_t a_fVal)35 muFloat_t Milli(muFloat_t a_fVal)
36 {
37 return a_fVal / 1.0e3;
38 }
39
ZeroArg()40 muFloat_t ZeroArg()
41 {
42 myprintf(_T("i'm a function without arguments.\n"));
43 return 123;
44 }
45
BulkTest(int nBulkIdx,int nThreadIdx,muFloat_t v1)46 muFloat_t BulkTest(int nBulkIdx, int nThreadIdx, muFloat_t v1)
47 {
48 (void*)&nThreadIdx; // STFU compiler warning...
49 myprintf(_T("%d,%2.2f\n"), nBulkIdx, v1);
50 return v1 / (nBulkIdx + 1);
51 }
52
53 //---------------------------------------------------------------------------
54 // Callbacks for infix operators
Not(muFloat_t v)55 muFloat_t Not(muFloat_t v) { return v == 0; }
56
57 //---------------------------------------------------------------------------
58 // Function callbacks
Rnd(muFloat_t v)59 muFloat_t Rnd(muFloat_t v) { return v * rand() / (muFloat_t)(RAND_MAX + 1.0); }
60
SampleQuery(const muChar_t * szMsg)61 muFloat_t SampleQuery(const muChar_t *szMsg)
62 {
63 if (szMsg)
64 {
65 myprintf(_T("%s\n"), szMsg);
66 }
67
68 return 999;
69 }
70
Sum(const muFloat_t * a_afArg,int a_iArgc)71 muFloat_t Sum(const muFloat_t *a_afArg, int a_iArgc)
72 {
73 muFloat_t fRes = 0;
74 int i = 0;
75
76 for (i = 0; i < a_iArgc; ++i)
77 fRes += a_afArg[i];
78
79 return fRes;
80 }
81
82 //---------------------------------------------------------------------------
83 // Binarty operator callbacks
Add(muFloat_t v1,muFloat_t v2)84 muFloat_t Add(muFloat_t v1, muFloat_t v2)
85 {
86 return v1 + v2;
87 }
88
Mul(muFloat_t v1,muFloat_t v2)89 muFloat_t Mul(muFloat_t v1, muFloat_t v2)
90 {
91 return v1*v2;
92 }
93
94 //---------------------------------------------------------------------------
95 // Factory function for creating new parser variables
96 // This could as well be a function performing database queries.
AddVariable(const muChar_t * a_szName,void * pUserData)97 muFloat_t* AddVariable(const muChar_t* a_szName, void *pUserData)
98 {
99 static muFloat_t afValBuf[PARSER_MAXVARS]; // I don't want dynamic allocation here
100 static int iVal = 0; // so i used this buffer
101
102 myprintf(_T("Generating new variable \"%s\" (slots left: %d; context pointer: 0x%x)\n"), a_szName, PARSER_MAXVARS - iVal, (int)pUserData);
103
104 afValBuf[iVal] = 0;
105 if (iVal >= PARSER_MAXVARS - 1)
106 {
107 myprintf(_T("Variable buffer overflow."));
108 return NULL;
109 }
110
111 return &afValBuf[iVal++];
112 }
113
114 //---------------------------------------------------------------------------
Intro(muParserHandle_t hParser)115 void Intro(muParserHandle_t hParser)
116 {
117 myprintf(_T(" __________ \n"));
118 myprintf(_T(" _____ __ __\\______ \\_____ _______ ______ ____ _______\n"));
119 myprintf(_T(" / \\ | | \\| ___/\\__ \\ \\_ __ \\/ ___/_/ __ \\\\_ __ \\ \n"));
120 myprintf(_T(" | Y Y \\| | /| | / __ \\_| | \\/\\___ \\ \\ ___/ | | \\/ \n"));
121 myprintf(_T(" |__|_| /|____/ |____| (____ /|__| /____ > \\___ >|__| \n"));
122 myprintf(_T(" \\/ \\/ \\/ \\/ \n"));
123 myprintf(_T(" Version %s (DLL)\n"), mupGetVersion(hParser));
124 #ifdef _UNICODE
125 myprintf(_T(" Sample build with UNICODE support\n"));
126 #else
127 myprintf(_T(" Sample build with ASCII support\n"));
128 #endif
129 myprintf(_T(" (C) 2015 Ingo Berg\n"));
130 myprintf(_T("---------------------------------------\n"));
131 myprintf(_T("Commands:\n"));
132 myprintf(_T(" list var - list parser variables\n"));
133 myprintf(_T(" list exprvar - list expression variables\n"));
134 myprintf(_T(" list const - list all numeric parser constants\n"));
135 myprintf(_T(" locale de - switch to german locale\n"));
136 myprintf(_T(" locale en - switch to english locale\n"));
137 myprintf(_T(" locale reset - reset locale\n"));
138 myprintf(_T(" test bulk - test bulk mode\n"));
139 myprintf(_T(" quit - exits the parser\n\n"));
140 myprintf(_T("---------------------------------------\n"));
141 myprintf(_T("Constants:\n"));
142 myprintf(_T(" \"_e\" 2.718281828459045235360287\n"));
143 myprintf(_T(" \"_pi\" 3.141592653589793238462643\n"));
144 myprintf(_T("---------------------------------------\n"));
145 myprintf(_T("Please enter an expression:\n"));
146 }
147
148 //---------------------------------------------------------------------------
149 // Callback function for parser errors
OnError(muParserHandle_t hParser)150 void OnError(muParserHandle_t hParser)
151 {
152 myprintf(_T("\nError:\n"));
153 myprintf(_T("------\n"));
154 myprintf(_T("Message: \"%s\"\n"), mupGetErrorMsg(hParser));
155 myprintf(_T("Token: \"%s\"\n"), mupGetErrorToken(hParser));
156 myprintf(_T("Position: %d\n"), mupGetErrorPos(hParser));
157 myprintf(_T("Errc: %d\n"), mupGetErrorCode(hParser));
158 }
159
160 //---------------------------------------------------------------------------
ListVar(muParserHandle_t a_hParser)161 void ListVar(muParserHandle_t a_hParser)
162 {
163 int iNumVar = mupGetVarNum(a_hParser);
164 int i = 0;
165
166 if (iNumVar == 0)
167 {
168 myprintf(_T("No variables defined\n"));
169 return;
170 }
171
172 myprintf(_T("\nExpression variables:\n"));
173 myprintf(_T("---------------------\n"));
174 myprintf(_T("Number: %d\n"), iNumVar);
175
176 for (i = 0; i < iNumVar; ++i)
177 {
178 const muChar_t* szName = 0;
179 muFloat_t* pVar = 0;
180
181 mupGetVar(a_hParser, i, &szName, &pVar);
182 myprintf(_T("Name: %s Address: [0x%x]\n"), szName, (long long)pVar);
183 }
184 }
185
186 //---------------------------------------------------------------------------
ListExprVar(muParserHandle_t a_hParser)187 void ListExprVar(muParserHandle_t a_hParser)
188 {
189 muInt_t iNumVar = mupGetExprVarNum(a_hParser),
190 i = 0;
191
192 if (iNumVar == 0)
193 {
194 myprintf(_T("Expression dos not contain variables\n"));
195 return;
196 }
197
198 myprintf(_T("\nExpression variables:\n"));
199 myprintf(_T("---------------------\n"));
200 myprintf(_T("Expression: %s\n"), mupGetExpr(a_hParser));
201 myprintf(_T("Number: %d\n"), iNumVar);
202
203 for (i = 0; i < iNumVar; ++i)
204 {
205 const muChar_t* szName = 0;
206 muFloat_t* pVar = 0;
207
208 mupGetExprVar(a_hParser, i, &szName, &pVar);
209 myprintf(_T("Name: %s Address: [0x%x]\n"), szName, (long long)pVar);
210 }
211 }
212
213 //---------------------------------------------------------------------------
ListConst(muParserHandle_t a_hParser)214 void ListConst(muParserHandle_t a_hParser)
215 {
216 muInt_t iNumVar = mupGetConstNum(a_hParser),
217 i = 0;
218
219 if (iNumVar == 0)
220 {
221 myprintf(_T("No constants defined\n"));
222 return;
223 }
224
225 myprintf(_T("\nParser constants:\n"));
226 myprintf(_T("---------------------\n"));
227 myprintf(_T("Number: %d"), iNumVar);
228
229 for (i = 0; i < iNumVar; ++i)
230 {
231 const muChar_t* szName = 0;
232 muFloat_t fVal = 0;
233
234 mupGetConst(a_hParser, i, &szName, &fVal);
235 myprintf(_T(" %s = %f\n"), szName, fVal);
236 }
237 }
238
239 //---------------------------------------------------------------------------
240 /** \brief Check for external keywords.
241 */
CheckKeywords(const muChar_t * a_szLine,muParserHandle_t a_hParser)242 int CheckKeywords(const muChar_t *a_szLine, muParserHandle_t a_hParser)
243 {
244 if (!mystrcmp(a_szLine, _T("quit")))
245 {
246 return -1;
247 }
248 else if (!mystrcmp(a_szLine, _T("list var")))
249 {
250 ListVar(a_hParser);
251 return 1;
252 }
253 else if (!mystrcmp(a_szLine, _T("list exprvar")))
254 {
255 ListExprVar(a_hParser);
256 return 1;
257 }
258 else if (!mystrcmp(a_szLine, _T("list const")))
259 {
260 ListConst(a_hParser);
261 return 1;
262 }
263 else if (!mystrcmp(a_szLine, _T("locale de")))
264 {
265 myprintf(_T("Setting german locale: ArgSep=';' DecSep=',' ThousandsSep='.'\n"));
266 mupSetArgSep(a_hParser, ';');
267 mupSetDecSep(a_hParser, ',');
268 mupSetThousandsSep(a_hParser, '.');
269 return 1;
270 }
271 else if (!mystrcmp(a_szLine, _T("locale en")))
272 {
273 myprintf(_T("Setting english locale: ArgSep=',' DecSep='.' ThousandsSep=''\n"));
274 mupSetArgSep(a_hParser, ',');
275 mupSetDecSep(a_hParser, '.');
276 mupSetThousandsSep(a_hParser, 0);
277 return 1;
278 }
279 else if (!mystrcmp(a_szLine, _T("locale reset")))
280 {
281 myprintf(_T("Resetting locale\n"));
282 mupResetLocale(a_hParser);
283 return 1;
284 }
285 else if (!mystrcmp(a_szLine, _T("test bulk")))
286 {
287 myprintf(_T("Testing bulk mode\n"));
288 CalcBulk();
289 return 1;
290 }
291
292 return 0;
293 }
294
295 //---------------------------------------------------------------------------
CalcBulk()296 void CalcBulk()
297 {
298 int nBulkSize = 200, i;
299 muFloat_t *x = (muFloat_t*)malloc(nBulkSize * sizeof(muFloat_t));
300 muFloat_t *y = (muFloat_t*)malloc(nBulkSize * sizeof(muFloat_t));
301 muFloat_t *r = (muFloat_t*)malloc(nBulkSize * sizeof(muFloat_t));
302
303 muParserHandle_t hParser = mupCreate(muBASETYPE_FLOAT); // initialize the parser
304
305 for (i = 0; i < nBulkSize; ++i)
306 {
307 x[i] = i;
308 y[i] = i;
309 r[i] = 0;
310 }
311
312 mupDefineVar(hParser, _T("x"), x);
313 mupDefineVar(hParser, _T("y"), y);
314 mupDefineBulkFun1(hParser, _T("bulktest"), BulkTest);
315 mupSetExpr(hParser, _T("bulktest(x+y)"));
316 mupEvalBulk(hParser, r, nBulkSize);
317 if (mupError(hParser))
318 {
319 myprintf(_T("\nError:\n"));
320 myprintf(_T("------\n"));
321 myprintf(_T("Message: %s\n"), mupGetErrorMsg(hParser));
322 myprintf(_T("Token: %s\n"), mupGetErrorToken(hParser));
323 myprintf(_T("Position: %d\n"), mupGetErrorPos(hParser));
324 myprintf(_T("Errc: %d\n"), mupGetErrorCode(hParser));
325 return;
326 }
327
328 for (i = 0; i < nBulkSize; ++i)
329 {
330 myprintf(_T("%d: bulkfun(%2.2f + %2.2f) = %2.2f\n"), i, x[i], y[i], r[i]);
331 x[i] = i;
332 y[i] = (muFloat_t)i / 10;
333 }
334
335 free(x);
336 free(y);
337 free(r);
338 }
339
340 //---------------------------------------------------------------------------
Calc()341 void Calc()
342 {
343 muChar_t szLine[100];
344 muFloat_t fVal = 0,
345 afVarVal[] = { 1, 2 }; // Values of the parser variables
346 muParserHandle_t hParser;
347
348 hParser = mupCreate(muBASETYPE_FLOAT); // initialize the parser
349 Intro(hParser);
350
351 // Set an error handler [optional]
352 // the only function that does not take a parser instance handle
353 mupSetErrorHandler(hParser, OnError);
354
355 //#define GERMAN_LOCALS
356 #ifdef GERMAN_LOCALS
357 mupSetArgSep(hParser, ';');
358 mupSetDecSep(hParser, ',');
359 mupSetThousandsSep(hParser, '.');
360 #else
361 mupSetArgSep(hParser, ',');
362 mupSetDecSep(hParser, '.');
363 #endif
364
365 // Set a variable factory
366 mupSetVarFactory(hParser, AddVariable, NULL);
367
368 // Define parser variables and bind them to C++ variables [optional]
369 mupDefineConst(hParser, _T("const1"), 1);
370 mupDefineConst(hParser, _T("const2"), 2);
371 mupDefineStrConst(hParser, _T("strBuf"), _T("Hallo welt"));
372
373 // Define parser variables and bind them to C++ variables [optional]
374 mupDefineVar(hParser, _T("a"), &afVarVal[0]);
375 mupDefineVar(hParser, _T("b"), &afVarVal[1]);
376
377 // Define postfix operators [optional]
378 mupDefinePostfixOprt(hParser, _T("M"), Mega, 0);
379 mupDefinePostfixOprt(hParser, _T("m"), Milli, 0);
380
381 // Define infix operator [optional]
382 mupDefineInfixOprt(hParser, _T("!"), Not, 0);
383
384 // Define functions [optional]
385 // mupDefineStrFun(hParser, "query", SampleQuery, 0); // Add an unoptimizeable function
386 mupDefineFun0(hParser, _T("zero"), ZeroArg, 0);
387 mupDefineFun1(hParser, _T("rnd"), Rnd, 0); // Add an unoptimizeable function
388 mupDefineFun1(hParser, _T("rnd2"), Rnd, 1);
389 mupDefineMultFun(hParser, _T("_sum"), Sum, 0); // "sum" is already a default function
390
391 // Define binary operators [optional]
392 mupDefineOprt(hParser, _T("add"), Add, 0, muOPRT_ASCT_LEFT, 0);
393 mupDefineOprt(hParser, _T("mul"), Mul, 1, muOPRT_ASCT_LEFT, 0);
394
395 while (myfgets(szLine, 99, stdin))
396 {
397 szLine[mystrlen(szLine) - 1] = 0; // overwrite the newline
398
399 switch (CheckKeywords(szLine, hParser))
400 {
401 case 0: break; // no keyword found; parse the line
402 case 1: continue; // A Keyword was found do not parse the line
403 case -1: return; // abort the application
404 }
405
406 mupSetExpr(hParser, szLine);
407
408 fVal = mupEval(hParser);
409
410
411 // Without an Error handler function
412 // you must use this for error treatment:
413 //if (mupError(hParser))
414 //{
415 // printf("\nError:\n");
416 // printf("------\n");
417 // printf("Message: %s\n", mupGetErrorMsg(hParser) );
418 // printf("Token: %s\n", mupGetErrorToken(hParser) );
419 // printf("Position: %s\n", mupGetErrorPos(hParser) );
420 // printf("Errc: %d\n", mupGetErrorCode(hParser) );
421 // continue;
422 //}
423
424 if (!mupError(hParser))
425 myprintf(_T("%f\n"), fVal);
426
427 } // while
428
429 // finalle free the parser ressources
430 mupRelease(hParser);
431 }
432
433 //---------------------------------------------------------------------------
main(int argc,char * argv[])434 int main(int argc, char *argv[])
435 {
436 // The next line is just for shutting up the compiler warning
437 // about unused variables without getting another warning about not
438 // beeing able to use type lists in function declarations.
439 myprintf(_T("Executing \"%s\" (argc=%d)\n"), argv[0], argc);
440 Calc();
441 printf(_T("done..."));
442 }
443