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