Mercurial > hg-old > index.cgi
annotate lwlib/lw_expr.c @ 367:34dfc9747f23
Reduction passes complete
author | lost@starbug |
---|---|
date | Thu, 15 Apr 2010 21:56:06 -0600 |
parents | 1649bc7bda5a |
children | 6b33faa21a0a |
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 |
347 | 38 int lw_expr_istype(lw_expr_t e, int t) |
39 { | |
40 if (e -> type == t) | |
41 return 1; | |
42 return 0; | |
43 } | |
44 | |
45 int lw_expr_intval(lw_expr_t e) | |
46 { | |
47 if (e -> type == lw_expr_type_int) | |
48 return e -> value; | |
49 return -1; | |
50 } | |
51 | |
367 | 52 int lw_expr_specint(lw_expr_t e) |
53 { | |
54 if (e -> type == lw_expr_type_special) | |
55 return e -> value; | |
56 return -1; | |
57 } | |
58 | |
346
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
59 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
|
60 { |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
61 parse_term = fn; |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
62 } |
337 | 63 |
342 | 64 void lw_expr_set_special_handler(lw_expr_fn_t *fn) |
337 | 65 { |
66 evaluate_special = fn; | |
67 } | |
68 | |
342 | 69 void lw_expr_set_var_handler(lw_expr_fn2_t *fn) |
337 | 70 { |
71 evaluate_var = fn; | |
72 } | |
73 | |
334 | 74 lw_expr_t lw_expr_create(void) |
75 { | |
76 lw_expr_t r; | |
77 | |
78 r = lw_alloc(sizeof(struct lw_expr_priv)); | |
79 r -> operands = NULL; | |
80 | |
81 return r; | |
82 } | |
83 | |
84 void lw_expr_destroy(lw_expr_t E) | |
85 { | |
337 | 86 struct lw_expr_opers *o; |
87 for (o = E -> operands; o; o = o -> next) | |
88 lw_expr_destroy(o -> p); | |
89 if (E -> type == lw_expr_type_var) | |
90 lw_free(E -> value2); | |
91 lw_free(E); | |
334 | 92 } |
93 | |
337 | 94 /* actually duplicates the entire expression */ |
95 void lw_expr_add_operand(lw_expr_t E, lw_expr_t O); | |
334 | 96 lw_expr_t lw_expr_copy(lw_expr_t E) |
97 { | |
337 | 98 lw_expr_t r, t; |
99 struct lw_expr_opers *o; | |
100 | |
101 r = lw_alloc(sizeof(struct lw_expr_priv)); | |
102 *r = *E; | |
103 r -> operands = NULL; | |
104 | |
105 if (E -> type == lw_expr_type_var) | |
106 r -> value2 = lw_strdup(E -> value2); | |
107 for (o = E -> operands; o; o = o -> next) | |
108 { | |
109 lw_expr_add_operand(r, lw_expr_copy(o -> p)); | |
110 } | |
111 | |
112 return r; | |
334 | 113 } |
114 | |
115 void lw_expr_add_operand(lw_expr_t E, lw_expr_t O) | |
116 { | |
117 struct lw_expr_opers *o, *t; | |
118 | |
119 o = lw_alloc(sizeof(struct lw_expr_opers)); | |
120 o -> p = lw_expr_copy(O); | |
121 o -> next = NULL; | |
122 for (t = E -> operands; t && t -> next; t = t -> next) | |
123 /* do nothing */ ; | |
124 | |
125 if (t) | |
126 t -> next = o; | |
127 else | |
128 E -> operands = o; | |
129 } | |
130 | |
335 | 131 lw_expr_t lw_expr_build_aux(int exprtype, va_list args) |
334 | 132 { |
133 lw_expr_t r; | |
134 int t; | |
135 void *p; | |
136 | |
137 lw_expr_t te1, te2; | |
138 | |
139 r = lw_expr_create(); | |
140 | |
141 switch (exprtype) | |
142 { | |
143 case lw_expr_type_int: | |
144 t = va_arg(args, int); | |
145 r -> type = lw_expr_type_int; | |
146 r -> value = t; | |
147 break; | |
148 | |
149 case lw_expr_type_var: | |
150 p = va_arg(args, char *); | |
151 r -> type = lw_expr_type_var; | |
152 r -> value2 = lw_strdup(p); | |
153 break; | |
154 | |
155 case lw_expr_type_special: | |
156 t = va_arg(args, int); | |
157 p = va_arg(args, char *); | |
158 r -> type = lw_expr_type_special; | |
337 | 159 r -> value = t; |
334 | 160 r -> value2 = p; |
161 break; | |
162 | |
163 case lw_expr_type_oper: | |
164 t = va_arg(args, int); | |
165 te1 = va_arg(args, lw_expr_t); | |
166 if (t != lw_expr_oper_com && t != lw_expr_oper_neg) | |
167 te2 = va_arg(args, lw_expr_t); | |
168 else | |
169 te2 = NULL; | |
170 | |
171 r -> type = lw_expr_type_oper; | |
172 r -> value = t; | |
173 lw_expr_add_operand(r, te1); | |
174 lw_expr_add_operand(r, te2); | |
175 break; | |
176 | |
177 default: | |
178 lw_error("Invalid expression type specified to lw_expr_build"); | |
179 } | |
180 | |
335 | 181 return r; |
182 } | |
183 | |
184 lw_expr_t lw_expr_build(int exprtype, ...) | |
185 { | |
186 va_list args; | |
187 lw_expr_t r; | |
188 | |
189 va_start(args, exprtype); | |
190 r = lw_expr_build_aux(exprtype, args); | |
191 va_end(args); | |
192 return r; | |
193 } | |
194 | |
334 | 195 void lw_expr_print(lw_expr_t E) |
196 { | |
197 struct lw_expr_opers *o; | |
335 | 198 int c = 0; |
199 | |
334 | 200 for (o = E -> operands; o; o = o -> next) |
201 { | |
335 | 202 c++; |
334 | 203 lw_expr_print(o -> p); |
204 } | |
205 | |
206 switch (E -> type) | |
207 { | |
208 case lw_expr_type_int: | |
209 printf("%d ", E -> value); | |
210 break; | |
335 | 211 |
212 case lw_expr_type_var: | |
213 printf("V(%s) ", (char *)(E -> value2)); | |
214 break; | |
215 | |
216 case lw_expr_type_special: | |
217 printf("S(%d,%p) ", E -> value, E -> value2); | |
218 break; | |
219 | |
334 | 220 case lw_expr_type_oper: |
335 | 221 printf("[%d]", c); |
334 | 222 switch (E -> value) |
223 { | |
224 case lw_expr_oper_plus: | |
225 printf("+ "); | |
226 break; | |
227 | |
228 case lw_expr_oper_minus: | |
229 printf("- "); | |
230 break; | |
231 | |
232 case lw_expr_oper_times: | |
233 printf("* "); | |
234 break; | |
235 | |
236 case lw_expr_oper_divide: | |
237 printf("/ "); | |
238 break; | |
239 | |
240 case lw_expr_oper_mod: | |
241 printf("%% "); | |
242 break; | |
243 | |
244 case lw_expr_oper_intdiv: | |
245 printf("\\ "); | |
246 break; | |
247 | |
248 case lw_expr_oper_bwand: | |
249 printf("BWAND "); | |
250 break; | |
251 | |
252 case lw_expr_oper_bwor: | |
253 printf("BWOR "); | |
254 break; | |
255 | |
256 case lw_expr_oper_bwxor: | |
257 printf("BWXOR "); | |
258 break; | |
259 | |
260 case lw_expr_oper_and: | |
261 printf("AND "); | |
262 break; | |
263 | |
264 case lw_expr_oper_or: | |
265 printf("OR "); | |
266 break; | |
267 | |
268 case lw_expr_oper_neg: | |
269 printf("NEG "); | |
270 break; | |
271 | |
272 case lw_expr_oper_com: | |
273 printf("COM "); | |
274 break; | |
275 | |
276 default: | |
277 printf("OPER "); | |
278 break; | |
279 } | |
280 break; | |
281 default: | |
282 printf("ERR "); | |
283 break; | |
284 } | |
285 } | |
286 | |
287 /* | |
288 Return: | |
289 nonzero if expressions are the same (identical pointers or matching values) | |
290 zero if expressions are not the same | |
291 | |
292 */ | |
293 int lw_expr_compare(lw_expr_t E1, lw_expr_t E2) | |
294 { | |
295 struct lw_expr_opers *o1, *o2; | |
296 | |
297 if (E1 == E2) | |
298 return 1; | |
299 | |
300 if (!(E1 -> type == E2 -> type && E1 -> value == E2 -> value)) | |
301 return 0; | |
302 | |
303 if (E1 -> type == lw_expr_type_var) | |
304 { | |
305 if (!strcmp(E1 -> value2, E2 -> value2)) | |
306 return 1; | |
307 else | |
308 return 0; | |
309 } | |
310 | |
311 if (E1 -> type == lw_expr_type_special) | |
312 { | |
313 if (E1 -> value2 == E2 -> value2) | |
314 return 1; | |
315 else | |
316 return 0; | |
317 } | |
318 | |
319 for (o1 = E1 -> operands, o2 = E2 -> operands; o1 && o2; o1 = o1 -> next, o2 = o2 -> next) | |
320 if (lw_expr_compare(o1 -> p, o2 -> p) == 0) | |
321 return 0; | |
322 if (o1 || o2) | |
323 return 0; | |
324 | |
325 return 1; | |
326 } | |
327 | |
328 /* return true if E is an operator of type oper */ | |
329 int lw_expr_isoper(lw_expr_t E, int oper) | |
330 { | |
331 if (E -> type == lw_expr_type_oper && E -> value == oper) | |
332 return 1; | |
333 return 0; | |
334 } | |
335 | 335 |
336 | |
337 void lw_expr_simplify_sortconstfirst(lw_expr_t E) | |
338 { | |
339 struct lw_expr_opers *o; | |
340 | |
341 for (o = E -> operands; o; o = o -> next) | |
342 lw_expr_simplify_sortconstfirst(o -> p); | |
343 | |
344 for (o = E -> operands; o; o = o -> next) | |
345 { | |
346 if (o -> p -> type == lw_expr_type_int && o != E -> operands) | |
347 { | |
348 struct lw_expr_opers *o2; | |
349 for (o2 = E -> operands; o2 -> next != o; o2 = o2 -> next) | |
350 /* do nothing */ ; | |
351 o2 -> next = o -> next; | |
352 o -> next = E -> operands; | |
353 E -> operands = o; | |
354 o = o2; | |
355 } | |
356 } | |
357 } | |
358 | |
336 | 359 void lw_expr_sortoperandlist(struct lw_expr_opers **o) |
360 { | |
361 fprintf(stderr, "lw_expr_sortoperandlist() not yet implemented\n"); | |
362 } | |
363 | |
335 | 364 // return 1 if the operand lists match, 0 if not |
365 // may re-order the argument lists | |
366 int lw_expr_simplify_compareoperandlist(struct lw_expr_opers **ol1, struct lw_expr_opers **ol2) | |
367 { | |
368 struct lw_expr_opers *o1, *o2; | |
369 | |
370 lw_expr_sortoperandlist(ol1); | |
371 lw_expr_sortoperandlist(ol2); | |
372 | |
373 for (o1 = *ol1, o2 = *ol2; o1 && o2; o1 = o1 -> next, o2 = o2 -> next) | |
374 { | |
375 if (!lw_expr_compare(o1 -> p, o2 -> p)) | |
376 return 0; | |
377 } | |
378 if (o1 || o2) | |
379 return 0; | |
380 return 1; | |
381 } | |
382 | |
346
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
383 void lw_expr_simplify(lw_expr_t E, void *priv) |
335 | 384 { |
385 struct lw_expr_opers *o; | |
386 | |
337 | 387 again: |
388 // try to resolve non-constant terms to constants here | |
389 if (E -> type == lw_expr_type_special && evaluate_special) | |
390 { | |
391 lw_expr_t te; | |
392 | |
346
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
393 te = evaluate_special(E -> value, E -> value2, priv); |
337 | 394 if (te) |
395 { | |
396 for (o = E -> operands; o; o = o -> next) | |
397 lw_expr_destroy(o -> p); | |
398 if (E -> type == lw_expr_type_var) | |
399 lw_free(E -> value2); | |
400 *E = *te; | |
401 E -> operands = NULL; | |
402 | |
403 if (te -> type == lw_expr_type_var) | |
404 E -> value2 = lw_strdup(te -> value2); | |
405 for (o = te -> operands; o; o = o -> next) | |
406 { | |
407 lw_expr_add_operand(E, lw_expr_copy(o -> p)); | |
408 } | |
409 lw_expr_destroy(te); | |
410 goto again; | |
411 } | |
412 return; | |
413 } | |
414 | |
415 if (E -> type == lw_expr_type_var && evaluate_var) | |
416 { | |
417 lw_expr_t te; | |
418 | |
346
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
419 te = evaluate_var(E -> value2, priv); |
337 | 420 if (te) |
421 { | |
422 for (o = E -> operands; o; o = o -> next) | |
423 lw_expr_destroy(o -> p); | |
424 if (E -> type == lw_expr_type_var) | |
425 lw_free(E -> value2); | |
426 *E = *te; | |
427 E -> operands = NULL; | |
428 | |
429 if (te -> type == lw_expr_type_var) | |
430 E -> value2 = lw_strdup(te -> value2); | |
431 for (o = te -> operands; o; o = o -> next) | |
432 { | |
433 lw_expr_add_operand(E, lw_expr_copy(o -> p)); | |
434 } | |
435 lw_expr_destroy(te); | |
436 goto again; | |
437 } | |
438 return; | |
439 } | |
440 | |
441 // non-operators have no simplification to do! | |
442 if (E -> type != lw_expr_type_oper) | |
443 return; | |
444 | |
335 | 445 // sort "constants" to the start of each operand list for + and * |
446 lw_expr_simplify_sortconstfirst(E); | |
447 | |
337 | 448 // simplify operands |
449 for (o = E -> operands; o; o = o -> next) | |
346
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
450 lw_expr_simplify(o -> p, priv); |
337 | 451 |
452 for (o = E -> operands; o; o = o -> next) | |
453 { | |
454 if (o -> p -> type != lw_expr_type_int) | |
455 break; | |
456 } | |
457 | |
458 if (!o) | |
459 { | |
460 // we can do the operation here! | |
461 int tr = -42424242; | |
462 | |
463 switch (E -> value) | |
464 { | |
465 case lw_expr_oper_neg: | |
466 tr = -(E -> operands -> p -> value); | |
467 break; | |
468 | |
469 case lw_expr_oper_com: | |
470 tr = ~(E -> operands -> p -> value); | |
471 break; | |
472 | |
473 case lw_expr_oper_plus: | |
474 tr = E -> operands -> p -> value; | |
475 for (o = E -> operands -> next; o; o = o -> next) | |
476 tr += o -> p -> value; | |
477 break; | |
478 | |
479 case lw_expr_oper_minus: | |
480 tr = E -> operands -> p -> value; | |
481 for (o = E -> operands -> next; o; o = o -> next) | |
482 tr -= o -> p -> value; | |
483 break; | |
484 | |
485 case lw_expr_oper_times: | |
486 tr = E -> operands -> p -> value; | |
487 for (o = E -> operands -> next; o; o = o -> next) | |
488 tr *= o -> p -> value; | |
489 break; | |
490 | |
491 case lw_expr_oper_divide: | |
492 tr = E -> operands -> p -> value / E -> operands -> next -> p -> value; | |
493 break; | |
494 | |
495 case lw_expr_oper_mod: | |
496 tr = E -> operands -> p -> value % E -> operands -> next -> p -> value; | |
497 break; | |
498 | |
499 case lw_expr_oper_intdiv: | |
500 tr = E -> operands -> p -> value / E -> operands -> next -> p -> value; | |
501 break; | |
502 | |
503 case lw_expr_oper_bwand: | |
504 tr = E -> operands -> p -> value & E -> operands -> next -> p -> value; | |
505 break; | |
506 | |
507 case lw_expr_oper_bwor: | |
508 tr = E -> operands -> p -> value | E -> operands -> next -> p -> value; | |
509 break; | |
510 | |
511 case lw_expr_oper_bwxor: | |
512 tr = E -> operands -> p -> value ^ E -> operands -> next -> p -> value; | |
513 break; | |
514 | |
515 case lw_expr_oper_and: | |
516 tr = E -> operands -> p -> value && E -> operands -> next -> p -> value; | |
517 break; | |
518 | |
519 case lw_expr_oper_or: | |
520 tr = E -> operands -> p -> value || E -> operands -> next -> p -> value; | |
521 break; | |
522 | |
523 } | |
524 | |
525 while (E -> operands) | |
526 { | |
527 o = E -> operands; | |
528 E -> operands = o -> next; | |
529 lw_expr_destroy(o -> p); | |
530 lw_free(o); | |
531 } | |
532 E -> type = lw_expr_type_int; | |
533 E -> value = tr; | |
335 | 534 return; |
337 | 535 } |
335 | 536 |
537 if (E -> value == lw_expr_oper_times) | |
538 { | |
539 for (o = E -> operands; o; o = o -> next) | |
540 { | |
541 if (o -> p -> type == lw_expr_type_int && o -> p -> value == 0) | |
542 { | |
543 // one operand of times is 0, replace operation with 0 | |
544 while (E -> operands) | |
545 { | |
546 o = E -> operands; | |
547 E -> operands = o -> next; | |
548 lw_expr_destroy(o -> p); | |
549 lw_free(o); | |
550 } | |
551 E -> type = lw_expr_type_int; | |
552 E -> value = 0; | |
553 return; | |
554 } | |
555 } | |
556 } | |
557 | |
558 // look for like terms and collect them together | |
559 if (E -> value == lw_expr_oper_plus) | |
560 { | |
561 for (o = E -> operands; o; o = o -> next) | |
562 { | |
563 if (o -> p -> type == lw_expr_type_oper && o -> p -> value == lw_expr_oper_times) | |
564 { | |
565 // we have a "times" here | |
566 // find first non-const operand | |
567 struct lw_expr_opers *op1, *op2, *o2; | |
568 for (op1 = o -> p -> operands; op1; op1 = op1 -> next) | |
569 if (op1 -> p -> type != lw_expr_type_int) | |
570 break; | |
571 | |
572 for (o2 = o -> next; o2; o2 = o2 -> next) | |
573 { | |
574 if (o2 -> p -> type == lw_expr_type_oper && o2 -> p -> value == lw_expr_oper_times) | |
575 { | |
576 // another "times" | |
577 for (op2 = o2 -> p -> operands; op2; op2 = op2 -> next) | |
578 if (op2 -> p -> type != lw_expr_type_int) | |
579 break; | |
580 | |
336 | 581 if (lw_expr_simplify_compareoperandlist(&op1, &op2)) |
335 | 582 { |
583 // we have like terms here | |
584 // do something about it | |
585 } | |
586 } | |
587 } | |
588 } | |
589 } | |
590 } | |
591 | |
592 | |
593 if (E -> value == lw_expr_oper_plus) | |
594 { | |
595 int c = 0, t = 0; | |
596 for (o = E -> operands; o; o = o -> next) | |
597 { | |
598 t++; | |
599 if (!(o -> p -> type == lw_expr_type_int && o -> p -> value == 0)) | |
600 { | |
601 c++; | |
602 } | |
603 } | |
604 if (c == 1) | |
605 { | |
606 lw_expr_t r; | |
607 // find the value and "move it up" | |
608 while (E -> operands) | |
609 { | |
610 o = E -> operands; | |
611 if (o -> p -> type != lw_expr_type_int || o -> p -> value != 0) | |
612 { | |
337 | 613 r = lw_expr_copy(o -> p); |
335 | 614 } |
615 E -> operands = o -> next; | |
616 lw_expr_destroy(o -> p); | |
617 lw_free(o); | |
618 } | |
619 *E = *r; | |
620 return; | |
621 } | |
622 else if (c == 0) | |
623 { | |
624 // replace with 0 | |
625 while (E -> operands) | |
626 { | |
627 o = E -> operands; | |
628 E -> operands = o -> next; | |
629 lw_expr_destroy(o -> p); | |
630 lw_free(o); | |
631 } | |
632 E -> type = lw_expr_type_int; | |
633 E -> value = 0; | |
634 return; | |
635 } | |
636 else if (c != t) | |
637 { | |
638 // collapse out zero terms | |
639 struct lw_expr_opers *o2; | |
640 | |
641 for (o = E -> operands; o; o = o -> next) | |
642 { | |
643 if (o -> p -> type == lw_expr_type_int && o -> p -> value == 0) | |
644 { | |
645 if (o == E -> operands) | |
646 { | |
647 E -> operands = o -> next; | |
648 lw_expr_destroy(o -> p); | |
649 lw_free(o); | |
650 o = E -> operands; | |
651 } | |
652 else | |
653 { | |
654 for (o2 = E -> operands; o2 -> next == o; o2 = o2 -> next) | |
655 /* do nothing */ ; | |
656 o2 -> next = o -> next; | |
657 lw_expr_destroy(o -> p); | |
658 lw_free(o); | |
659 o = o2; | |
660 } | |
661 } | |
662 } | |
663 } | |
664 return; | |
665 } | |
666 } | |
346
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
667 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
668 /* |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
669 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
670 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
|
671 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
|
672 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
|
673 determine what the term really is. It also handles parentheses. |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
674 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
675 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
|
676 respects the order of operations. |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
677 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
678 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
|
679 following conditions: |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
680 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
681 1. a NUL character |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
682 2. a whitespace character |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
683 3. a ) |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
684 4. a , |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
685 5. any character that is not recognized as a term |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
686 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
687 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
|
688 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
689 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
|
690 error. |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
691 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
692 */ |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
693 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
694 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
|
695 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
696 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
|
697 { |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
698 lw_expr_t term, term2; |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
699 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
700 eval_next: |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
701 if (!**p || isspace(**p) || **p == ')' || **p == ']') |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
702 return NULL; |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
703 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
704 // parentheses |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
705 if (**p == '(') |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
706 { |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
707 (*p)++; |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
708 term = lw_expr_parse_expr(p, priv, 0); |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
709 if (**p != ')') |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
710 { |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
711 lw_expr_destroy(term); |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
712 return NULL; |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
713 } |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
714 (*p)++; |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
715 return term; |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
716 } |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
717 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
718 // unary + |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
719 if (**p == '+') |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
720 { |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
721 (*p)++; |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
722 goto eval_next; |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
723 } |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
724 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
725 // unary - (prec 200) |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
726 if (**p == '-') |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
727 { |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
728 (*p)++; |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
729 term = lw_expr_parse_expr(p, priv, 200); |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
730 if (!term) |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
731 return NULL; |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
732 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
733 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
|
734 lw_expr_destroy(term); |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
735 return term2; |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
736 } |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
737 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
738 // unary ^ or ~ (complement, prec 200) |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
739 if (**p == '^' || **p == '~') |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
740 { |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
741 (*p)++; |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
742 term = lw_expr_parse_expr(p, priv, 200); |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
743 if (!term) |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
744 return NULL; |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
745 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
746 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
|
747 lw_expr_destroy(term); |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
748 return term2; |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
749 } |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
750 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
751 // non-operator - pass to caller |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
752 return parse_term(p, priv); |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
753 } |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
754 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
755 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
|
756 { |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
757 static const struct operinfo |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
758 { |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
759 int opernum; |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
760 char *operstr; |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
761 int operprec; |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
762 } operators[] = |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
763 { |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
764 { lw_expr_oper_plus, "+", 100 }, |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
765 { lw_expr_oper_minus, "-", 100 }, |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
766 { lw_expr_oper_times, "*", 100 }, |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
767 { lw_expr_oper_divide, "/", 150 }, |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
768 { lw_expr_oper_mod, "%", 150 }, |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
769 { lw_expr_oper_intdiv, "\\", 150 }, |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
770 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
771 { lw_expr_oper_and, "&&", 25 }, |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
772 { lw_expr_oper_or, "||", 25 }, |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
773 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
774 { lw_expr_oper_bwand, "&", 50 }, |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
775 { lw_expr_oper_bwor, "|", 50 }, |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
776 { lw_expr_oper_bwxor, "^", 50 }, |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
777 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
778 { lw_expr_oper_none, "", 0 } |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
779 }; |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
780 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
781 int opern, i; |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
782 lw_expr_t term1, term2, term3; |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
783 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
784 if (!**p || isspace(**p) || **p == ')' || **p == ',' || **p == ']') |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
785 return NULL; |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
786 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
787 term1 = lw_expr_parse_term(p, priv); |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
788 if (!term1) |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
789 return NULL; |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
790 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
791 eval_next: |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
792 if (!**p || isspace(**p) || **p == ')' || **p == ',' || **p == ']') |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
793 return term1; |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
794 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
795 // expecting an operator here |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
796 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
|
797 { |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
798 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
|
799 /* do nothing */; |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
800 if (operators[opern].operstr[i] == '\0') |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
801 break; |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
802 } |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
803 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
804 if (operators[opern].opernum == lw_expr_oper_none) |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
805 { |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
806 // unrecognized operator |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
807 lw_expr_destroy(term1); |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
808 return NULL; |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
809 } |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
810 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
811 // operator number is in opern, length of oper in i |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
812 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
813 // logic: |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
814 // 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
|
815 // we simply return without advancing the input pointer; the operator |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
816 // will be evaluated again in the enclosing function call |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
817 if (operators[opern].operprec <= prec) |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
818 return term1; |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
819 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
820 // logic: |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
821 // 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
|
822 // 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
|
823 // 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
|
824 // stack and then go on with the expression evaluation |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
825 (*p) += i; |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
826 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
827 // evaluate next expression(s) of higher precedence |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
828 term2 = lw_expr_parse_expr(p, priv, operators[opern].operprec); |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
829 if (!term2) |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
830 { |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
831 lw_expr_destroy(term1); |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
832 return NULL; |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
833 } |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
834 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
835 // now create operator |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
836 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
|
837 lw_expr_destroy(term1); |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
838 lw_expr_destroy(term2); |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
839 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
840 // the new "expression" is the next "left operand" |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
841 term1 = term3; |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
842 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
843 // continue evaluating |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
844 goto eval_next; |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
845 } |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
846 |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
847 lw_expr_t lw_expr_parse(char **p, void *priv) |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
848 { |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
849 return lw_expr_parse_expr(p, priv, 0); |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
342
diff
changeset
|
850 } |
367 | 851 |
852 int lw_expr_testterms(lw_expr_t e, lw_expr_testfn_t *fn, void *priv) | |
853 { | |
854 struct lw_expr_opers *o; | |
855 int r; | |
856 | |
857 for (o = e -> operands; o; o = o -> next) | |
858 { | |
859 r = lw_expr_testterms(o -> p, fn, priv); | |
860 if (r) | |
861 return r; | |
862 } | |
863 return (fn)(e, priv); | |
864 } |