Mercurial > hg > dmlib
annotate src/dmeval.c @ 1102:e06abfde6c39
Cosmetics pass: Remove excess whitespace.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Tue, 03 Mar 2015 23:22:36 +0200 |
parents | ff13d79c75e0 |
children | 848a88ce7a57 |
rev | line source |
---|---|
0 | 1 #include "dmeval.h" |
2 #include <math.h> | |
3 | |
4 #define DM_MAX_BUF 512 | |
761
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
5 |
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
6 |
764 | 7 /* Operators |
8 */ | |
761
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
9 const DMEvalOper dmEvalOpers[OP_NOPERS] = |
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
10 { |
766
11fba703014f
Some more work. Still broken.
Matti Hamalainen <ccr@tnsp.org>
parents:
765
diff
changeset
|
11 { "-" , OT_UNARY , FALSE }, |
11fba703014f
Some more work. Still broken.
Matti Hamalainen <ccr@tnsp.org>
parents:
765
diff
changeset
|
12 { "~" , OT_UNARY , TRUE }, |
1102
e06abfde6c39
Cosmetics pass: Remove excess whitespace.
Matti Hamalainen <ccr@tnsp.org>
parents:
852
diff
changeset
|
13 |
766
11fba703014f
Some more work. Still broken.
Matti Hamalainen <ccr@tnsp.org>
parents:
765
diff
changeset
|
14 { "+" , OT_LEFT , TRUE }, |
11fba703014f
Some more work. Still broken.
Matti Hamalainen <ccr@tnsp.org>
parents:
765
diff
changeset
|
15 { "-" , OT_LEFT , TRUE }, |
11fba703014f
Some more work. Still broken.
Matti Hamalainen <ccr@tnsp.org>
parents:
765
diff
changeset
|
16 { "*" , OT_LEFT , TRUE }, |
11fba703014f
Some more work. Still broken.
Matti Hamalainen <ccr@tnsp.org>
parents:
765
diff
changeset
|
17 { "/" , OT_LEFT , TRUE }, |
11fba703014f
Some more work. Still broken.
Matti Hamalainen <ccr@tnsp.org>
parents:
765
diff
changeset
|
18 { "%" , OT_LEFT , TRUE }, |
761
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
19 |
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
20 |
766
11fba703014f
Some more work. Still broken.
Matti Hamalainen <ccr@tnsp.org>
parents:
765
diff
changeset
|
21 { "<<" , OT_LEFT , TRUE }, |
11fba703014f
Some more work. Still broken.
Matti Hamalainen <ccr@tnsp.org>
parents:
765
diff
changeset
|
22 { ">>" , OT_LEFT , TRUE }, |
761
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
23 |
766
11fba703014f
Some more work. Still broken.
Matti Hamalainen <ccr@tnsp.org>
parents:
765
diff
changeset
|
24 { "&" , OT_LEFT , TRUE }, |
11fba703014f
Some more work. Still broken.
Matti Hamalainen <ccr@tnsp.org>
parents:
765
diff
changeset
|
25 { "|" , OT_LEFT , TRUE }, |
11fba703014f
Some more work. Still broken.
Matti Hamalainen <ccr@tnsp.org>
parents:
765
diff
changeset
|
26 { "^" , OT_LEFT , TRUE }, |
761
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
27 |
766
11fba703014f
Some more work. Still broken.
Matti Hamalainen <ccr@tnsp.org>
parents:
765
diff
changeset
|
28 { ">=" , OT_LEFT , TRUE }, |
11fba703014f
Some more work. Still broken.
Matti Hamalainen <ccr@tnsp.org>
parents:
765
diff
changeset
|
29 { "<=" , OT_LEFT , TRUE }, |
11fba703014f
Some more work. Still broken.
Matti Hamalainen <ccr@tnsp.org>
parents:
765
diff
changeset
|
30 { ">" , OT_LEFT , TRUE }, |
11fba703014f
Some more work. Still broken.
Matti Hamalainen <ccr@tnsp.org>
parents:
765
diff
changeset
|
31 { "<" , OT_LEFT , TRUE }, |
761
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
32 |
766
11fba703014f
Some more work. Still broken.
Matti Hamalainen <ccr@tnsp.org>
parents:
765
diff
changeset
|
33 { "FUNC" , OT_NONE , FALSE }, |
11fba703014f
Some more work. Still broken.
Matti Hamalainen <ccr@tnsp.org>
parents:
765
diff
changeset
|
34 { "VAR" , OT_NONE , FALSE }, |
11fba703014f
Some more work. Still broken.
Matti Hamalainen <ccr@tnsp.org>
parents:
765
diff
changeset
|
35 { "CONST" , OT_NONE , FALSE }, |
761
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
36 |
766
11fba703014f
Some more work. Still broken.
Matti Hamalainen <ccr@tnsp.org>
parents:
765
diff
changeset
|
37 { "SUBEXPR", OT_NONE , FALSE }, |
761
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
38 }; |
0 | 39 |
670 | 40 |
41 /* Function definitions | |
42 */ | |
663
05eb24a608f0
Some minor touches to evaluator code.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
43 static DMValue func_int_clip(DMValue *v) |
05eb24a608f0
Some minor touches to evaluator code.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
44 { |
05eb24a608f0
Some minor touches to evaluator code.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
45 return (*v < -1.0f) ? -1.0f : ((*v > 1.0f) ? 1.0f : *v); |
05eb24a608f0
Some minor touches to evaluator code.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
46 } |
05eb24a608f0
Some minor touches to evaluator code.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
47 |
05eb24a608f0
Some minor touches to evaluator code.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
48 |
05eb24a608f0
Some minor touches to evaluator code.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
49 static DMValue func_sin(DMValue *v) |
0 | 50 { |
663
05eb24a608f0
Some minor touches to evaluator code.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
51 return sin(*v); |
05eb24a608f0
Some minor touches to evaluator code.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
52 } |
05eb24a608f0
Some minor touches to evaluator code.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
53 |
05eb24a608f0
Some minor touches to evaluator code.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
54 |
05eb24a608f0
Some minor touches to evaluator code.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
55 static DMValue func_cos(DMValue *v) |
05eb24a608f0
Some minor touches to evaluator code.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
56 { |
05eb24a608f0
Some minor touches to evaluator code.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
57 return cos(*v); |
05eb24a608f0
Some minor touches to evaluator code.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
58 } |
05eb24a608f0
Some minor touches to evaluator code.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
59 |
05eb24a608f0
Some minor touches to evaluator code.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
60 |
05eb24a608f0
Some minor touches to evaluator code.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
61 static DMValue func_pow(DMValue *v) |
05eb24a608f0
Some minor touches to evaluator code.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
62 { |
05eb24a608f0
Some minor touches to evaluator code.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
63 return pow(v[0], v[1]); |
0 | 64 } |
65 | |
66 | |
67 /* Some basic functions | |
68 */ | |
761
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
69 static const DMEvalSymbol dmEvalBasicFuncs[] = |
0 | 70 { |
765 | 71 { "sin", SYM_FUNC , 1, func_sin, NULL, 0 }, |
72 { "cos", SYM_FUNC , 1, func_cos, NULL, 0 }, | |
73 { "clip", SYM_FUNC , 1, func_int_clip, NULL, 0 }, | |
74 { "pow", SYM_FUNC , 2, func_pow, NULL, 0 }, | |
670 | 75 |
765 | 76 { "pi", SYM_CONST, 0, NULL, NULL, DM_PI }, |
77 { "e", SYM_CONST, 0, NULL, NULL, DM_E }, | |
0 | 78 }; |
79 | |
761
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
80 static const int ndmEvalBasicFuncs = sizeof(dmEvalBasicFuncs) / sizeof(dmEvalBasicFuncs[0]); |
0 | 81 |
82 | |
761
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
83 void dmEvalErrorV(DMEvalContext *ev, const char *fmt, va_list ap) |
0 | 84 { |
85 char *tmp = dm_strdup_vprintf(fmt, ap); | |
1102
e06abfde6c39
Cosmetics pass: Remove excess whitespace.
Matti Hamalainen <ccr@tnsp.org>
parents:
852
diff
changeset
|
86 |
0 | 87 ev->err = TRUE; |
88 | |
89 if (ev->errStr != NULL) | |
90 { | |
91 ev->errStr = dm_strdup_printf("%s%s", ev->errStr, tmp); | |
92 dmFree(tmp); | |
93 } | |
94 else | |
95 ev->errStr = tmp; | |
96 } | |
97 | |
98 | |
761
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
99 void dmEvalError(DMEvalContext *ev, const char *fmt, ...) |
0 | 100 { |
101 va_list ap; | |
102 va_start(ap, fmt); | |
761
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
103 dmEvalErrorV(ev, fmt, ap); |
0 | 104 va_end(ap); |
105 } | |
106 | |
107 | |
761
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
108 DMEvalSymbol *dmEvalContextFindSymbol(DMEvalContext *ev, const char *name) |
0 | 109 { |
110 int i; | |
761
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
111 if (ev->symbols == NULL) |
0 | 112 return NULL; |
113 | |
761
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
114 for (i = 0; i < ev->nsymbols; i++) |
670 | 115 { |
761
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
116 if (strcmp(ev->symbols[i].name, name) == 0) |
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
117 return &(ev->symbols[i]); |
670 | 118 } |
1102
e06abfde6c39
Cosmetics pass: Remove excess whitespace.
Matti Hamalainen <ccr@tnsp.org>
parents:
852
diff
changeset
|
119 |
0 | 120 return NULL; |
121 } | |
122 | |
123 | |
764 | 124 // Add a new symbol to the evaluation context. |
125 // Return pointer to newly allocated symbol struct if successful. | |
126 // If the symbol already exists or there was a memory allocation | |
127 // error, NULL is returned. | |
128 static DMEvalSymbol * dmEvalContextAddSymbol(DMEvalContext *ev, const char *name, const int type) | |
0 | 129 { |
764 | 130 DMEvalSymbol *symbol = dmEvalContextFindSymbol(ev, name); |
131 if (symbol != NULL) | |
0 | 132 return NULL; |
133 | |
761
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
134 ev->symbols = dmRealloc(ev->symbols, sizeof(DMEvalSymbol) * (ev->nsymbols + 1)); |
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
135 if (ev->symbols == NULL) |
0 | 136 { |
764 | 137 dmEvalError(ev, |
138 "Could not reallocate eval symbols array (#%d). Fatal error.\n", | |
139 ev->nsymbols + 1); | |
0 | 140 return NULL; |
141 } | |
1102
e06abfde6c39
Cosmetics pass: Remove excess whitespace.
Matti Hamalainen <ccr@tnsp.org>
parents:
852
diff
changeset
|
142 |
764 | 143 symbol = &(ev->symbols[ev->nsymbols]); |
761
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
144 ev->nsymbols++; |
0 | 145 |
764 | 146 memset(symbol, 0, sizeof(DMEvalSymbol)); |
147 symbol->name = dm_strdup(name); | |
148 symbol->type = type; | |
670 | 149 |
764 | 150 return symbol; |
0 | 151 } |
152 | |
153 | |
761
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
154 DMEvalSymbol *dmEvalContextAddVar(DMEvalContext *ev, const char *name, DMValue *var) |
0 | 155 { |
764 | 156 DMEvalSymbol *symbol = dmEvalContextAddSymbol(ev, name, SYM_VAR); |
157 if (symbol == NULL) | |
0 | 158 return NULL; |
1102
e06abfde6c39
Cosmetics pass: Remove excess whitespace.
Matti Hamalainen <ccr@tnsp.org>
parents:
852
diff
changeset
|
159 |
764 | 160 symbol->var = var; |
161 return symbol; | |
0 | 162 } |
163 | |
164 | |
761
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
165 DMEvalSymbol *dmEvalContextAddConst(DMEvalContext *ev, const char *name, DMValue value) |
670 | 166 { |
765 | 167 DMEvalSymbol *symbol = dmEvalContextAddSymbol(ev, name, SYM_CONST); |
764 | 168 if (symbol == NULL) |
670 | 169 return NULL; |
1102
e06abfde6c39
Cosmetics pass: Remove excess whitespace.
Matti Hamalainen <ccr@tnsp.org>
parents:
852
diff
changeset
|
170 |
764 | 171 symbol->cvalue = value; |
172 return symbol; | |
670 | 173 } |
174 | |
175 | |
761
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
176 DMEvalSymbol *dmEvalContextAddFunc(DMEvalContext *ev, const char *name, DMValue (*func)(DMValue *), int nargs) |
0 | 177 { |
764 | 178 DMEvalSymbol *symbol = dmEvalContextAddSymbol(ev, name, SYM_VAR); |
179 if (symbol == NULL) | |
0 | 180 return NULL; |
1102
e06abfde6c39
Cosmetics pass: Remove excess whitespace.
Matti Hamalainen <ccr@tnsp.org>
parents:
852
diff
changeset
|
181 |
764 | 182 symbol->func = func; |
183 symbol->nargs = nargs; | |
184 | |
185 return DMERR_OK; | |
0 | 186 } |
187 | |
188 | |
761
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
189 DMEvalContext *dmEvalContextNew(void) |
0 | 190 { |
191 int i; | |
192 DMEvalContext *ev = dmCalloc(1, sizeof(DMEvalContext)); | |
193 | |
194 if (ev == NULL) | |
195 return NULL; | |
196 | |
761
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
197 for (i = 0; i < ndmEvalBasicFuncs; i++) |
0 | 198 { |
764 | 199 const DMEvalSymbol *symbol= &dmEvalBasicFuncs[i]; |
200 DMEvalSymbol *nsymbol = dmEvalContextAddSymbol(ev, symbol->name, symbol->type); | |
201 if (nsymbol != NULL) | |
202 { | |
203 nsymbol->nargs = symbol->nargs; | |
204 nsymbol->func = symbol->func; | |
205 nsymbol->var = symbol->var; | |
206 nsymbol->cvalue = symbol->cvalue; | |
207 } | |
0 | 208 } |
209 | |
210 return ev; | |
211 } | |
212 | |
670 | 213 |
761
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
214 void dmEvalTreeFree(DMEvalNode *node) |
0 | 215 { |
216 while (node != NULL) | |
217 { | |
218 DMEvalNode *next = node->next; | |
670 | 219 int i; |
0 | 220 |
852 | 221 for (i = 0; i < DM_EVAL_MAX_ARGS; i++) |
670 | 222 { |
761
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
223 dmEvalTreeFree(node->args[i]); |
670 | 224 node->args[i] = NULL; |
225 } | |
0 | 226 |
761
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
227 dmEvalTreeFree(node->subexpr); |
687
f3d2b19dbbb7
Set node->subexpr to NULL in free, as we are paranoidly cargo-culting a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
686
diff
changeset
|
228 node->subexpr = NULL; |
0 | 229 dmFree(node); |
230 node = next; | |
231 } | |
232 } | |
233 | |
234 | |
761
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
235 void dmEvalContextClear(DMEvalContext *ev) |
0 | 236 { |
237 if (ev == NULL) | |
238 return; | |
1102
e06abfde6c39
Cosmetics pass: Remove excess whitespace.
Matti Hamalainen <ccr@tnsp.org>
parents:
852
diff
changeset
|
239 |
0 | 240 dmFree(ev->errStr); |
241 ev->err = FALSE; | |
242 ev->errStr = NULL; | |
243 } | |
244 | |
245 | |
761
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
246 void dmEvalContextClose(DMEvalContext *ev) |
0 | 247 { |
248 int i; | |
249 | |
250 if (ev == NULL) | |
251 return; | |
252 | |
761
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
253 for (i = 0; i < ev->nsymbols; i++) |
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
254 dmFree(ev->symbols[i].name); |
0 | 255 |
761
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
256 dmFree(ev->symbols); |
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
257 dmEvalContextClear(ev); |
0 | 258 dmFree(ev); |
259 } | |
260 | |
261 | |
761
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
262 static DMEvalNode *dmEvalInsertNode(DMEvalNode **list, DMEvalNode *node) |
0 | 263 { |
264 if (*list != NULL) | |
265 { | |
266 node->prev = (*list)->prev; | |
267 (*list)->prev->next = node; | |
268 (*list)->prev = node; | |
269 } | |
270 else | |
271 { | |
272 *list = node; | |
273 node->prev = *list; | |
274 } | |
275 | |
276 node->next = NULL; | |
277 return node; | |
278 } | |
279 | |
280 | |
761
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
281 static DMEvalNode *dmEvalAddNode(DMEvalNode **list, const int op) |
0 | 282 { |
283 DMEvalNode *node = dmCalloc(1, sizeof(DMEvalNode)); | |
284 if (node == NULL) | |
285 return NULL; | |
286 | |
287 node->op = op; | |
288 | |
761
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
289 return dmEvalInsertNode(list, node); |
0 | 290 } |
291 | |
292 | |
293 enum | |
294 { | |
740
48c48e94d87f
More work on the evaluator. Still broken, of course.
Matti Hamalainen <ccr@tnsp.org>
parents:
725
diff
changeset
|
295 PARSE_NONE = 0x0000, |
48c48e94d87f
More work on the evaluator. Still broken, of course.
Matti Hamalainen <ccr@tnsp.org>
parents:
725
diff
changeset
|
296 PARSE_START = 0x1000, |
48c48e94d87f
More work on the evaluator. Still broken, of course.
Matti Hamalainen <ccr@tnsp.org>
parents:
725
diff
changeset
|
297 PARSE_END = 0x2000, |
48c48e94d87f
More work on the evaluator. Still broken, of course.
Matti Hamalainen <ccr@tnsp.org>
parents:
725
diff
changeset
|
298 PARSE_ERROR = 0x8000, |
0 | 299 |
740
48c48e94d87f
More work on the evaluator. Still broken, of course.
Matti Hamalainen <ccr@tnsp.org>
parents:
725
diff
changeset
|
300 PARSE_IDENT = 0x0001, // Any identifier (variable, function name) |
48c48e94d87f
More work on the evaluator. Still broken, of course.
Matti Hamalainen <ccr@tnsp.org>
parents:
725
diff
changeset
|
301 PARSE_CONST = 0x0002, // Constant value (n, n.nnn, etc) |
48c48e94d87f
More work on the evaluator. Still broken, of course.
Matti Hamalainen <ccr@tnsp.org>
parents:
725
diff
changeset
|
302 PARSE_OPER = 0x0004, // All operators |
48c48e94d87f
More work on the evaluator. Still broken, of course.
Matti Hamalainen <ccr@tnsp.org>
parents:
725
diff
changeset
|
303 PARSE_OPER_UNARY = 0x0008, // Unary operators ~, - |
48c48e94d87f
More work on the evaluator. Still broken, of course.
Matti Hamalainen <ccr@tnsp.org>
parents:
725
diff
changeset
|
304 PARSE_SUBEXPR_START = 0x0010, // ( ... |
48c48e94d87f
More work on the evaluator. Still broken, of course.
Matti Hamalainen <ccr@tnsp.org>
parents:
725
diff
changeset
|
305 PARSE_SUBEXPR_END = 0x0020, // ) |
48c48e94d87f
More work on the evaluator. Still broken, of course.
Matti Hamalainen <ccr@tnsp.org>
parents:
725
diff
changeset
|
306 PARSE_ARGS = 0x0040, // function args: (xxx[, yyy ...]) |
670 | 307 |
740
48c48e94d87f
More work on the evaluator. Still broken, of course.
Matti Hamalainen <ccr@tnsp.org>
parents:
725
diff
changeset
|
308 PARSE_NORMAL = PARSE_CONST | PARSE_IDENT | PARSE_SUBEXPR_START | PARSE_OPER_UNARY, |
0 | 309 }; |
310 | |
311 #define DM_CHECK(x) { if (mode & PARSE_ ## x ) { if (str[0]) strcat(str, " or "); strcat(str, # x ); } } | |
312 | |
761
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
313 static char *dmEvalGetMode(int mode) |
0 | 314 { |
315 char str[128] = ""; | |
316 | |
317 DM_CHECK(START); | |
318 DM_CHECK(END); | |
319 DM_CHECK(IDENT); | |
320 DM_CHECK(CONST); | |
321 DM_CHECK(OPER); | |
740
48c48e94d87f
More work on the evaluator. Still broken, of course.
Matti Hamalainen <ccr@tnsp.org>
parents:
725
diff
changeset
|
322 DM_CHECK(OPER_UNARY); |
48c48e94d87f
More work on the evaluator. Still broken, of course.
Matti Hamalainen <ccr@tnsp.org>
parents:
725
diff
changeset
|
323 DM_CHECK(SUBEXPR_START); |
48c48e94d87f
More work on the evaluator. Still broken, of course.
Matti Hamalainen <ccr@tnsp.org>
parents:
725
diff
changeset
|
324 DM_CHECK(SUBEXPR_END); |
670 | 325 DM_CHECK(ARGS); |
1102
e06abfde6c39
Cosmetics pass: Remove excess whitespace.
Matti Hamalainen <ccr@tnsp.org>
parents:
852
diff
changeset
|
326 |
0 | 327 return dm_strdup(str); |
328 } | |
329 | |
330 | |
761
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
331 static void dmEvalSetMode(DMEvalContext *ev, const int mode) |
0 | 332 { |
670 | 333 if (mode != PARSE_ERROR && |
334 mode != PARSE_START && | |
0 | 335 ev->expect != PARSE_NONE && |
336 (mode & ev->expect) == 0) | |
337 { | |
761
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
338 char *tmp1 = dmEvalGetMode(ev->expect), |
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
339 *tmp2 = dmEvalGetMode(mode); |
0 | 340 |
761
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
341 dmEvalError(ev, "Expected [%s], got %s.\n", tmp1, tmp2); |
0 | 342 dmFree(tmp1); |
343 dmFree(tmp2); | |
344 } | |
345 | |
346 ev->prev = ev->mode; | |
347 ev->mode = mode; | |
348 } | |
349 | |
350 | |
765 | 351 static BOOL dmEvalTokenizeExpr(DMEvalContext *ev, DMEvalNode **list, char **str, int depth) |
0 | 352 { |
353 char *c = *str; | |
764 | 354 char tmpStr[DM_MAX_BUF + 2], *tmp; |
355 int tmpStrLen = 0, argIndex, op; | |
0 | 356 DMEvalNode *node = NULL, *func = NULL; |
357 BOOL first = FALSE, decimal = FALSE; | |
358 | |
670 | 359 ev->expect = PARSE_NORMAL; |
0 | 360 ev->mode = PARSE_START; |
1102
e06abfde6c39
Cosmetics pass: Remove excess whitespace.
Matti Hamalainen <ccr@tnsp.org>
parents:
852
diff
changeset
|
361 |
0 | 362 while (ev->mode != PARSE_ERROR && ev->mode != PARSE_END) |
363 switch (ev->mode) | |
364 { | |
365 case PARSE_START: | |
366 // Start | |
367 if (*c == 0) | |
761
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
368 dmEvalSetMode(ev, PARSE_END); |
0 | 369 |
670 | 370 // Skip whitespace |
0 | 371 else if (isspace(*c)) |
670 | 372 c++; |
0 | 373 |
670 | 374 else if (*c == ')' || *c == ',') |
0 | 375 { |
376 if (depth > 0) | |
761
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
377 dmEvalSetMode(ev, PARSE_END); |
0 | 378 else |
379 { | |
761
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
380 dmEvalError(ev, "Invalid nesting near '%s' (depth %d).\n", c, depth); |
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
381 dmEvalSetMode(ev, PARSE_ERROR); |
0 | 382 } |
383 c++; | |
384 } | |
1102
e06abfde6c39
Cosmetics pass: Remove excess whitespace.
Matti Hamalainen <ccr@tnsp.org>
parents:
852
diff
changeset
|
385 |
0 | 386 else if (*c == '(') |
761
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
387 dmEvalSetMode(ev, func != NULL ? PARSE_ARGS : PARSE_SUBEXPR_START); |
1102
e06abfde6c39
Cosmetics pass: Remove excess whitespace.
Matti Hamalainen <ccr@tnsp.org>
parents:
852
diff
changeset
|
388 |
671
e5e56d16597e
And another fix to parsing.
Matti Hamalainen <ccr@tnsp.org>
parents:
670
diff
changeset
|
389 else if (*c == '-') |
761
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
390 dmEvalSetMode(ev, (ev->prev == PARSE_START || ev->prev == PARSE_OPER || ev->prev == PARSE_OPER_UNARY) ? PARSE_OPER_UNARY : PARSE_OPER); |
1102
e06abfde6c39
Cosmetics pass: Remove excess whitespace.
Matti Hamalainen <ccr@tnsp.org>
parents:
852
diff
changeset
|
391 |
740
48c48e94d87f
More work on the evaluator. Still broken, of course.
Matti Hamalainen <ccr@tnsp.org>
parents:
725
diff
changeset
|
392 else if (*c == '~') |
761
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
393 dmEvalSetMode(ev, PARSE_OPER_UNARY); |
1102
e06abfde6c39
Cosmetics pass: Remove excess whitespace.
Matti Hamalainen <ccr@tnsp.org>
parents:
852
diff
changeset
|
394 |
671
e5e56d16597e
And another fix to parsing.
Matti Hamalainen <ccr@tnsp.org>
parents:
670
diff
changeset
|
395 else if (strchr("+*/<>%&|!^", *c)) |
761
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
396 dmEvalSetMode(ev, PARSE_OPER); |
0 | 397 |
398 else if (isdigit(*c) || *c == '.') | |
761
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
399 dmEvalSetMode(ev, PARSE_CONST); |
0 | 400 |
401 else if (isalpha(*c) || *c == '_') | |
761
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
402 dmEvalSetMode(ev, PARSE_IDENT); |
1102
e06abfde6c39
Cosmetics pass: Remove excess whitespace.
Matti Hamalainen <ccr@tnsp.org>
parents:
852
diff
changeset
|
403 |
0 | 404 else |
405 { | |
761
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
406 dmEvalError(ev, "Syntax error near '%s' (depth %d).\n", c, depth); |
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
407 dmEvalSetMode(ev, PARSE_ERROR); |
0 | 408 } |
409 | |
410 first = TRUE; | |
411 break; | |
1102
e06abfde6c39
Cosmetics pass: Remove excess whitespace.
Matti Hamalainen <ccr@tnsp.org>
parents:
852
diff
changeset
|
412 |
766
11fba703014f
Some more work. Still broken.
Matti Hamalainen <ccr@tnsp.org>
parents:
765
diff
changeset
|
413 case PARSE_SUBEXPR_START: |
11fba703014f
Some more work. Still broken.
Matti Hamalainen <ccr@tnsp.org>
parents:
765
diff
changeset
|
414 tmp = c + 1; |
11fba703014f
Some more work. Still broken.
Matti Hamalainen <ccr@tnsp.org>
parents:
765
diff
changeset
|
415 |
11fba703014f
Some more work. Still broken.
Matti Hamalainen <ccr@tnsp.org>
parents:
765
diff
changeset
|
416 ev->expect = PARSE_NORMAL; |
11fba703014f
Some more work. Still broken.
Matti Hamalainen <ccr@tnsp.org>
parents:
765
diff
changeset
|
417 |
11fba703014f
Some more work. Still broken.
Matti Hamalainen <ccr@tnsp.org>
parents:
765
diff
changeset
|
418 if ((node = dmEvalAddNode(list, OP_SUBEXPR)) == NULL) |
11fba703014f
Some more work. Still broken.
Matti Hamalainen <ccr@tnsp.org>
parents:
765
diff
changeset
|
419 dmEvalSetMode(ev, PARSE_ERROR); |
11fba703014f
Some more work. Still broken.
Matti Hamalainen <ccr@tnsp.org>
parents:
765
diff
changeset
|
420 else |
11fba703014f
Some more work. Still broken.
Matti Hamalainen <ccr@tnsp.org>
parents:
765
diff
changeset
|
421 if (dmEvalTokenizeExpr(ev, &(node->subexpr), &tmp, depth + 1) != 0) |
11fba703014f
Some more work. Still broken.
Matti Hamalainen <ccr@tnsp.org>
parents:
765
diff
changeset
|
422 { |
11fba703014f
Some more work. Still broken.
Matti Hamalainen <ccr@tnsp.org>
parents:
765
diff
changeset
|
423 dmEvalError(ev, "Subexpression starting at '%s' contained errors.\n", c); |
11fba703014f
Some more work. Still broken.
Matti Hamalainen <ccr@tnsp.org>
parents:
765
diff
changeset
|
424 dmEvalSetMode(ev, PARSE_ERROR); |
11fba703014f
Some more work. Still broken.
Matti Hamalainen <ccr@tnsp.org>
parents:
765
diff
changeset
|
425 } |
11fba703014f
Some more work. Still broken.
Matti Hamalainen <ccr@tnsp.org>
parents:
765
diff
changeset
|
426 |
11fba703014f
Some more work. Still broken.
Matti Hamalainen <ccr@tnsp.org>
parents:
765
diff
changeset
|
427 if (ev->mode != PARSE_ERROR) |
11fba703014f
Some more work. Still broken.
Matti Hamalainen <ccr@tnsp.org>
parents:
765
diff
changeset
|
428 { |
11fba703014f
Some more work. Still broken.
Matti Hamalainen <ccr@tnsp.org>
parents:
765
diff
changeset
|
429 dmEvalSetMode(ev, PARSE_START); |
11fba703014f
Some more work. Still broken.
Matti Hamalainen <ccr@tnsp.org>
parents:
765
diff
changeset
|
430 ev->expect = PARSE_OPER | PARSE_SUBEXPR_END; |
11fba703014f
Some more work. Still broken.
Matti Hamalainen <ccr@tnsp.org>
parents:
765
diff
changeset
|
431 c = tmp; |
11fba703014f
Some more work. Still broken.
Matti Hamalainen <ccr@tnsp.org>
parents:
765
diff
changeset
|
432 } |
11fba703014f
Some more work. Still broken.
Matti Hamalainen <ccr@tnsp.org>
parents:
765
diff
changeset
|
433 break; |
11fba703014f
Some more work. Still broken.
Matti Hamalainen <ccr@tnsp.org>
parents:
765
diff
changeset
|
434 |
11fba703014f
Some more work. Still broken.
Matti Hamalainen <ccr@tnsp.org>
parents:
765
diff
changeset
|
435 case PARSE_ARGS: |
11fba703014f
Some more work. Still broken.
Matti Hamalainen <ccr@tnsp.org>
parents:
765
diff
changeset
|
436 tmp = c + 1; |
1102
e06abfde6c39
Cosmetics pass: Remove excess whitespace.
Matti Hamalainen <ccr@tnsp.org>
parents:
852
diff
changeset
|
437 |
766
11fba703014f
Some more work. Still broken.
Matti Hamalainen <ccr@tnsp.org>
parents:
765
diff
changeset
|
438 for (argIndex = 0; argIndex < func->symbol->nargs; argIndex++) |
11fba703014f
Some more work. Still broken.
Matti Hamalainen <ccr@tnsp.org>
parents:
765
diff
changeset
|
439 { |
11fba703014f
Some more work. Still broken.
Matti Hamalainen <ccr@tnsp.org>
parents:
765
diff
changeset
|
440 if (dmEvalTokenizeExpr(ev, &(func->args[argIndex]), &tmp, depth + 1) != 0) |
11fba703014f
Some more work. Still broken.
Matti Hamalainen <ccr@tnsp.org>
parents:
765
diff
changeset
|
441 { |
11fba703014f
Some more work. Still broken.
Matti Hamalainen <ccr@tnsp.org>
parents:
765
diff
changeset
|
442 dmEvalError(ev, "Function argument subexpression starting at '%s' contained errors.\n", c); |
11fba703014f
Some more work. Still broken.
Matti Hamalainen <ccr@tnsp.org>
parents:
765
diff
changeset
|
443 dmEvalSetMode(ev, PARSE_ERROR); |
11fba703014f
Some more work. Still broken.
Matti Hamalainen <ccr@tnsp.org>
parents:
765
diff
changeset
|
444 } |
11fba703014f
Some more work. Still broken.
Matti Hamalainen <ccr@tnsp.org>
parents:
765
diff
changeset
|
445 } |
11fba703014f
Some more work. Still broken.
Matti Hamalainen <ccr@tnsp.org>
parents:
765
diff
changeset
|
446 |
11fba703014f
Some more work. Still broken.
Matti Hamalainen <ccr@tnsp.org>
parents:
765
diff
changeset
|
447 func = NULL; |
11fba703014f
Some more work. Still broken.
Matti Hamalainen <ccr@tnsp.org>
parents:
765
diff
changeset
|
448 |
11fba703014f
Some more work. Still broken.
Matti Hamalainen <ccr@tnsp.org>
parents:
765
diff
changeset
|
449 if (ev->mode != PARSE_ERROR) |
11fba703014f
Some more work. Still broken.
Matti Hamalainen <ccr@tnsp.org>
parents:
765
diff
changeset
|
450 { |
11fba703014f
Some more work. Still broken.
Matti Hamalainen <ccr@tnsp.org>
parents:
765
diff
changeset
|
451 dmEvalSetMode(ev, PARSE_START); |
11fba703014f
Some more work. Still broken.
Matti Hamalainen <ccr@tnsp.org>
parents:
765
diff
changeset
|
452 ev->expect = PARSE_OPER | PARSE_END; |
11fba703014f
Some more work. Still broken.
Matti Hamalainen <ccr@tnsp.org>
parents:
765
diff
changeset
|
453 c = tmp; |
11fba703014f
Some more work. Still broken.
Matti Hamalainen <ccr@tnsp.org>
parents:
765
diff
changeset
|
454 } |
11fba703014f
Some more work. Still broken.
Matti Hamalainen <ccr@tnsp.org>
parents:
765
diff
changeset
|
455 break; |
11fba703014f
Some more work. Still broken.
Matti Hamalainen <ccr@tnsp.org>
parents:
765
diff
changeset
|
456 |
0 | 457 case PARSE_CONST: |
458 if (first) | |
459 { | |
460 first = FALSE; | |
461 decimal = FALSE; | |
462 tmpStrLen = 0; | |
1102
e06abfde6c39
Cosmetics pass: Remove excess whitespace.
Matti Hamalainen <ccr@tnsp.org>
parents:
852
diff
changeset
|
463 |
0 | 464 if (isdigit(*c) || *c == '-' || *c == '+' || *c == '.') |
465 { | |
466 if (*c == '.') | |
467 decimal = TRUE; | |
468 tmpStr[tmpStrLen++] = *c++; | |
469 } | |
470 else | |
471 { | |
761
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
472 dmEvalError(ev, "Invalid constant expression near '%s'.\n", c); |
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
473 dmEvalSetMode(ev, PARSE_ERROR); |
0 | 474 } |
475 } | |
476 else | |
477 { | |
740
48c48e94d87f
More work on the evaluator. Still broken, of course.
Matti Hamalainen <ccr@tnsp.org>
parents:
725
diff
changeset
|
478 if (isdigit(*c)) |
48c48e94d87f
More work on the evaluator. Still broken, of course.
Matti Hamalainen <ccr@tnsp.org>
parents:
725
diff
changeset
|
479 { |
48c48e94d87f
More work on the evaluator. Still broken, of course.
Matti Hamalainen <ccr@tnsp.org>
parents:
725
diff
changeset
|
480 tmpStr[tmpStrLen++] = *c++; |
48c48e94d87f
More work on the evaluator. Still broken, of course.
Matti Hamalainen <ccr@tnsp.org>
parents:
725
diff
changeset
|
481 } |
48c48e94d87f
More work on the evaluator. Still broken, of course.
Matti Hamalainen <ccr@tnsp.org>
parents:
725
diff
changeset
|
482 else |
48c48e94d87f
More work on the evaluator. Still broken, of course.
Matti Hamalainen <ccr@tnsp.org>
parents:
725
diff
changeset
|
483 if (*c == '.') |
0 | 484 { |
740
48c48e94d87f
More work on the evaluator. Still broken, of course.
Matti Hamalainen <ccr@tnsp.org>
parents:
725
diff
changeset
|
485 if (!decimal) |
48c48e94d87f
More work on the evaluator. Still broken, of course.
Matti Hamalainen <ccr@tnsp.org>
parents:
725
diff
changeset
|
486 { |
48c48e94d87f
More work on the evaluator. Still broken, of course.
Matti Hamalainen <ccr@tnsp.org>
parents:
725
diff
changeset
|
487 tmpStr[tmpStrLen++] = *c++; |
0 | 488 decimal = TRUE; |
740
48c48e94d87f
More work on the evaluator. Still broken, of course.
Matti Hamalainen <ccr@tnsp.org>
parents:
725
diff
changeset
|
489 } |
48c48e94d87f
More work on the evaluator. Still broken, of course.
Matti Hamalainen <ccr@tnsp.org>
parents:
725
diff
changeset
|
490 else |
48c48e94d87f
More work on the evaluator. Still broken, of course.
Matti Hamalainen <ccr@tnsp.org>
parents:
725
diff
changeset
|
491 { |
761
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
492 dmEvalError(ev, "Invalid constant expression near '%s'.\n", c); |
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
493 dmEvalSetMode(ev, PARSE_ERROR); |
740
48c48e94d87f
More work on the evaluator. Still broken, of course.
Matti Hamalainen <ccr@tnsp.org>
parents:
725
diff
changeset
|
494 } |
0 | 495 } |
496 else | |
497 { | |
498 tmpStr[tmpStrLen] = 0; | |
499 | |
764 | 500 if ((node = dmEvalAddNode(list, OP_VALUE)) == NULL) |
0 | 501 { |
761
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
502 dmEvalSetMode(ev, PARSE_ERROR); |
0 | 503 } |
697
48321a711bec
Work towards plugging memory leaks.
Matti Hamalainen <ccr@tnsp.org>
parents:
696
diff
changeset
|
504 else |
48321a711bec
Work towards plugging memory leaks.
Matti Hamalainen <ccr@tnsp.org>
parents:
696
diff
changeset
|
505 { |
48321a711bec
Work towards plugging memory leaks.
Matti Hamalainen <ccr@tnsp.org>
parents:
696
diff
changeset
|
506 node->val = atof(tmpStr); |
761
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
507 dmEvalSetMode(ev, PARSE_START); |
697
48321a711bec
Work towards plugging memory leaks.
Matti Hamalainen <ccr@tnsp.org>
parents:
696
diff
changeset
|
508 ev->expect = PARSE_OPER | PARSE_END; |
48321a711bec
Work towards plugging memory leaks.
Matti Hamalainen <ccr@tnsp.org>
parents:
696
diff
changeset
|
509 } |
0 | 510 } |
511 } | |
512 break; | |
513 | |
740
48c48e94d87f
More work on the evaluator. Still broken, of course.
Matti Hamalainen <ccr@tnsp.org>
parents:
725
diff
changeset
|
514 case PARSE_OPER_UNARY: |
48c48e94d87f
More work on the evaluator. Still broken, of course.
Matti Hamalainen <ccr@tnsp.org>
parents:
725
diff
changeset
|
515 { |
761
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
516 int op = OP_INVALID; |
740
48c48e94d87f
More work on the evaluator. Still broken, of course.
Matti Hamalainen <ccr@tnsp.org>
parents:
725
diff
changeset
|
517 |
48c48e94d87f
More work on the evaluator. Still broken, of course.
Matti Hamalainen <ccr@tnsp.org>
parents:
725
diff
changeset
|
518 switch (*c) |
48c48e94d87f
More work on the evaluator. Still broken, of course.
Matti Hamalainen <ccr@tnsp.org>
parents:
725
diff
changeset
|
519 { |
48c48e94d87f
More work on the evaluator. Still broken, of course.
Matti Hamalainen <ccr@tnsp.org>
parents:
725
diff
changeset
|
520 case '-': op = OP_SUB_UNARY; c++; break; |
747 | 521 case '~': op = OP_BIT_COMPLEMENT; c++; break; |
740
48c48e94d87f
More work on the evaluator. Still broken, of course.
Matti Hamalainen <ccr@tnsp.org>
parents:
725
diff
changeset
|
522 } |
48c48e94d87f
More work on the evaluator. Still broken, of course.
Matti Hamalainen <ccr@tnsp.org>
parents:
725
diff
changeset
|
523 |
761
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
524 if (op != OP_INVALID) |
740
48c48e94d87f
More work on the evaluator. Still broken, of course.
Matti Hamalainen <ccr@tnsp.org>
parents:
725
diff
changeset
|
525 { |
761
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
526 if ((node = dmEvalAddNode(list, op)) != NULL) |
740
48c48e94d87f
More work on the evaluator. Still broken, of course.
Matti Hamalainen <ccr@tnsp.org>
parents:
725
diff
changeset
|
527 { |
48c48e94d87f
More work on the evaluator. Still broken, of course.
Matti Hamalainen <ccr@tnsp.org>
parents:
725
diff
changeset
|
528 ev->expect = PARSE_NORMAL; |
761
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
529 dmEvalSetMode(ev, PARSE_START); |
740
48c48e94d87f
More work on the evaluator. Still broken, of course.
Matti Hamalainen <ccr@tnsp.org>
parents:
725
diff
changeset
|
530 } |
48c48e94d87f
More work on the evaluator. Still broken, of course.
Matti Hamalainen <ccr@tnsp.org>
parents:
725
diff
changeset
|
531 else |
761
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
532 dmEvalSetMode(ev, PARSE_ERROR); |
740
48c48e94d87f
More work on the evaluator. Still broken, of course.
Matti Hamalainen <ccr@tnsp.org>
parents:
725
diff
changeset
|
533 } |
48c48e94d87f
More work on the evaluator. Still broken, of course.
Matti Hamalainen <ccr@tnsp.org>
parents:
725
diff
changeset
|
534 } |
48c48e94d87f
More work on the evaluator. Still broken, of course.
Matti Hamalainen <ccr@tnsp.org>
parents:
725
diff
changeset
|
535 break; |
48c48e94d87f
More work on the evaluator. Still broken, of course.
Matti Hamalainen <ccr@tnsp.org>
parents:
725
diff
changeset
|
536 |
0 | 537 case PARSE_OPER: |
764 | 538 op = OP_INVALID; |
740
48c48e94d87f
More work on the evaluator. Still broken, of course.
Matti Hamalainen <ccr@tnsp.org>
parents:
725
diff
changeset
|
539 |
764 | 540 switch (*c) |
541 { | |
542 case '+': op = OP_ADD; c++; break; | |
543 case '-': op = OP_SUB; c++; break; | |
544 case '*': op = OP_MUL; c++; break; | |
545 case '/': op = OP_DIV; c++; break; | |
546 case '%': op = OP_MOD; c++; break; | |
547 case '&': op = OP_BIT_AND; c++; break; | |
548 case '^': op = OP_BIT_XOR; c++; break; | |
549 case '|': op = OP_BIT_OR; c++; break; | |
0 | 550 |
764 | 551 case '>': |
552 if (c[1] == '>') | |
676 | 553 { |
764 | 554 c += 2; |
555 op = OP_BIT_RSHIFT; | |
0 | 556 } |
557 else | |
764 | 558 { |
559 op = (c[1] == '=') ? OP_GT_EQ : OP_GT; | |
560 c++; | |
561 } | |
562 break; | |
1102
e06abfde6c39
Cosmetics pass: Remove excess whitespace.
Matti Hamalainen <ccr@tnsp.org>
parents:
852
diff
changeset
|
563 |
764 | 564 case '<': |
565 if (c[1] == '<') | |
566 { | |
567 c += 2; | |
568 op = OP_BIT_LSHIFT; | |
569 } | |
570 else | |
571 { | |
572 op = (c[1] == '=') ? OP_LT_EQ : OP_LT; | |
573 c++; | |
574 } | |
575 break; | |
576 | |
577 default: | |
578 dmEvalError(ev, "Unknown operator '%c' at %s\n", *c, c); | |
579 dmEvalSetMode(ev, PARSE_ERROR); | |
580 } | |
581 | |
582 if (op != OP_INVALID) | |
583 { | |
584 if ((node = dmEvalAddNode(list, op)) != NULL) | |
585 { | |
586 ev->expect = PARSE_NORMAL | PARSE_OPER_UNARY; | |
587 dmEvalSetMode(ev, PARSE_START); | |
0 | 588 } |
764 | 589 else |
590 dmEvalSetMode(ev, PARSE_ERROR); | |
0 | 591 } |
592 break; | |
593 | |
594 case PARSE_IDENT: | |
595 if (isalnum(*c) || *c == '_') | |
596 { | |
597 if (first) | |
598 { | |
599 tmpStrLen = 0; | |
600 first = FALSE; | |
601 } | |
602 | |
761
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
603 if (tmpStrLen < DM_MAX_BUF) |
0 | 604 tmpStr[tmpStrLen++] = *c++; |
605 else | |
606 { | |
607 tmpStr[tmpStrLen] = 0; | |
761
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
608 dmEvalError(ev, "Identifier too long! ('%s') near %s\n", tmpStr, c); |
0 | 609 } |
610 } | |
611 else | |
612 { | |
613 tmpStr[tmpStrLen] = 0; | |
764 | 614 DMEvalSymbol *symbol = dmEvalContextFindSymbol(ev, tmpStr); |
615 if (symbol != NULL) | |
0 | 616 { |
764 | 617 if ((node = dmEvalAddNode(list, symbol->type == SYM_FUNC ? OP_FUNC : OP_VAR)) != NULL) |
0 | 618 { |
764 | 619 node->symbol = symbol; |
620 if (symbol->type == SYM_FUNC) | |
0 | 621 { |
622 func = node; | |
670 | 623 ev->expect = PARSE_ARGS; |
0 | 624 } |
625 else | |
626 ev->expect = PARSE_END | PARSE_OPER; | |
627 | |
761
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
628 dmEvalSetMode(ev, PARSE_START); |
0 | 629 } |
630 else | |
761
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
631 dmEvalSetMode(ev, PARSE_ERROR); |
0 | 632 } |
633 else | |
634 { | |
761
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
635 dmEvalError(ev, "No such identifier '%s'.\n", tmpStr); |
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
636 dmEvalSetMode(ev, PARSE_ERROR); |
0 | 637 } |
638 } | |
639 break; | |
640 } | |
641 | |
642 *str = c; | |
643 | |
765 | 644 return (ev->mode == PARSE_ERROR); |
0 | 645 } |
646 | |
647 | |
761
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
648 int dmEvalParseExpr(DMEvalContext *ev, char *expr, DMEvalNode **result) |
0 | 649 { |
650 int ret; | |
651 | |
652 if (ev == NULL || result == NULL) | |
765 | 653 return DMERR_NULLPTR; |
0 | 654 |
670 | 655 ev->prev = PARSE_START; |
761
7be7c7c5deaa
Large cleanup, breaking everything. Yay.
Matti Hamalainen <ccr@tnsp.org>
parents:
747
diff
changeset
|
656 ret = dmEvalTokenizeExpr(ev, result, &expr, 0); |
1102
e06abfde6c39
Cosmetics pass: Remove excess whitespace.
Matti Hamalainen <ccr@tnsp.org>
parents:
852
diff
changeset
|
657 |
0 | 658 return ret; |
659 } | |
660 | |
661 | |
662 | |
740
48c48e94d87f
More work on the evaluator. Still broken, of course.
Matti Hamalainen <ccr@tnsp.org>
parents:
725
diff
changeset
|
663 |
764 | 664 BOOL dmEvalTreeExecute(DMEvalContext *ev, DMEvalNode *node, DMValue *presult) |
0 | 665 { |
764 | 666 DMValue val1, val2; |
667 | |
0 | 668 if (node == NULL) |
764 | 669 return FALSE; |
670 | |
0 | 671 switch (node->op) |
672 { | |
765 | 673 case OP_VAR: |
674 switch (node->symbol->type) | |
675 { | |
676 case SYM_CONST: *presult = node->symbol->cvalue; return TRUE; | |
677 case SYM_VAR : *presult = *(node->symbol->var); return TRUE; | |
678 } | |
679 return FALSE; | |
680 | |
764 | 681 case OP_VALUE: |
682 *presult = node->val; | |
683 return TRUE; | |
1102
e06abfde6c39
Cosmetics pass: Remove excess whitespace.
Matti Hamalainen <ccr@tnsp.org>
parents:
852
diff
changeset
|
684 |
0 | 685 case OP_FUNC: |
1102
e06abfde6c39
Cosmetics pass: Remove excess whitespace.
Matti Hamalainen <ccr@tnsp.org>
parents:
852
diff
changeset
|
686 |
764 | 687 return TRUE; |
1102
e06abfde6c39
Cosmetics pass: Remove excess whitespace.
Matti Hamalainen <ccr@tnsp.org>
parents:
852
diff
changeset
|
688 |
764 | 689 case OP_SUBEXPR: |
690 return dmEvalTreeExecute(ev, node->subexpr, presult); | |
1102
e06abfde6c39
Cosmetics pass: Remove excess whitespace.
Matti Hamalainen <ccr@tnsp.org>
parents:
852
diff
changeset
|
691 |
764 | 692 // Binary operators |
693 case OP_BIT_LSHIFT: | |
694 case OP_BIT_RSHIFT: | |
1102
e06abfde6c39
Cosmetics pass: Remove excess whitespace.
Matti Hamalainen <ccr@tnsp.org>
parents:
852
diff
changeset
|
695 |
764 | 696 case OP_BIT_AND: |
697 case OP_BIT_XOR: | |
698 case OP_BIT_OR: | |
699 | |
700 case OP_ADD: | |
701 case OP_SUB: | |
702 case OP_MUL: | |
703 case OP_DIV: | |
704 case OP_MOD: | |
705 if (!dmEvalTreeExecute(ev, node->left, &val1) || | |
706 !dmEvalTreeExecute(ev, node->right, &val2)) | |
707 return FALSE; | |
708 | |
709 switch (node->op) | |
670 | 710 { |
764 | 711 case OP_DIV: |
712 if (val2 == 0) | |
713 { | |
714 dmEvalError(ev, "Division by zero.\n"); | |
715 return FALSE; | |
716 } | |
717 *presult = val1 / val2; | |
718 break; | |
0 | 719 |
720 | |
764 | 721 case OP_MOD: |
722 if (val2 == 0) | |
723 { | |
724 dmEvalError(ev, "Division by zero.\n"); | |
725 return FALSE; | |
726 } | |
727 *presult = DMCONVTYPE val1 % DMCONVTYPE val2; | |
728 break; | |
0 | 729 |
764 | 730 case OP_BIT_LSHIFT: |
731 if (val2 > 31) | |
732 dmEvalError(ev, "Left shift count >= width of type (%d << %d)\n", val1, val2); | |
733 *presult = DMCONVTYPE val1 << DMCONVTYPE val2; break; | |
0 | 734 |
764 | 735 case OP_BIT_RSHIFT: |
736 if (val2 > 31) | |
737 dmEvalError(ev, "Right shift count >= width of type (%d >> %d)\n", val1, val2); | |
738 *presult = DMCONVTYPE val1 >> DMCONVTYPE val2; break; | |
0 | 739 |
764 | 740 case OP_MUL : *presult = val1 * val2; break; |
741 case OP_ADD : *presult = val1 + val2; break; | |
742 case OP_SUB : *presult = val1 - val2; break; | |
743 case OP_BIT_AND : *presult = DMCONVTYPE val1 & DMCONVTYPE val2; break; | |
744 case OP_BIT_OR : *presult = DMCONVTYPE val1 | DMCONVTYPE val2; break; | |
745 case OP_BIT_XOR : *presult = DMCONVTYPE val1 ^ DMCONVTYPE val2; break; | |
746 } | |
747 return TRUE; | |
0 | 748 |
764 | 749 // Unary operators |
750 case OP_SUB_UNARY: | |
751 case OP_BIT_COMPLEMENT: | |
752 /* | |
753 switch (node->op) | |
754 { | |
755 case OP_SUB_UNARY: *presult -= tmp; break; | |
756 case OP_BIT_COMPLEMENT: *presult = DMCONVTYPE ~(DMCONVTYPE tmp); break; | |
757 } | |
758 */ | |
759 return TRUE; | |
0 | 760 |
764 | 761 default: |
762 dmEvalError(ev, "Invalid opcode %d in node %p.\n", node->op, node); | |
763 return FALSE; | |
0 | 764 } |
765 } |