Mercurial > hg-old > index.cgi
annotate lwlib/lw_expr.c @ 443:a8934dfba400 3.0 3.0.1
Fixed operator precedence for *
author | lost@l-w.ca |
---|---|
date | Sat, 30 Oct 2010 15:02:57 -0600 |
parents | 367bdde181be |
children | 5cccf90bf838 |
rev | line source |
---|---|
334 | 1 /* |
2 lwexpr.c | |
3 | |
4 Copyright © 2010 William Astle | |
5 | |
6 This file is part of LWTOOLS. | |
7 | |
8 LWTOOLS is free software: you can redistribute it and/or modify it under the | |
9 terms of the GNU General Public License as published by the Free Software | |
10 Foundation, either version 3 of the License, or (at your option) any later | |
11 version. | |
12 | |
13 This program is distributed in the hope that it will be useful, but WITHOUT | |
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
16 more details. | |
17 | |
18 You should have received a copy of the GNU General Public License along with | |
19 this program. If not, see <http://www.gnu.org/licenses/>. | |
20 */ | |
21 | |
22 #include <config.h> | |
23 | |
24 #include <stdarg.h> | |
25 #include <stdio.h> | |
26 #include <string.h> | |
27 | |
28 #define ___lw_expr_c_seen___ | |
29 #include "lw_alloc.h" | |
30 #include "lw_expr.h" | |
31 #include "lw_error.h" | |
32 #include "lw_string.h" | |
33 | |
342 | 34 static lw_expr_fn_t *evaluate_special = NULL; |
35 static lw_expr_fn2_t *evaluate_var = NULL; | |
346
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
36 static lw_expr_fn3_t *parse_term = NULL; |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
37 |
431
d7d7e4dca3e7
Eliminated infinite loop on recursive symbol resolution with a Q&D hack: limit the depth that lw_expr_simplify can be called to globally. Not thread friendly.
lost@l-w.ca
parents:
426
diff
changeset
|
38 /* Q&D to break out of infinite recursion */ |
d7d7e4dca3e7
Eliminated infinite loop on recursive symbol resolution with a Q&D hack: limit the depth that lw_expr_simplify can be called to globally. Not thread friendly.
lost@l-w.ca
parents:
426
diff
changeset
|
39 static int level = 0; |
d7d7e4dca3e7
Eliminated infinite loop on recursive symbol resolution with a Q&D hack: limit the depth that lw_expr_simplify can be called to globally. Not thread friendly.
lost@l-w.ca
parents:
426
diff
changeset
|
40 static int bailing = 0; |
d7d7e4dca3e7
Eliminated infinite loop on recursive symbol resolution with a Q&D hack: limit the depth that lw_expr_simplify can be called to globally. Not thread friendly.
lost@l-w.ca
parents:
426
diff
changeset
|
41 |
347 | 42 int lw_expr_istype(lw_expr_t e, int t) |
43 { | |
44 if (e -> type == t) | |
45 return 1; | |
46 return 0; | |
47 } | |
48 | |
49 int lw_expr_intval(lw_expr_t e) | |
50 { | |
51 if (e -> type == lw_expr_type_int) | |
52 return e -> value; | |
53 return -1; | |
54 } | |
55 | |
387
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
56 int lw_expr_whichop(lw_expr_t e) |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
57 { |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
58 if (e -> type == lw_expr_type_oper) |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
59 return e -> value; |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
60 return -1; |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
61 } |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
62 |
367 | 63 int lw_expr_specint(lw_expr_t e) |
64 { | |
65 if (e -> type == lw_expr_type_special) | |
66 return e -> value; | |
67 return -1; | |
68 } | |
69 | |
346
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
70 void lw_expr_set_term_parser(lw_expr_fn3_t *fn) |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
71 { |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
72 parse_term = fn; |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
73 } |
337 | 74 |
342 | 75 void lw_expr_set_special_handler(lw_expr_fn_t *fn) |
337 | 76 { |
77 evaluate_special = fn; | |
78 } | |
79 | |
342 | 80 void lw_expr_set_var_handler(lw_expr_fn2_t *fn) |
337 | 81 { |
82 evaluate_var = fn; | |
83 } | |
84 | |
334 | 85 lw_expr_t lw_expr_create(void) |
86 { | |
87 lw_expr_t r; | |
88 | |
89 r = lw_alloc(sizeof(struct lw_expr_priv)); | |
90 r -> operands = NULL; | |
91 | |
92 return r; | |
93 } | |
94 | |
95 void lw_expr_destroy(lw_expr_t E) | |
96 { | |
337 | 97 struct lw_expr_opers *o; |
426 | 98 if (!E) |
99 return; | |
438
22bbb716dea6
Fixed memory leaks related to expressions; bumped version to 3.0.1
lost@l-w.ca
parents:
431
diff
changeset
|
100 while (E -> operands) |
22bbb716dea6
Fixed memory leaks related to expressions; bumped version to 3.0.1
lost@l-w.ca
parents:
431
diff
changeset
|
101 { |
22bbb716dea6
Fixed memory leaks related to expressions; bumped version to 3.0.1
lost@l-w.ca
parents:
431
diff
changeset
|
102 o = E -> operands; |
22bbb716dea6
Fixed memory leaks related to expressions; bumped version to 3.0.1
lost@l-w.ca
parents:
431
diff
changeset
|
103 E -> operands = o -> next; |
337 | 104 lw_expr_destroy(o -> p); |
440 | 105 lw_free(o); |
438
22bbb716dea6
Fixed memory leaks related to expressions; bumped version to 3.0.1
lost@l-w.ca
parents:
431
diff
changeset
|
106 } |
337 | 107 if (E -> type == lw_expr_type_var) |
108 lw_free(E -> value2); | |
109 lw_free(E); | |
334 | 110 } |
111 | |
337 | 112 /* actually duplicates the entire expression */ |
113 void lw_expr_add_operand(lw_expr_t E, lw_expr_t O); | |
334 | 114 lw_expr_t lw_expr_copy(lw_expr_t E) |
115 { | |
337 | 116 lw_expr_t r, t; |
117 struct lw_expr_opers *o; | |
118 | |
119 r = lw_alloc(sizeof(struct lw_expr_priv)); | |
120 *r = *E; | |
121 r -> operands = NULL; | |
122 | |
123 if (E -> type == lw_expr_type_var) | |
124 r -> value2 = lw_strdup(E -> value2); | |
125 for (o = E -> operands; o; o = o -> next) | |
126 { | |
438
22bbb716dea6
Fixed memory leaks related to expressions; bumped version to 3.0.1
lost@l-w.ca
parents:
431
diff
changeset
|
127 lw_expr_add_operand(r, o -> p); |
337 | 128 } |
129 | |
130 return r; | |
334 | 131 } |
132 | |
133 void lw_expr_add_operand(lw_expr_t E, lw_expr_t O) | |
134 { | |
135 struct lw_expr_opers *o, *t; | |
136 | |
137 o = lw_alloc(sizeof(struct lw_expr_opers)); | |
138 o -> p = lw_expr_copy(O); | |
139 o -> next = NULL; | |
140 for (t = E -> operands; t && t -> next; t = t -> next) | |
141 /* do nothing */ ; | |
142 | |
143 if (t) | |
144 t -> next = o; | |
145 else | |
146 E -> operands = o; | |
147 } | |
148 | |
335 | 149 lw_expr_t lw_expr_build_aux(int exprtype, va_list args) |
334 | 150 { |
151 lw_expr_t r; | |
152 int t; | |
153 void *p; | |
154 | |
155 lw_expr_t te1, te2; | |
156 | |
157 r = lw_expr_create(); | |
158 | |
159 switch (exprtype) | |
160 { | |
161 case lw_expr_type_int: | |
162 t = va_arg(args, int); | |
163 r -> type = lw_expr_type_int; | |
164 r -> value = t; | |
165 break; | |
166 | |
167 case lw_expr_type_var: | |
168 p = va_arg(args, char *); | |
169 r -> type = lw_expr_type_var; | |
170 r -> value2 = lw_strdup(p); | |
171 break; | |
172 | |
173 case lw_expr_type_special: | |
174 t = va_arg(args, int); | |
175 p = va_arg(args, char *); | |
176 r -> type = lw_expr_type_special; | |
337 | 177 r -> value = t; |
334 | 178 r -> value2 = p; |
179 break; | |
180 | |
181 case lw_expr_type_oper: | |
182 t = va_arg(args, int); | |
183 te1 = va_arg(args, lw_expr_t); | |
184 if (t != lw_expr_oper_com && t != lw_expr_oper_neg) | |
185 te2 = va_arg(args, lw_expr_t); | |
186 else | |
187 te2 = NULL; | |
188 | |
189 r -> type = lw_expr_type_oper; | |
190 r -> value = t; | |
191 lw_expr_add_operand(r, te1); | |
371 | 192 if (te2) |
193 lw_expr_add_operand(r, te2); | |
334 | 194 break; |
195 | |
196 default: | |
197 lw_error("Invalid expression type specified to lw_expr_build"); | |
198 } | |
199 | |
335 | 200 return r; |
201 } | |
202 | |
203 lw_expr_t lw_expr_build(int exprtype, ...) | |
204 { | |
205 va_list args; | |
206 lw_expr_t r; | |
207 | |
208 va_start(args, exprtype); | |
209 r = lw_expr_build_aux(exprtype, args); | |
210 va_end(args); | |
211 return r; | |
212 } | |
213 | |
372
90de73ba0cac
Created a useful debug framework and adjusted lw_expr_print() to return a "static" dynamic string
lost@starbug
parents:
371
diff
changeset
|
214 void lw_expr_print_aux(lw_expr_t E, char **obuf, int *buflen, int *bufloc) |
334 | 215 { |
216 struct lw_expr_opers *o; | |
335 | 217 int c = 0; |
372
90de73ba0cac
Created a useful debug framework and adjusted lw_expr_print() to return a "static" dynamic string
lost@starbug
parents:
371
diff
changeset
|
218 char buf[256]; |
387
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
219 |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
220 if (!E) |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
221 { |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
222 strcpy(buf, "(NULL)"); |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
223 return; |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
224 } |
334 | 225 for (o = E -> operands; o; o = o -> next) |
226 { | |
335 | 227 c++; |
372
90de73ba0cac
Created a useful debug framework and adjusted lw_expr_print() to return a "static" dynamic string
lost@starbug
parents:
371
diff
changeset
|
228 lw_expr_print_aux(o -> p, obuf, buflen, bufloc); |
334 | 229 } |
230 | |
231 switch (E -> type) | |
232 { | |
233 case lw_expr_type_int: | |
371 | 234 if (E -> value < 0) |
372
90de73ba0cac
Created a useful debug framework and adjusted lw_expr_print() to return a "static" dynamic string
lost@starbug
parents:
371
diff
changeset
|
235 snprintf(buf, 256, "-%#x ", -(E -> value)); |
371 | 236 else |
372
90de73ba0cac
Created a useful debug framework and adjusted lw_expr_print() to return a "static" dynamic string
lost@starbug
parents:
371
diff
changeset
|
237 snprintf(buf, 256, "%#x ", E -> value); |
334 | 238 break; |
335 | 239 |
240 case lw_expr_type_var: | |
372
90de73ba0cac
Created a useful debug framework and adjusted lw_expr_print() to return a "static" dynamic string
lost@starbug
parents:
371
diff
changeset
|
241 snprintf(buf, 256, "V(%s) ", (char *)(E -> value2)); |
335 | 242 break; |
243 | |
244 case lw_expr_type_special: | |
372
90de73ba0cac
Created a useful debug framework and adjusted lw_expr_print() to return a "static" dynamic string
lost@starbug
parents:
371
diff
changeset
|
245 snprintf(buf, 256, "S(%d,%p) ", E -> value, E -> value2); |
335 | 246 break; |
247 | |
334 | 248 case lw_expr_type_oper: |
372
90de73ba0cac
Created a useful debug framework and adjusted lw_expr_print() to return a "static" dynamic string
lost@starbug
parents:
371
diff
changeset
|
249 snprintf(buf, 256, "[%d]", c); |
334 | 250 switch (E -> value) |
251 { | |
252 case lw_expr_oper_plus: | |
372
90de73ba0cac
Created a useful debug framework and adjusted lw_expr_print() to return a "static" dynamic string
lost@starbug
parents:
371
diff
changeset
|
253 strcat(buf, "+ "); |
334 | 254 break; |
255 | |
256 case lw_expr_oper_minus: | |
372
90de73ba0cac
Created a useful debug framework and adjusted lw_expr_print() to return a "static" dynamic string
lost@starbug
parents:
371
diff
changeset
|
257 strcat(buf, "- "); |
334 | 258 break; |
259 | |
260 case lw_expr_oper_times: | |
372
90de73ba0cac
Created a useful debug framework and adjusted lw_expr_print() to return a "static" dynamic string
lost@starbug
parents:
371
diff
changeset
|
261 strcat(buf, "* "); |
334 | 262 break; |
263 | |
264 case lw_expr_oper_divide: | |
372
90de73ba0cac
Created a useful debug framework and adjusted lw_expr_print() to return a "static" dynamic string
lost@starbug
parents:
371
diff
changeset
|
265 strcat(buf, "/ "); |
334 | 266 break; |
267 | |
268 case lw_expr_oper_mod: | |
372
90de73ba0cac
Created a useful debug framework and adjusted lw_expr_print() to return a "static" dynamic string
lost@starbug
parents:
371
diff
changeset
|
269 strcat(buf, "% "); |
334 | 270 break; |
271 | |
272 case lw_expr_oper_intdiv: | |
372
90de73ba0cac
Created a useful debug framework and adjusted lw_expr_print() to return a "static" dynamic string
lost@starbug
parents:
371
diff
changeset
|
273 strcat(buf, "\\ "); |
334 | 274 break; |
275 | |
276 case lw_expr_oper_bwand: | |
372
90de73ba0cac
Created a useful debug framework and adjusted lw_expr_print() to return a "static" dynamic string
lost@starbug
parents:
371
diff
changeset
|
277 strcat(buf, "BWAND "); |
334 | 278 break; |
279 | |
280 case lw_expr_oper_bwor: | |
372
90de73ba0cac
Created a useful debug framework and adjusted lw_expr_print() to return a "static" dynamic string
lost@starbug
parents:
371
diff
changeset
|
281 strcat(buf, "BWOR "); |
334 | 282 break; |
283 | |
284 case lw_expr_oper_bwxor: | |
372
90de73ba0cac
Created a useful debug framework and adjusted lw_expr_print() to return a "static" dynamic string
lost@starbug
parents:
371
diff
changeset
|
285 strcat(buf, "BWXOR "); |
334 | 286 break; |
287 | |
288 case lw_expr_oper_and: | |
372
90de73ba0cac
Created a useful debug framework and adjusted lw_expr_print() to return a "static" dynamic string
lost@starbug
parents:
371
diff
changeset
|
289 strcat(buf, "AND "); |
334 | 290 break; |
291 | |
292 case lw_expr_oper_or: | |
372
90de73ba0cac
Created a useful debug framework and adjusted lw_expr_print() to return a "static" dynamic string
lost@starbug
parents:
371
diff
changeset
|
293 strcat(buf, "OR "); |
334 | 294 break; |
295 | |
296 case lw_expr_oper_neg: | |
372
90de73ba0cac
Created a useful debug framework and adjusted lw_expr_print() to return a "static" dynamic string
lost@starbug
parents:
371
diff
changeset
|
297 strcat(buf, "NEG "); |
334 | 298 break; |
299 | |
300 case lw_expr_oper_com: | |
372
90de73ba0cac
Created a useful debug framework and adjusted lw_expr_print() to return a "static" dynamic string
lost@starbug
parents:
371
diff
changeset
|
301 strcat(buf, "COM "); |
334 | 302 break; |
303 | |
304 default: | |
372
90de73ba0cac
Created a useful debug framework and adjusted lw_expr_print() to return a "static" dynamic string
lost@starbug
parents:
371
diff
changeset
|
305 strcat(buf, "OPER "); |
334 | 306 break; |
307 } | |
308 break; | |
309 default: | |
372
90de73ba0cac
Created a useful debug framework and adjusted lw_expr_print() to return a "static" dynamic string
lost@starbug
parents:
371
diff
changeset
|
310 snprintf(buf, 256, "ERR "); |
334 | 311 break; |
312 } | |
372
90de73ba0cac
Created a useful debug framework and adjusted lw_expr_print() to return a "static" dynamic string
lost@starbug
parents:
371
diff
changeset
|
313 |
90de73ba0cac
Created a useful debug framework and adjusted lw_expr_print() to return a "static" dynamic string
lost@starbug
parents:
371
diff
changeset
|
314 c = strlen(buf); |
90de73ba0cac
Created a useful debug framework and adjusted lw_expr_print() to return a "static" dynamic string
lost@starbug
parents:
371
diff
changeset
|
315 if (*bufloc + c >= *buflen) |
90de73ba0cac
Created a useful debug framework and adjusted lw_expr_print() to return a "static" dynamic string
lost@starbug
parents:
371
diff
changeset
|
316 { |
90de73ba0cac
Created a useful debug framework and adjusted lw_expr_print() to return a "static" dynamic string
lost@starbug
parents:
371
diff
changeset
|
317 *buflen += 128; |
90de73ba0cac
Created a useful debug framework and adjusted lw_expr_print() to return a "static" dynamic string
lost@starbug
parents:
371
diff
changeset
|
318 *obuf = lw_realloc(*obuf, *buflen); |
90de73ba0cac
Created a useful debug framework and adjusted lw_expr_print() to return a "static" dynamic string
lost@starbug
parents:
371
diff
changeset
|
319 } |
90de73ba0cac
Created a useful debug framework and adjusted lw_expr_print() to return a "static" dynamic string
lost@starbug
parents:
371
diff
changeset
|
320 strcpy(*obuf + *bufloc, buf); |
90de73ba0cac
Created a useful debug framework and adjusted lw_expr_print() to return a "static" dynamic string
lost@starbug
parents:
371
diff
changeset
|
321 *bufloc += c; |
90de73ba0cac
Created a useful debug framework and adjusted lw_expr_print() to return a "static" dynamic string
lost@starbug
parents:
371
diff
changeset
|
322 } |
90de73ba0cac
Created a useful debug framework and adjusted lw_expr_print() to return a "static" dynamic string
lost@starbug
parents:
371
diff
changeset
|
323 |
90de73ba0cac
Created a useful debug framework and adjusted lw_expr_print() to return a "static" dynamic string
lost@starbug
parents:
371
diff
changeset
|
324 char *lw_expr_print(lw_expr_t E) |
90de73ba0cac
Created a useful debug framework and adjusted lw_expr_print() to return a "static" dynamic string
lost@starbug
parents:
371
diff
changeset
|
325 { |
90de73ba0cac
Created a useful debug framework and adjusted lw_expr_print() to return a "static" dynamic string
lost@starbug
parents:
371
diff
changeset
|
326 static char *obuf = NULL; |
90de73ba0cac
Created a useful debug framework and adjusted lw_expr_print() to return a "static" dynamic string
lost@starbug
parents:
371
diff
changeset
|
327 static int obufsize = 0; |
90de73ba0cac
Created a useful debug framework and adjusted lw_expr_print() to return a "static" dynamic string
lost@starbug
parents:
371
diff
changeset
|
328 |
90de73ba0cac
Created a useful debug framework and adjusted lw_expr_print() to return a "static" dynamic string
lost@starbug
parents:
371
diff
changeset
|
329 int obufloc = 0; |
90de73ba0cac
Created a useful debug framework and adjusted lw_expr_print() to return a "static" dynamic string
lost@starbug
parents:
371
diff
changeset
|
330 |
90de73ba0cac
Created a useful debug framework and adjusted lw_expr_print() to return a "static" dynamic string
lost@starbug
parents:
371
diff
changeset
|
331 lw_expr_print_aux(E, &obuf, &obufsize, &obufloc); |
90de73ba0cac
Created a useful debug framework and adjusted lw_expr_print() to return a "static" dynamic string
lost@starbug
parents:
371
diff
changeset
|
332 |
90de73ba0cac
Created a useful debug framework and adjusted lw_expr_print() to return a "static" dynamic string
lost@starbug
parents:
371
diff
changeset
|
333 return obuf; |
334 | 334 } |
335 | |
336 /* | |
337 Return: | |
338 nonzero if expressions are the same (identical pointers or matching values) | |
339 zero if expressions are not the same | |
340 | |
341 */ | |
342 int lw_expr_compare(lw_expr_t E1, lw_expr_t E2) | |
343 { | |
344 struct lw_expr_opers *o1, *o2; | |
345 | |
346 if (E1 == E2) | |
347 return 1; | |
348 | |
431
d7d7e4dca3e7
Eliminated infinite loop on recursive symbol resolution with a Q&D hack: limit the depth that lw_expr_simplify can be called to globally. Not thread friendly.
lost@l-w.ca
parents:
426
diff
changeset
|
349 if (!E1 || !E2) |
d7d7e4dca3e7
Eliminated infinite loop on recursive symbol resolution with a Q&D hack: limit the depth that lw_expr_simplify can be called to globally. Not thread friendly.
lost@l-w.ca
parents:
426
diff
changeset
|
350 return 0; |
d7d7e4dca3e7
Eliminated infinite loop on recursive symbol resolution with a Q&D hack: limit the depth that lw_expr_simplify can be called to globally. Not thread friendly.
lost@l-w.ca
parents:
426
diff
changeset
|
351 |
334 | 352 if (!(E1 -> type == E2 -> type && E1 -> value == E2 -> value)) |
353 return 0; | |
354 | |
355 if (E1 -> type == lw_expr_type_var) | |
356 { | |
357 if (!strcmp(E1 -> value2, E2 -> value2)) | |
358 return 1; | |
359 else | |
360 return 0; | |
361 } | |
362 | |
363 if (E1 -> type == lw_expr_type_special) | |
364 { | |
365 if (E1 -> value2 == E2 -> value2) | |
366 return 1; | |
367 else | |
368 return 0; | |
369 } | |
370 | |
371 for (o1 = E1 -> operands, o2 = E2 -> operands; o1 && o2; o1 = o1 -> next, o2 = o2 -> next) | |
372 if (lw_expr_compare(o1 -> p, o2 -> p) == 0) | |
373 return 0; | |
374 if (o1 || o2) | |
375 return 0; | |
376 | |
377 return 1; | |
378 } | |
379 | |
380 /* return true if E is an operator of type oper */ | |
381 int lw_expr_isoper(lw_expr_t E, int oper) | |
382 { | |
383 if (E -> type == lw_expr_type_oper && E -> value == oper) | |
384 return 1; | |
385 return 0; | |
386 } | |
335 | 387 |
388 | |
389 void lw_expr_simplify_sortconstfirst(lw_expr_t E) | |
390 { | |
391 struct lw_expr_opers *o; | |
371 | 392 |
393 if (E -> type != lw_expr_type_oper) | |
394 return; | |
395 if (E -> value != lw_expr_oper_times && E -> value != lw_expr_oper_plus) | |
396 return; | |
397 | |
335 | 398 for (o = E -> operands; o; o = o -> next) |
371 | 399 { |
400 if (o -> p -> type == lw_expr_type_oper && (o -> p -> value == lw_expr_oper_times || o -> p -> value == lw_expr_oper_plus)) | |
401 lw_expr_simplify_sortconstfirst(o -> p); | |
402 } | |
335 | 403 |
404 for (o = E -> operands; o; o = o -> next) | |
405 { | |
406 if (o -> p -> type == lw_expr_type_int && o != E -> operands) | |
407 { | |
408 struct lw_expr_opers *o2; | |
409 for (o2 = E -> operands; o2 -> next != o; o2 = o2 -> next) | |
410 /* do nothing */ ; | |
411 o2 -> next = o -> next; | |
412 o -> next = E -> operands; | |
413 E -> operands = o; | |
414 o = o2; | |
415 } | |
416 } | |
417 } | |
418 | |
336 | 419 void lw_expr_sortoperandlist(struct lw_expr_opers **o) |
420 { | |
382 | 421 // fprintf(stderr, "lw_expr_sortoperandlist() not yet implemented\n"); |
336 | 422 } |
423 | |
335 | 424 // return 1 if the operand lists match, 0 if not |
425 // may re-order the argument lists | |
426 int lw_expr_simplify_compareoperandlist(struct lw_expr_opers **ol1, struct lw_expr_opers **ol2) | |
427 { | |
428 struct lw_expr_opers *o1, *o2; | |
429 | |
430 lw_expr_sortoperandlist(ol1); | |
431 lw_expr_sortoperandlist(ol2); | |
432 | |
433 for (o1 = *ol1, o2 = *ol2; o1 && o2; o1 = o1 -> next, o2 = o2 -> next) | |
434 { | |
435 if (!lw_expr_compare(o1 -> p, o2 -> p)) | |
436 return 0; | |
437 } | |
438 if (o1 || o2) | |
439 return 0; | |
440 return 1; | |
441 } | |
442 | |
371 | 443 int lw_expr_simplify_isliketerm(lw_expr_t e1, lw_expr_t e2) |
444 { | |
445 // first term is a "times" | |
446 if (e1 -> type == lw_expr_type_oper && e1 -> value == lw_expr_oper_times) | |
447 { | |
448 // second term is a "times" | |
449 if (e2 -> type == lw_expr_type_oper && e2 -> value == lw_expr_oper_times) | |
450 { | |
451 // both times - easy check | |
452 struct lw_expr_opers *o1, *o2; | |
453 for (o1 = e1 -> operands; o1; o1 = o1 -> next) | |
454 if (o1 -> p -> type != lw_expr_type_int) | |
455 break; | |
456 | |
457 for (o2 = e2 -> operands; o2; o2 = o2 -> next) | |
458 if (o2 -> p -> type != lw_expr_type_int) | |
459 break; | |
460 | |
461 if (lw_expr_simplify_compareoperandlist(&o1, &o2)) | |
462 return 1; | |
463 return 0; | |
464 } | |
465 | |
466 // not a times - have to assume it's the operand list | |
467 // with a "1 *" in front if it | |
431
d7d7e4dca3e7
Eliminated infinite loop on recursive symbol resolution with a Q&D hack: limit the depth that lw_expr_simplify can be called to globally. Not thread friendly.
lost@l-w.ca
parents:
426
diff
changeset
|
468 if (!e1 -> operands -> next) |
d7d7e4dca3e7
Eliminated infinite loop on recursive symbol resolution with a Q&D hack: limit the depth that lw_expr_simplify can be called to globally. Not thread friendly.
lost@l-w.ca
parents:
426
diff
changeset
|
469 return 0; |
371 | 470 if (e1 -> operands -> next -> next) |
471 return 0; | |
472 if (!lw_expr_compare(e1 -> operands -> next -> p, e2)) | |
473 return 0; | |
474 return 1; | |
475 } | |
476 | |
477 // e1 is not a times | |
478 if (e2 -> type == lw_expr_type_oper && e2 -> value == lw_expr_oper_times) | |
479 { | |
480 // e2 is a times | |
481 if (e2 -> operands -> next -> next) | |
482 return 0; | |
483 if (!lw_expr_compare(e1, e2 -> operands -> next -> p)) | |
484 return 0; | |
485 return 1; | |
486 } | |
487 | |
488 // neither are times | |
489 if (!lw_expr_compare(e1, e2)) | |
490 return 0; | |
491 return 1; | |
492 } | |
493 | |
431
d7d7e4dca3e7
Eliminated infinite loop on recursive symbol resolution with a Q&D hack: limit the depth that lw_expr_simplify can be called to globally. Not thread friendly.
lost@l-w.ca
parents:
426
diff
changeset
|
494 int lw_expr_contains(lw_expr_t E, lw_expr_t E1) |
d7d7e4dca3e7
Eliminated infinite loop on recursive symbol resolution with a Q&D hack: limit the depth that lw_expr_simplify can be called to globally. Not thread friendly.
lost@l-w.ca
parents:
426
diff
changeset
|
495 { |
d7d7e4dca3e7
Eliminated infinite loop on recursive symbol resolution with a Q&D hack: limit the depth that lw_expr_simplify can be called to globally. Not thread friendly.
lost@l-w.ca
parents:
426
diff
changeset
|
496 struct lw_expr_opers *o; |
d7d7e4dca3e7
Eliminated infinite loop on recursive symbol resolution with a Q&D hack: limit the depth that lw_expr_simplify can be called to globally. Not thread friendly.
lost@l-w.ca
parents:
426
diff
changeset
|
497 |
d7d7e4dca3e7
Eliminated infinite loop on recursive symbol resolution with a Q&D hack: limit the depth that lw_expr_simplify can be called to globally. Not thread friendly.
lost@l-w.ca
parents:
426
diff
changeset
|
498 // NULL expr contains nothing :) |
d7d7e4dca3e7
Eliminated infinite loop on recursive symbol resolution with a Q&D hack: limit the depth that lw_expr_simplify can be called to globally. Not thread friendly.
lost@l-w.ca
parents:
426
diff
changeset
|
499 if (!E) |
d7d7e4dca3e7
Eliminated infinite loop on recursive symbol resolution with a Q&D hack: limit the depth that lw_expr_simplify can be called to globally. Not thread friendly.
lost@l-w.ca
parents:
426
diff
changeset
|
500 return 0; |
d7d7e4dca3e7
Eliminated infinite loop on recursive symbol resolution with a Q&D hack: limit the depth that lw_expr_simplify can be called to globally. Not thread friendly.
lost@l-w.ca
parents:
426
diff
changeset
|
501 |
d7d7e4dca3e7
Eliminated infinite loop on recursive symbol resolution with a Q&D hack: limit the depth that lw_expr_simplify can be called to globally. Not thread friendly.
lost@l-w.ca
parents:
426
diff
changeset
|
502 if (E1 -> type != lw_expr_type_var && E1 -> type != lw_expr_type_special) |
d7d7e4dca3e7
Eliminated infinite loop on recursive symbol resolution with a Q&D hack: limit the depth that lw_expr_simplify can be called to globally. Not thread friendly.
lost@l-w.ca
parents:
426
diff
changeset
|
503 return 0; |
d7d7e4dca3e7
Eliminated infinite loop on recursive symbol resolution with a Q&D hack: limit the depth that lw_expr_simplify can be called to globally. Not thread friendly.
lost@l-w.ca
parents:
426
diff
changeset
|
504 |
d7d7e4dca3e7
Eliminated infinite loop on recursive symbol resolution with a Q&D hack: limit the depth that lw_expr_simplify can be called to globally. Not thread friendly.
lost@l-w.ca
parents:
426
diff
changeset
|
505 if (lw_expr_compare(E, E1)) |
d7d7e4dca3e7
Eliminated infinite loop on recursive symbol resolution with a Q&D hack: limit the depth that lw_expr_simplify can be called to globally. Not thread friendly.
lost@l-w.ca
parents:
426
diff
changeset
|
506 return 1; |
d7d7e4dca3e7
Eliminated infinite loop on recursive symbol resolution with a Q&D hack: limit the depth that lw_expr_simplify can be called to globally. Not thread friendly.
lost@l-w.ca
parents:
426
diff
changeset
|
507 |
d7d7e4dca3e7
Eliminated infinite loop on recursive symbol resolution with a Q&D hack: limit the depth that lw_expr_simplify can be called to globally. Not thread friendly.
lost@l-w.ca
parents:
426
diff
changeset
|
508 for (o = E -> operands; o; o = o -> next) |
d7d7e4dca3e7
Eliminated infinite loop on recursive symbol resolution with a Q&D hack: limit the depth that lw_expr_simplify can be called to globally. Not thread friendly.
lost@l-w.ca
parents:
426
diff
changeset
|
509 { |
d7d7e4dca3e7
Eliminated infinite loop on recursive symbol resolution with a Q&D hack: limit the depth that lw_expr_simplify can be called to globally. Not thread friendly.
lost@l-w.ca
parents:
426
diff
changeset
|
510 if (lw_expr_contains(o -> p, E1)) |
d7d7e4dca3e7
Eliminated infinite loop on recursive symbol resolution with a Q&D hack: limit the depth that lw_expr_simplify can be called to globally. Not thread friendly.
lost@l-w.ca
parents:
426
diff
changeset
|
511 return 1; |
d7d7e4dca3e7
Eliminated infinite loop on recursive symbol resolution with a Q&D hack: limit the depth that lw_expr_simplify can be called to globally. Not thread friendly.
lost@l-w.ca
parents:
426
diff
changeset
|
512 } |
d7d7e4dca3e7
Eliminated infinite loop on recursive symbol resolution with a Q&D hack: limit the depth that lw_expr_simplify can be called to globally. Not thread friendly.
lost@l-w.ca
parents:
426
diff
changeset
|
513 return 0; |
d7d7e4dca3e7
Eliminated infinite loop on recursive symbol resolution with a Q&D hack: limit the depth that lw_expr_simplify can be called to globally. Not thread friendly.
lost@l-w.ca
parents:
426
diff
changeset
|
514 } |
d7d7e4dca3e7
Eliminated infinite loop on recursive symbol resolution with a Q&D hack: limit the depth that lw_expr_simplify can be called to globally. Not thread friendly.
lost@l-w.ca
parents:
426
diff
changeset
|
515 |
d7d7e4dca3e7
Eliminated infinite loop on recursive symbol resolution with a Q&D hack: limit the depth that lw_expr_simplify can be called to globally. Not thread friendly.
lost@l-w.ca
parents:
426
diff
changeset
|
516 void lw_expr_simplify_l(lw_expr_t E, void *priv); |
387
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
517 |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
518 void lw_expr_simplify_go(lw_expr_t E, void *priv) |
335 | 519 { |
520 struct lw_expr_opers *o; | |
521 | |
371 | 522 // replace subtraction with O1 + -1(O2)... |
523 // needed for like term collection | |
524 if (E -> type == lw_expr_type_oper && E -> value == lw_expr_oper_minus) | |
525 { | |
526 for (o = E -> operands -> next; o; o = o -> next) | |
527 { | |
528 lw_expr_t e1, e2; | |
529 | |
530 e2 = lw_expr_build(lw_expr_type_int, -1); | |
531 e1 = lw_expr_build(lw_expr_type_oper, lw_expr_oper_times, e2, o -> p); | |
532 lw_expr_destroy(o -> p); | |
533 lw_expr_destroy(e2); | |
534 o -> p = e1; | |
535 } | |
536 E -> value = lw_expr_oper_plus; | |
537 } | |
538 | |
539 // turn "NEG" into -1(O) - needed for like term collection | |
540 if (E -> type == lw_expr_type_oper && E -> value == lw_expr_oper_neg) | |
541 { | |
542 lw_expr_t e1; | |
543 | |
544 E -> value = lw_expr_oper_times; | |
545 e1 = lw_expr_build(lw_expr_type_int, -1); | |
546 lw_expr_add_operand(E, e1); | |
547 lw_expr_destroy(e1); | |
548 } | |
549 | |
337 | 550 again: |
551 // try to resolve non-constant terms to constants here | |
552 if (E -> type == lw_expr_type_special && evaluate_special) | |
553 { | |
554 lw_expr_t te; | |
555 | |
346
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
556 te = evaluate_special(E -> value, E -> value2, priv); |
431
d7d7e4dca3e7
Eliminated infinite loop on recursive symbol resolution with a Q&D hack: limit the depth that lw_expr_simplify can be called to globally. Not thread friendly.
lost@l-w.ca
parents:
426
diff
changeset
|
557 if (lw_expr_contains(te, E)) |
d7d7e4dca3e7
Eliminated infinite loop on recursive symbol resolution with a Q&D hack: limit the depth that lw_expr_simplify can be called to globally. Not thread friendly.
lost@l-w.ca
parents:
426
diff
changeset
|
558 lw_expr_destroy(te); |
337 | 559 if (te) |
560 { | |
561 for (o = E -> operands; o; o = o -> next) | |
562 lw_expr_destroy(o -> p); | |
563 if (E -> type == lw_expr_type_var) | |
564 lw_free(E -> value2); | |
565 *E = *te; | |
566 E -> operands = NULL; | |
567 | |
568 if (te -> type == lw_expr_type_var) | |
569 E -> value2 = lw_strdup(te -> value2); | |
570 for (o = te -> operands; o; o = o -> next) | |
571 { | |
572 lw_expr_add_operand(E, lw_expr_copy(o -> p)); | |
573 } | |
574 lw_expr_destroy(te); | |
575 goto again; | |
576 } | |
577 return; | |
578 } | |
579 | |
580 if (E -> type == lw_expr_type_var && evaluate_var) | |
581 { | |
582 lw_expr_t te; | |
583 | |
346
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
584 te = evaluate_var(E -> value2, priv); |
431
d7d7e4dca3e7
Eliminated infinite loop on recursive symbol resolution with a Q&D hack: limit the depth that lw_expr_simplify can be called to globally. Not thread friendly.
lost@l-w.ca
parents:
426
diff
changeset
|
585 if (lw_expr_contains(te, E)) |
d7d7e4dca3e7
Eliminated infinite loop on recursive symbol resolution with a Q&D hack: limit the depth that lw_expr_simplify can be called to globally. Not thread friendly.
lost@l-w.ca
parents:
426
diff
changeset
|
586 lw_expr_destroy(te); |
d7d7e4dca3e7
Eliminated infinite loop on recursive symbol resolution with a Q&D hack: limit the depth that lw_expr_simplify can be called to globally. Not thread friendly.
lost@l-w.ca
parents:
426
diff
changeset
|
587 else if (te) |
337 | 588 { |
589 for (o = E -> operands; o; o = o -> next) | |
590 lw_expr_destroy(o -> p); | |
591 if (E -> type == lw_expr_type_var) | |
592 lw_free(E -> value2); | |
593 *E = *te; | |
594 E -> operands = NULL; | |
595 | |
596 if (te -> type == lw_expr_type_var) | |
597 E -> value2 = lw_strdup(te -> value2); | |
598 for (o = te -> operands; o; o = o -> next) | |
599 { | |
600 lw_expr_add_operand(E, lw_expr_copy(o -> p)); | |
601 } | |
602 lw_expr_destroy(te); | |
603 goto again; | |
604 } | |
605 return; | |
606 } | |
607 | |
608 // non-operators have no simplification to do! | |
609 if (E -> type != lw_expr_type_oper) | |
610 return; | |
611 | |
371 | 612 // merge plus operations |
613 if (E -> value == lw_expr_oper_plus) | |
614 { | |
615 lw_expr_t e2; | |
616 | |
617 tryagainplus: | |
618 for (o = E -> operands; o; o = o -> next) | |
619 { | |
620 if (o -> p -> type == lw_expr_type_oper && o -> p -> value == lw_expr_oper_plus) | |
621 { | |
622 struct lw_expr_opers *o2, *o3; | |
623 // we have a + operation - bring operands up | |
624 | |
625 for (o2 = E -> operands; o2 && o2 -> next != o; o2 = o2 -> next) | |
626 /* do nothing */ ; | |
627 if (o2) | |
628 o2 -> next = o -> p -> operands; | |
629 else | |
630 E -> operands = o -> p -> operands; | |
631 for (o2 = o -> p -> operands; o2 -> next; o2 = o2 -> next) | |
632 /* do nothing */ ; | |
633 o2 -> next = o -> next; | |
634 o -> p -> operands = NULL; | |
635 lw_expr_destroy(o -> p); | |
636 lw_free(o); | |
637 goto tryagainplus; | |
638 } | |
639 } | |
640 } | |
641 | |
642 // merge times operations | |
643 if (E -> value == lw_expr_oper_times) | |
644 { | |
645 lw_expr_t e2; | |
646 | |
647 tryagaintimes: | |
648 for (o = E -> operands; o; o = o -> next) | |
649 { | |
650 if (o -> p -> type == lw_expr_type_oper && o -> p -> value == lw_expr_oper_times) | |
651 { | |
652 struct lw_expr_opers *o2, *o3; | |
653 // we have a + operation - bring operands up | |
654 | |
655 for (o2 = E -> operands; o2 && o2 -> next != o; o2 = o2 -> next) | |
656 /* do nothing */ ; | |
657 if (o2) | |
658 o2 -> next = o -> p -> operands; | |
659 else | |
660 E -> operands = o -> p -> operands; | |
661 for (o2 = o -> p -> operands; o2 -> next; o2 = o2 -> next) | |
662 /* do nothing */ ; | |
663 o2 -> next = o -> next; | |
664 o -> p -> operands = NULL; | |
665 lw_expr_destroy(o -> p); | |
666 lw_free(o); | |
667 goto tryagaintimes; | |
668 } | |
669 } | |
670 } | |
335 | 671 |
337 | 672 // simplify operands |
673 for (o = E -> operands; o; o = o -> next) | |
431
d7d7e4dca3e7
Eliminated infinite loop on recursive symbol resolution with a Q&D hack: limit the depth that lw_expr_simplify can be called to globally. Not thread friendly.
lost@l-w.ca
parents:
426
diff
changeset
|
674 lw_expr_simplify_l(o -> p, priv); |
337 | 675 |
676 for (o = E -> operands; o; o = o -> next) | |
677 { | |
678 if (o -> p -> type != lw_expr_type_int) | |
679 break; | |
680 } | |
681 | |
682 if (!o) | |
683 { | |
684 // we can do the operation here! | |
685 int tr = -42424242; | |
686 | |
687 switch (E -> value) | |
688 { | |
689 case lw_expr_oper_neg: | |
690 tr = -(E -> operands -> p -> value); | |
691 break; | |
692 | |
693 case lw_expr_oper_com: | |
694 tr = ~(E -> operands -> p -> value); | |
695 break; | |
696 | |
697 case lw_expr_oper_plus: | |
698 tr = E -> operands -> p -> value; | |
699 for (o = E -> operands -> next; o; o = o -> next) | |
700 tr += o -> p -> value; | |
701 break; | |
702 | |
703 case lw_expr_oper_minus: | |
704 tr = E -> operands -> p -> value; | |
705 for (o = E -> operands -> next; o; o = o -> next) | |
706 tr -= o -> p -> value; | |
707 break; | |
708 | |
709 case lw_expr_oper_times: | |
710 tr = E -> operands -> p -> value; | |
711 for (o = E -> operands -> next; o; o = o -> next) | |
712 tr *= o -> p -> value; | |
713 break; | |
714 | |
715 case lw_expr_oper_divide: | |
716 tr = E -> operands -> p -> value / E -> operands -> next -> p -> value; | |
717 break; | |
718 | |
719 case lw_expr_oper_mod: | |
720 tr = E -> operands -> p -> value % E -> operands -> next -> p -> value; | |
721 break; | |
722 | |
723 case lw_expr_oper_intdiv: | |
724 tr = E -> operands -> p -> value / E -> operands -> next -> p -> value; | |
725 break; | |
726 | |
727 case lw_expr_oper_bwand: | |
728 tr = E -> operands -> p -> value & E -> operands -> next -> p -> value; | |
729 break; | |
730 | |
731 case lw_expr_oper_bwor: | |
732 tr = E -> operands -> p -> value | E -> operands -> next -> p -> value; | |
733 break; | |
734 | |
735 case lw_expr_oper_bwxor: | |
736 tr = E -> operands -> p -> value ^ E -> operands -> next -> p -> value; | |
737 break; | |
738 | |
739 case lw_expr_oper_and: | |
740 tr = E -> operands -> p -> value && E -> operands -> next -> p -> value; | |
741 break; | |
742 | |
743 case lw_expr_oper_or: | |
744 tr = E -> operands -> p -> value || E -> operands -> next -> p -> value; | |
745 break; | |
746 | |
747 } | |
748 | |
749 while (E -> operands) | |
750 { | |
751 o = E -> operands; | |
752 E -> operands = o -> next; | |
753 lw_expr_destroy(o -> p); | |
754 lw_free(o); | |
755 } | |
756 E -> type = lw_expr_type_int; | |
757 E -> value = tr; | |
335 | 758 return; |
337 | 759 } |
335 | 760 |
371 | 761 if (E -> value == lw_expr_oper_plus) |
762 { | |
763 lw_expr_t e1; | |
764 int cval = 0; | |
765 | |
766 e1 = lw_expr_create(); | |
767 e1 -> operands = E -> operands; | |
768 E -> operands = 0; | |
769 | |
770 for (o = e1 -> operands; o; o = o -> next) | |
771 { | |
772 if (o -> p -> type == lw_expr_type_int) | |
773 cval += o -> p -> value; | |
774 else | |
775 lw_expr_add_operand(E, o -> p); | |
776 } | |
777 lw_expr_destroy(e1); | |
778 if (cval) | |
779 { | |
780 e1 = lw_expr_build(lw_expr_type_int, cval); | |
781 lw_expr_add_operand(E, e1); | |
782 lw_expr_destroy(e1); | |
783 } | |
784 } | |
785 | |
786 if (E -> value == lw_expr_oper_times) | |
787 { | |
788 lw_expr_t e1; | |
789 int cval = 1; | |
790 | |
791 e1 = lw_expr_create(); | |
792 e1 -> operands = E -> operands; | |
793 E -> operands = 0; | |
794 | |
795 for (o = e1 -> operands; o; o = o -> next) | |
796 { | |
797 if (o -> p -> type == lw_expr_type_int) | |
798 cval *= o -> p -> value; | |
799 else | |
800 lw_expr_add_operand(E, o -> p); | |
801 } | |
802 lw_expr_destroy(e1); | |
803 if (cval != 1) | |
804 { | |
805 e1 = lw_expr_build(lw_expr_type_int, cval); | |
806 lw_expr_add_operand(E, e1); | |
807 lw_expr_destroy(e1); | |
808 } | |
809 } | |
810 | |
335 | 811 if (E -> value == lw_expr_oper_times) |
812 { | |
813 for (o = E -> operands; o; o = o -> next) | |
814 { | |
815 if (o -> p -> type == lw_expr_type_int && o -> p -> value == 0) | |
816 { | |
817 // one operand of times is 0, replace operation with 0 | |
818 while (E -> operands) | |
819 { | |
820 o = E -> operands; | |
821 E -> operands = o -> next; | |
822 lw_expr_destroy(o -> p); | |
823 lw_free(o); | |
824 } | |
825 E -> type = lw_expr_type_int; | |
826 E -> value = 0; | |
827 return; | |
828 } | |
829 } | |
830 } | |
831 | |
371 | 832 // sort "constants" to the start of each operand list for + and * |
833 if (E -> value == lw_expr_oper_plus || E -> value == lw_expr_oper_times) | |
834 lw_expr_simplify_sortconstfirst(E); | |
835 | |
335 | 836 // look for like terms and collect them together |
837 if (E -> value == lw_expr_oper_plus) | |
838 { | |
371 | 839 struct lw_expr_opers *o2; |
335 | 840 for (o = E -> operands; o; o = o -> next) |
841 { | |
371 | 842 // skip constants |
843 if (o -> p -> type == lw_expr_type_int) | |
844 continue; | |
845 | |
846 // we have a term to match | |
847 // (o -> p) is first term | |
848 for (o2 = o -> next; o2; o2 = o2 -> next) | |
335 | 849 { |
371 | 850 lw_expr_t e1, e2; |
335 | 851 |
371 | 852 if (o2 -> p -> type == lw_expr_type_int) |
853 continue; | |
854 | |
855 if (lw_expr_simplify_isliketerm(o -> p, o2 -> p)) | |
335 | 856 { |
371 | 857 int coef, coef2; |
858 | |
859 // we have a like term here | |
860 // do something about it | |
861 if (o -> p -> type == lw_expr_type_oper && o -> p -> value == lw_expr_oper_times) | |
862 { | |
863 if (o -> p -> operands -> p -> type == lw_expr_type_int) | |
864 coef = o -> p -> operands -> p -> value; | |
865 else | |
866 coef = 1; | |
867 } | |
868 else | |
869 coef = 1; | |
335 | 870 if (o2 -> p -> type == lw_expr_type_oper && o2 -> p -> value == lw_expr_oper_times) |
871 { | |
371 | 872 if (o2 -> p -> operands -> p -> type == lw_expr_type_int) |
873 coef2 = o2 -> p -> operands -> p -> value; | |
874 else | |
875 coef2 = 1; | |
335 | 876 } |
371 | 877 else |
878 coef2 = 1; | |
879 coef += coef2; | |
880 e1 = lw_expr_create(); | |
881 e1 -> type = lw_expr_type_oper; | |
882 e1 -> value = lw_expr_oper_times; | |
883 if (coef != 1) | |
884 { | |
885 e2 = lw_expr_build(lw_expr_type_int, coef); | |
886 lw_expr_add_operand(e1, e2); | |
887 lw_expr_destroy(e2); | |
888 } | |
889 lw_expr_destroy(o -> p); | |
890 o -> p = e1; | |
891 for (o = o2 -> p -> operands; o; o = o -> next) | |
892 { | |
893 if (o -> p -> type == lw_expr_type_int) | |
894 continue; | |
895 lw_expr_add_operand(e1, o -> p); | |
896 } | |
897 lw_expr_destroy(o2 -> p); | |
898 o2 -> p = lw_expr_build(lw_expr_type_int, 0); | |
899 goto again; | |
335 | 900 } |
901 } | |
902 } | |
903 } | |
904 | |
905 | |
906 if (E -> value == lw_expr_oper_plus) | |
907 { | |
908 int c = 0, t = 0; | |
909 for (o = E -> operands; o; o = o -> next) | |
910 { | |
911 t++; | |
912 if (!(o -> p -> type == lw_expr_type_int && o -> p -> value == 0)) | |
913 { | |
914 c++; | |
915 } | |
916 } | |
917 if (c == 1) | |
918 { | |
919 lw_expr_t r; | |
920 // find the value and "move it up" | |
921 while (E -> operands) | |
922 { | |
923 o = E -> operands; | |
924 if (o -> p -> type != lw_expr_type_int || o -> p -> value != 0) | |
925 { | |
337 | 926 r = lw_expr_copy(o -> p); |
335 | 927 } |
928 E -> operands = o -> next; | |
929 lw_expr_destroy(o -> p); | |
930 lw_free(o); | |
931 } | |
932 *E = *r; | |
933 return; | |
934 } | |
935 else if (c == 0) | |
936 { | |
937 // replace with 0 | |
938 while (E -> operands) | |
939 { | |
940 o = E -> operands; | |
941 E -> operands = o -> next; | |
942 lw_expr_destroy(o -> p); | |
943 lw_free(o); | |
944 } | |
945 E -> type = lw_expr_type_int; | |
946 E -> value = 0; | |
947 return; | |
948 } | |
949 else if (c != t) | |
950 { | |
951 // collapse out zero terms | |
952 struct lw_expr_opers *o2; | |
953 | |
954 for (o = E -> operands; o; o = o -> next) | |
955 { | |
956 if (o -> p -> type == lw_expr_type_int && o -> p -> value == 0) | |
957 { | |
958 if (o == E -> operands) | |
959 { | |
960 E -> operands = o -> next; | |
961 lw_expr_destroy(o -> p); | |
962 lw_free(o); | |
963 o = E -> operands; | |
964 } | |
965 else | |
966 { | |
967 for (o2 = E -> operands; o2 -> next == o; o2 = o2 -> next) | |
968 /* do nothing */ ; | |
969 o2 -> next = o -> next; | |
970 lw_expr_destroy(o -> p); | |
971 lw_free(o); | |
972 o = o2; | |
973 } | |
974 } | |
975 } | |
976 } | |
977 return; | |
978 } | |
387
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
979 |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
980 /* handle <int> times <plus> - expand the terms - only with exactly two operands */ |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
981 if (E -> value == lw_expr_oper_times) |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
982 { |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
983 lw_expr_t t1; |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
984 lw_expr_t E2; |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
985 lw_expr_t E3; |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
986 if (E -> operands && E -> operands -> next && !(E -> operands -> next -> next)) |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
987 { |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
988 if (E -> operands -> p -> type == lw_expr_type_int) |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
989 { |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
990 /* <int> TIMES <other> */ |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
991 E2 = E -> operands -> next -> p; |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
992 E3 = E -> operands -> p; |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
993 if (E2 -> type == lw_expr_type_oper && E2 -> value == lw_expr_oper_plus) |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
994 { |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
995 lw_free(E -> operands -> next); |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
996 lw_free(E -> operands); |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
997 E -> operands = NULL; |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
998 E -> value = lw_expr_oper_plus; |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
999 |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
1000 for (o = E2 -> operands; o; o = o -> next) |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
1001 { |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
1002 t1 = lw_expr_build(lw_expr_type_oper, lw_expr_oper_times, E3, o -> p); |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
1003 lw_expr_add_operand(E, t1); |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
1004 } |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
1005 |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
1006 lw_expr_destroy(E2); |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
1007 lw_expr_destroy(E3); |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
1008 } |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
1009 } |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
1010 else if (E -> operands -> next -> p -> type == lw_expr_type_int) |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
1011 { |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
1012 /* <other> TIMES <int> */ |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
1013 E2 = E -> operands -> p; |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
1014 E3 = E -> operands -> next -> p; |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
1015 if (E2 -> type == lw_expr_type_oper && E2 -> value == lw_expr_oper_plus) |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
1016 { |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
1017 lw_free(E -> operands -> next); |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
1018 lw_free(E -> operands); |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
1019 E -> operands = NULL; |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
1020 E -> value = lw_expr_oper_plus; |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
1021 |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
1022 for (o = E2 -> operands; o; o = o -> next) |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
1023 { |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
1024 t1 = lw_expr_build(lw_expr_type_oper, lw_expr_oper_times, E3, o -> p); |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
1025 lw_expr_add_operand(E, t1); |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
1026 } |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
1027 |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
1028 lw_expr_destroy(E2); |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
1029 lw_expr_destroy(E3); |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
1030 } |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
1031 } |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
1032 } |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
1033 } |
335 | 1034 } |
346
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1035 |
431
d7d7e4dca3e7
Eliminated infinite loop on recursive symbol resolution with a Q&D hack: limit the depth that lw_expr_simplify can be called to globally. Not thread friendly.
lost@l-w.ca
parents:
426
diff
changeset
|
1036 void lw_expr_simplify_l(lw_expr_t E, void *priv) |
387
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
1037 { |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
1038 lw_expr_t te; |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
1039 int c; |
431
d7d7e4dca3e7
Eliminated infinite loop on recursive symbol resolution with a Q&D hack: limit the depth that lw_expr_simplify can be called to globally. Not thread friendly.
lost@l-w.ca
parents:
426
diff
changeset
|
1040 |
d7d7e4dca3e7
Eliminated infinite loop on recursive symbol resolution with a Q&D hack: limit the depth that lw_expr_simplify can be called to globally. Not thread friendly.
lost@l-w.ca
parents:
426
diff
changeset
|
1041 (level)++; |
d7d7e4dca3e7
Eliminated infinite loop on recursive symbol resolution with a Q&D hack: limit the depth that lw_expr_simplify can be called to globally. Not thread friendly.
lost@l-w.ca
parents:
426
diff
changeset
|
1042 // bail out if the level gets too deep |
d7d7e4dca3e7
Eliminated infinite loop on recursive symbol resolution with a Q&D hack: limit the depth that lw_expr_simplify can be called to globally. Not thread friendly.
lost@l-w.ca
parents:
426
diff
changeset
|
1043 if (level >= 500 || bailing) |
d7d7e4dca3e7
Eliminated infinite loop on recursive symbol resolution with a Q&D hack: limit the depth that lw_expr_simplify can be called to globally. Not thread friendly.
lost@l-w.ca
parents:
426
diff
changeset
|
1044 { |
d7d7e4dca3e7
Eliminated infinite loop on recursive symbol resolution with a Q&D hack: limit the depth that lw_expr_simplify can be called to globally. Not thread friendly.
lost@l-w.ca
parents:
426
diff
changeset
|
1045 bailing = 1; |
d7d7e4dca3e7
Eliminated infinite loop on recursive symbol resolution with a Q&D hack: limit the depth that lw_expr_simplify can be called to globally. Not thread friendly.
lost@l-w.ca
parents:
426
diff
changeset
|
1046 level--; |
d7d7e4dca3e7
Eliminated infinite loop on recursive symbol resolution with a Q&D hack: limit the depth that lw_expr_simplify can be called to globally. Not thread friendly.
lost@l-w.ca
parents:
426
diff
changeset
|
1047 if (level == 0) |
d7d7e4dca3e7
Eliminated infinite loop on recursive symbol resolution with a Q&D hack: limit the depth that lw_expr_simplify can be called to globally. Not thread friendly.
lost@l-w.ca
parents:
426
diff
changeset
|
1048 bailing = 0; |
d7d7e4dca3e7
Eliminated infinite loop on recursive symbol resolution with a Q&D hack: limit the depth that lw_expr_simplify can be called to globally. Not thread friendly.
lost@l-w.ca
parents:
426
diff
changeset
|
1049 return; |
d7d7e4dca3e7
Eliminated infinite loop on recursive symbol resolution with a Q&D hack: limit the depth that lw_expr_simplify can be called to globally. Not thread friendly.
lost@l-w.ca
parents:
426
diff
changeset
|
1050 } |
387
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
1051 do |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
1052 { |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
1053 te = lw_expr_copy(E); |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
1054 lw_expr_simplify_go(E, priv); |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
1055 c = 0; |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
1056 if (lw_expr_compare(te, E) == 0) |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
1057 c = 1; |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
1058 lw_expr_destroy(te); |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
1059 } |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
1060 while (c); |
431
d7d7e4dca3e7
Eliminated infinite loop on recursive symbol resolution with a Q&D hack: limit the depth that lw_expr_simplify can be called to globally. Not thread friendly.
lost@l-w.ca
parents:
426
diff
changeset
|
1061 (level)--; |
387
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
1062 } |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
1063 |
431
d7d7e4dca3e7
Eliminated infinite loop on recursive symbol resolution with a Q&D hack: limit the depth that lw_expr_simplify can be called to globally. Not thread friendly.
lost@l-w.ca
parents:
426
diff
changeset
|
1064 void lw_expr_simplify(lw_expr_t E, void *priv) |
d7d7e4dca3e7
Eliminated infinite loop on recursive symbol resolution with a Q&D hack: limit the depth that lw_expr_simplify can be called to globally. Not thread friendly.
lost@l-w.ca
parents:
426
diff
changeset
|
1065 { |
d7d7e4dca3e7
Eliminated infinite loop on recursive symbol resolution with a Q&D hack: limit the depth that lw_expr_simplify can be called to globally. Not thread friendly.
lost@l-w.ca
parents:
426
diff
changeset
|
1066 lw_expr_simplify_l(E, priv); |
d7d7e4dca3e7
Eliminated infinite loop on recursive symbol resolution with a Q&D hack: limit the depth that lw_expr_simplify can be called to globally. Not thread friendly.
lost@l-w.ca
parents:
426
diff
changeset
|
1067 } |
387
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
382
diff
changeset
|
1068 |
346
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1069 /* |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1070 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1071 The following two functions are co-routines which evaluate an infix |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1072 expression. lw_expr_parse_term checks for unary prefix operators then, if |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1073 none found, passes the string off the the defined helper function to |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1074 determine what the term really is. It also handles parentheses. |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1075 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1076 lw_expr_parse_expr evaluates actual expressions with infix operators. It |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1077 respects the order of operations. |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1078 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1079 The end of an expression is determined by the presence of any of the |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1080 following conditions: |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1081 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1082 1. a NUL character |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1083 2. a whitespace character |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1084 3. a ) |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1085 4. a , |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1086 5. any character that is not recognized as a term |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1087 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1088 lw_expr_parse_term returns NULL if there is no term (end of expr, etc.) |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1089 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1090 lw_expr_parse_expr returns NULL if there is no expression or on a syntax |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1091 error. |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1092 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1093 */ |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1094 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1095 lw_expr_t lw_expr_parse_expr(char **p, void *priv, int prec); |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1096 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1097 lw_expr_t lw_expr_parse_term(char **p, void *priv) |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1098 { |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1099 lw_expr_t term, term2; |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1100 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1101 eval_next: |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1102 if (!**p || isspace(**p) || **p == ')' || **p == ']') |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1103 return NULL; |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1104 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1105 // parentheses |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1106 if (**p == '(') |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1107 { |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1108 (*p)++; |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1109 term = lw_expr_parse_expr(p, priv, 0); |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1110 if (**p != ')') |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1111 { |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1112 lw_expr_destroy(term); |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1113 return NULL; |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1114 } |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1115 (*p)++; |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1116 return term; |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1117 } |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1118 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1119 // unary + |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1120 if (**p == '+') |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1121 { |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1122 (*p)++; |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1123 goto eval_next; |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1124 } |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1125 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1126 // unary - (prec 200) |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1127 if (**p == '-') |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1128 { |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1129 (*p)++; |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1130 term = lw_expr_parse_expr(p, priv, 200); |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1131 if (!term) |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1132 return NULL; |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1133 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1134 term2 = lw_expr_build(lw_expr_type_oper, lw_expr_oper_neg, term); |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1135 lw_expr_destroy(term); |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1136 return term2; |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1137 } |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1138 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1139 // unary ^ or ~ (complement, prec 200) |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1140 if (**p == '^' || **p == '~') |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1141 { |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1142 (*p)++; |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1143 term = lw_expr_parse_expr(p, priv, 200); |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1144 if (!term) |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1145 return NULL; |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1146 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1147 term2 = lw_expr_build(lw_expr_type_oper, lw_expr_oper_com, term); |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1148 lw_expr_destroy(term); |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1149 return term2; |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1150 } |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1151 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1152 // non-operator - pass to caller |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1153 return parse_term(p, priv); |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1154 } |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1155 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1156 lw_expr_t lw_expr_parse_expr(char **p, void *priv, int prec) |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1157 { |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1158 static const struct operinfo |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1159 { |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1160 int opernum; |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1161 char *operstr; |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1162 int operprec; |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1163 } operators[] = |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1164 { |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1165 { lw_expr_oper_plus, "+", 100 }, |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1166 { lw_expr_oper_minus, "-", 100 }, |
443 | 1167 { lw_expr_oper_times, "*", 150 }, |
346
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1168 { lw_expr_oper_divide, "/", 150 }, |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1169 { lw_expr_oper_mod, "%", 150 }, |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1170 { lw_expr_oper_intdiv, "\\", 150 }, |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1171 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1172 { lw_expr_oper_and, "&&", 25 }, |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1173 { lw_expr_oper_or, "||", 25 }, |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1174 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1175 { lw_expr_oper_bwand, "&", 50 }, |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1176 { lw_expr_oper_bwor, "|", 50 }, |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1177 { lw_expr_oper_bwxor, "^", 50 }, |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1178 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1179 { lw_expr_oper_none, "", 0 } |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1180 }; |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1181 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1182 int opern, i; |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1183 lw_expr_t term1, term2, term3; |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1184 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1185 if (!**p || isspace(**p) || **p == ')' || **p == ',' || **p == ']') |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1186 return NULL; |
370 | 1187 |
346
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1188 term1 = lw_expr_parse_term(p, priv); |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1189 if (!term1) |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1190 return NULL; |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1191 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1192 eval_next: |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1193 if (!**p || isspace(**p) || **p == ')' || **p == ',' || **p == ']') |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1194 return term1; |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1195 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1196 // expecting an operator here |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1197 for (opern = 0; operators[opern].opernum != lw_expr_oper_none; opern++) |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1198 { |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1199 for (i = 0; (*p)[i] && operators[opern].operstr[i] && ((*p)[i] == operators[opern].operstr[i]); i++) |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1200 /* do nothing */; |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1201 if (operators[opern].operstr[i] == '\0') |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1202 break; |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1203 } |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1204 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1205 if (operators[opern].opernum == lw_expr_oper_none) |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1206 { |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1207 // unrecognized operator |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1208 lw_expr_destroy(term1); |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1209 return NULL; |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1210 } |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1211 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1212 // operator number is in opern, length of oper in i |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1213 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1214 // logic: |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1215 // if the precedence of this operation is <= to the "prec" flag, |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1216 // we simply return without advancing the input pointer; the operator |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1217 // will be evaluated again in the enclosing function call |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1218 if (operators[opern].operprec <= prec) |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1219 return term1; |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1220 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1221 // logic: |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1222 // we have a higher precedence operator here so we will advance the |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1223 // input pointer to the next term and let the expression evaluator |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1224 // loose on it after which time we will push our operator onto the |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1225 // stack and then go on with the expression evaluation |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1226 (*p) += i; |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1227 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1228 // evaluate next expression(s) of higher precedence |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1229 term2 = lw_expr_parse_expr(p, priv, operators[opern].operprec); |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1230 if (!term2) |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1231 { |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1232 lw_expr_destroy(term1); |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1233 return NULL; |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1234 } |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1235 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1236 // now create operator |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1237 term3 = lw_expr_build(lw_expr_type_oper, operators[opern].opernum, term1, term2); |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1238 lw_expr_destroy(term1); |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1239 lw_expr_destroy(term2); |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1240 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1241 // the new "expression" is the next "left operand" |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1242 term1 = term3; |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1243 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1244 // continue evaluating |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1245 goto eval_next; |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1246 } |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1247 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1248 lw_expr_t lw_expr_parse(char **p, void *priv) |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1249 { |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1250 return lw_expr_parse_expr(p, priv, 0); |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
1251 } |
367 | 1252 |
1253 int lw_expr_testterms(lw_expr_t e, lw_expr_testfn_t *fn, void *priv) | |
1254 { | |
1255 struct lw_expr_opers *o; | |
1256 int r; | |
1257 | |
1258 for (o = e -> operands; o; o = o -> next) | |
1259 { | |
1260 r = lw_expr_testterms(o -> p, fn, priv); | |
1261 if (r) | |
1262 return r; | |
1263 } | |
1264 return (fn)(e, priv); | |
1265 } | |
376 | 1266 |
1267 int lw_expr_type(lw_expr_t e) | |
1268 { | |
1269 return e -> type; | |
1270 } | |
1271 | |
1272 void *lw_expr_specptr(lw_expr_t e) | |
1273 { | |
1274 return e -> value2; | |
1275 } |