1 /*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License
4 * as published by the Free Software Foundation; either version 2
5 * of the License, or (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software Foundation,
14 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15 *
16 * The Original Code is Copyright (C) 2018 Blender Foundation, Alexander Gavrilov
17 * All rights reserved.
18 */
19
20 /** \file
21 * \ingroup bli
22 *
23 * Simple evaluator for a subset of Python expressions that can be
24 * computed using purely double precision floating point values.
25 *
26 * Supported subset:
27 *
28 * - Identifiers use only ASCII characters.
29 * - Literals:
30 * floating point and decimal integer.
31 * - Constants:
32 * pi, True, False
33 * - Operators:
34 * +, -, *, /, ==, !=, <, <=, >, >=, and, or, not, ternary if
35 * - Functions:
36 * min, max, radians, degrees,
37 * abs, fabs, floor, ceil, trunc, int,
38 * sin, cos, tan, asin, acos, atan, atan2,
39 * exp, log, sqrt, pow, fmod
40 *
41 * The implementation has no global state and can be used multi-threaded.
42 */
43
44 #include <ctype.h>
45 #include <fenv.h>
46 #include <float.h>
47 #include <math.h>
48 #include <stddef.h>
49 #include <stdio.h>
50 #include <stdlib.h>
51 #include <string.h>
52
53 #include "MEM_guardedalloc.h"
54
55 #include "BLI_alloca.h"
56 #include "BLI_expr_pylike_eval.h"
57 #include "BLI_math_base.h"
58 #include "BLI_utildefines.h"
59
60 #ifdef _MSC_VER
61 # pragma fenv_access(on)
62 #endif
63
64 /* -------------------------------------------------------------------- */
65 /** \name Internal Types
66 * \{ */
67
68 typedef enum eOpCode {
69 /* Double constant: (-> dval) */
70 OPCODE_CONST,
71 /* 1 argument function call: (a -> func1(a)) */
72 OPCODE_FUNC1,
73 /* 2 argument function call: (a b -> func2(a,b)) */
74 OPCODE_FUNC2,
75 /* 3 argument function call: (a b c -> func3(a,b,c)) */
76 OPCODE_FUNC3,
77 /* Parameter access: (-> params[ival]) */
78 OPCODE_PARAMETER,
79 /* Minimum of multiple inputs: (a b c... -> min); ival = arg count */
80 OPCODE_MIN,
81 /* Maximum of multiple inputs: (a b c... -> max); ival = arg count */
82 OPCODE_MAX,
83 /* Jump (pc += jmp_offset) */
84 OPCODE_JMP,
85 /* Pop and jump if zero: (a -> ); JUMP IF NOT a */
86 OPCODE_JMP_ELSE,
87 /* Jump if nonzero, or pop: (a -> a JUMP) IF a ELSE (a -> ) */
88 OPCODE_JMP_OR,
89 /* Jump if zero, or pop: (a -> a JUMP) IF NOT a ELSE (a -> ) */
90 OPCODE_JMP_AND,
91 /* For comparison chaining: (a b -> 0 JUMP) IF NOT func2(a,b) ELSE (a b -> b) */
92 OPCODE_CMP_CHAIN,
93 } eOpCode;
94
95 typedef double (*UnaryOpFunc)(double);
96 typedef double (*BinaryOpFunc)(double, double);
97 typedef double (*TernaryOpFunc)(double, double, double);
98
99 typedef struct ExprOp {
100 eOpCode opcode;
101
102 int jmp_offset;
103
104 union {
105 int ival;
106 double dval;
107 void *ptr;
108 UnaryOpFunc func1;
109 BinaryOpFunc func2;
110 TernaryOpFunc func3;
111 } arg;
112 } ExprOp;
113
114 struct ExprPyLike_Parsed {
115 int ops_count;
116 int max_stack;
117
118 ExprOp ops[];
119 };
120
121 /** \} */
122
123 /* -------------------------------------------------------------------- */
124 /** \name Public API
125 * \{ */
126
127 /** Free the parsed data; NULL argument is ok. */
BLI_expr_pylike_free(ExprPyLike_Parsed * expr)128 void BLI_expr_pylike_free(ExprPyLike_Parsed *expr)
129 {
130 if (expr != NULL) {
131 MEM_freeN(expr);
132 }
133 }
134
135 /** Check if the parsing result is valid for evaluation. */
BLI_expr_pylike_is_valid(ExprPyLike_Parsed * expr)136 bool BLI_expr_pylike_is_valid(ExprPyLike_Parsed *expr)
137 {
138 return expr != NULL && expr->ops_count > 0;
139 }
140
141 /** Check if the parsed expression always evaluates to the same value. */
BLI_expr_pylike_is_constant(ExprPyLike_Parsed * expr)142 bool BLI_expr_pylike_is_constant(ExprPyLike_Parsed *expr)
143 {
144 return expr != NULL && expr->ops_count == 1 && expr->ops[0].opcode == OPCODE_CONST;
145 }
146
147 /** Check if the parsed expression uses the parameter with the given index. */
BLI_expr_pylike_is_using_param(ExprPyLike_Parsed * expr,int index)148 bool BLI_expr_pylike_is_using_param(ExprPyLike_Parsed *expr, int index)
149 {
150 int i;
151
152 if (expr == NULL) {
153 return false;
154 }
155
156 for (i = 0; i < expr->ops_count; i++) {
157 if (expr->ops[i].opcode == OPCODE_PARAMETER && expr->ops[i].arg.ival == index) {
158 return true;
159 }
160 }
161
162 return false;
163 }
164
165 /** \} */
166
167 /* -------------------------------------------------------------------- */
168 /** \name Stack Machine Evaluation
169 * \{ */
170
171 /**
172 * Evaluate the expression with the given parameters.
173 * The order and number of parameters must match the names given to parse.
174 */
BLI_expr_pylike_eval(ExprPyLike_Parsed * expr,const double * param_values,int param_values_len,double * r_result)175 eExprPyLike_EvalStatus BLI_expr_pylike_eval(ExprPyLike_Parsed *expr,
176 const double *param_values,
177 int param_values_len,
178 double *r_result)
179 {
180 *r_result = 0.0;
181
182 if (!BLI_expr_pylike_is_valid(expr)) {
183 return EXPR_PYLIKE_INVALID;
184 }
185
186 #define FAIL_IF(condition) \
187 if (condition) { \
188 return EXPR_PYLIKE_FATAL_ERROR; \
189 } \
190 ((void)0)
191
192 /* Check the stack requirement is at least remotely sane and allocate on the actual stack. */
193 FAIL_IF(expr->max_stack <= 0 || expr->max_stack > 1000);
194
195 double *stack = BLI_array_alloca(stack, expr->max_stack);
196
197 /* Evaluate expression. */
198 ExprOp *ops = expr->ops;
199 int sp = 0, pc;
200
201 feclearexcept(FE_ALL_EXCEPT);
202
203 for (pc = 0; pc >= 0 && pc < expr->ops_count; pc++) {
204 switch (ops[pc].opcode) {
205 /* Arithmetic */
206 case OPCODE_CONST:
207 FAIL_IF(sp >= expr->max_stack);
208 stack[sp++] = ops[pc].arg.dval;
209 break;
210 case OPCODE_PARAMETER:
211 FAIL_IF(sp >= expr->max_stack || ops[pc].arg.ival >= param_values_len);
212 stack[sp++] = param_values[ops[pc].arg.ival];
213 break;
214 case OPCODE_FUNC1:
215 FAIL_IF(sp < 1);
216 stack[sp - 1] = ops[pc].arg.func1(stack[sp - 1]);
217 break;
218 case OPCODE_FUNC2:
219 FAIL_IF(sp < 2);
220 stack[sp - 2] = ops[pc].arg.func2(stack[sp - 2], stack[sp - 1]);
221 sp--;
222 break;
223 case OPCODE_FUNC3:
224 FAIL_IF(sp < 3);
225 stack[sp - 3] = ops[pc].arg.func3(stack[sp - 3], stack[sp - 2], stack[sp - 1]);
226 sp -= 2;
227 break;
228 case OPCODE_MIN:
229 FAIL_IF(sp < ops[pc].arg.ival);
230 for (int j = 1; j < ops[pc].arg.ival; j++, sp--) {
231 CLAMP_MAX(stack[sp - 2], stack[sp - 1]);
232 }
233 break;
234 case OPCODE_MAX:
235 FAIL_IF(sp < ops[pc].arg.ival);
236 for (int j = 1; j < ops[pc].arg.ival; j++, sp--) {
237 CLAMP_MIN(stack[sp - 2], stack[sp - 1]);
238 }
239 break;
240
241 /* Jumps */
242 case OPCODE_JMP:
243 pc += ops[pc].jmp_offset;
244 break;
245 case OPCODE_JMP_ELSE:
246 FAIL_IF(sp < 1);
247 if (!stack[--sp]) {
248 pc += ops[pc].jmp_offset;
249 }
250 break;
251 case OPCODE_JMP_OR:
252 case OPCODE_JMP_AND:
253 FAIL_IF(sp < 1);
254 if (!stack[sp - 1] == !(ops[pc].opcode == OPCODE_JMP_OR)) {
255 pc += ops[pc].jmp_offset;
256 }
257 else {
258 sp--;
259 }
260 break;
261
262 /* For chaining comparisons, i.e. "a < b < c" as "a < b and b < c" */
263 case OPCODE_CMP_CHAIN:
264 FAIL_IF(sp < 2);
265 /* If comparison fails, return 0 and jump to end. */
266 if (!ops[pc].arg.func2(stack[sp - 2], stack[sp - 1])) {
267 stack[sp - 2] = 0.0;
268 pc += ops[pc].jmp_offset;
269 }
270 /* Otherwise keep b on the stack and proceed. */
271 else {
272 stack[sp - 2] = stack[sp - 1];
273 }
274 sp--;
275 break;
276
277 default:
278 return EXPR_PYLIKE_FATAL_ERROR;
279 }
280 }
281
282 FAIL_IF(sp != 1 || pc != expr->ops_count);
283
284 #undef FAIL_IF
285
286 *r_result = stack[0];
287
288 /* Detect floating point evaluation errors. */
289 int flags = fetestexcept(FE_DIVBYZERO | FE_INVALID);
290 if (flags) {
291 return (flags & FE_INVALID) ? EXPR_PYLIKE_MATH_ERROR : EXPR_PYLIKE_DIV_BY_ZERO;
292 }
293
294 return EXPR_PYLIKE_SUCCESS;
295 }
296
297 /** \} */
298
299 /* -------------------------------------------------------------------- */
300 /** \name Built-In Operations
301 * \{ */
302
op_negate(double arg)303 static double op_negate(double arg)
304 {
305 return -arg;
306 }
307
op_mul(double a,double b)308 static double op_mul(double a, double b)
309 {
310 return a * b;
311 }
312
op_div(double a,double b)313 static double op_div(double a, double b)
314 {
315 return a / b;
316 }
317
op_add(double a,double b)318 static double op_add(double a, double b)
319 {
320 return a + b;
321 }
322
op_sub(double a,double b)323 static double op_sub(double a, double b)
324 {
325 return a - b;
326 }
327
op_radians(double arg)328 static double op_radians(double arg)
329 {
330 return arg * M_PI / 180.0;
331 }
332
op_degrees(double arg)333 static double op_degrees(double arg)
334 {
335 return arg * 180.0 / M_PI;
336 }
337
op_log2(double a,double b)338 static double op_log2(double a, double b)
339 {
340 return log(a) / log(b);
341 }
342
op_lerp(double a,double b,double x)343 static double op_lerp(double a, double b, double x)
344 {
345 return a * (1.0 - x) + b * x;
346 }
347
op_clamp(double arg)348 static double op_clamp(double arg)
349 {
350 CLAMP(arg, 0.0, 1.0);
351 return arg;
352 }
353
op_clamp3(double arg,double minv,double maxv)354 static double op_clamp3(double arg, double minv, double maxv)
355 {
356 CLAMP(arg, minv, maxv);
357 return arg;
358 }
359
op_smoothstep(double a,double b,double x)360 static double op_smoothstep(double a, double b, double x)
361 {
362 double t = (x - a) / (b - a);
363 CLAMP(t, 0.0, 1.0);
364 return t * t * (3.0 - 2.0 * t);
365 }
366
op_not(double a)367 static double op_not(double a)
368 {
369 return a ? 0.0 : 1.0;
370 }
371
op_eq(double a,double b)372 static double op_eq(double a, double b)
373 {
374 return a == b ? 1.0 : 0.0;
375 }
376
op_ne(double a,double b)377 static double op_ne(double a, double b)
378 {
379 return a != b ? 1.0 : 0.0;
380 }
381
op_lt(double a,double b)382 static double op_lt(double a, double b)
383 {
384 return a < b ? 1.0 : 0.0;
385 }
386
op_le(double a,double b)387 static double op_le(double a, double b)
388 {
389 return a <= b ? 1.0 : 0.0;
390 }
391
op_gt(double a,double b)392 static double op_gt(double a, double b)
393 {
394 return a > b ? 1.0 : 0.0;
395 }
396
op_ge(double a,double b)397 static double op_ge(double a, double b)
398 {
399 return a >= b ? 1.0 : 0.0;
400 }
401
402 typedef struct BuiltinConstDef {
403 const char *name;
404 double value;
405 } BuiltinConstDef;
406
407 static BuiltinConstDef builtin_consts[] = {
408 {"pi", M_PI}, {"True", 1.0}, {"False", 0.0}, {NULL, 0.0}};
409
410 typedef struct BuiltinOpDef {
411 const char *name;
412 eOpCode op;
413 void *funcptr;
414 } BuiltinOpDef;
415
416 #ifdef _MSC_VER
417 /* Prevent MSVC from inlining calls to ceil/floor so the table below can get a function pointer to
418 * them. */
419 # pragma function(ceil)
420 # pragma function(floor)
421 #endif
422
423 static BuiltinOpDef builtin_ops[] = {
424 {"radians", OPCODE_FUNC1, op_radians},
425 {"degrees", OPCODE_FUNC1, op_degrees},
426 {"abs", OPCODE_FUNC1, fabs},
427 {"fabs", OPCODE_FUNC1, fabs},
428 {"floor", OPCODE_FUNC1, floor},
429 {"ceil", OPCODE_FUNC1, ceil},
430 {"trunc", OPCODE_FUNC1, trunc},
431 {"round", OPCODE_FUNC1, round},
432 {"int", OPCODE_FUNC1, trunc},
433 {"sin", OPCODE_FUNC1, sin},
434 {"cos", OPCODE_FUNC1, cos},
435 {"tan", OPCODE_FUNC1, tan},
436 {"asin", OPCODE_FUNC1, asin},
437 {"acos", OPCODE_FUNC1, acos},
438 {"atan", OPCODE_FUNC1, atan},
439 {"atan2", OPCODE_FUNC2, atan2},
440 {"exp", OPCODE_FUNC1, exp},
441 {"log", OPCODE_FUNC1, log},
442 {"log", OPCODE_FUNC2, op_log2},
443 {"sqrt", OPCODE_FUNC1, sqrt},
444 {"pow", OPCODE_FUNC2, pow},
445 {"fmod", OPCODE_FUNC2, fmod},
446 {"lerp", OPCODE_FUNC3, op_lerp},
447 {"clamp", OPCODE_FUNC1, op_clamp},
448 {"clamp", OPCODE_FUNC3, op_clamp3},
449 {"smoothstep", OPCODE_FUNC3, op_smoothstep},
450 {NULL, OPCODE_CONST, NULL},
451 };
452
453 /** \} */
454
455 /* -------------------------------------------------------------------- */
456 /** \name Expression Parser State
457 * \{ */
458
459 #define MAKE_CHAR2(a, b) (((a) << 8) | (b))
460
461 #define CHECK_ERROR(condition) \
462 if (!(condition)) { \
463 return false; \
464 } \
465 ((void)0)
466
467 /* For simplicity simple token types are represented by their own character;
468 * these are special identifiers for multi-character tokens. */
469 #define TOKEN_ID MAKE_CHAR2('I', 'D')
470 #define TOKEN_NUMBER MAKE_CHAR2('0', '0')
471 #define TOKEN_GE MAKE_CHAR2('>', '=')
472 #define TOKEN_LE MAKE_CHAR2('<', '=')
473 #define TOKEN_NE MAKE_CHAR2('!', '=')
474 #define TOKEN_EQ MAKE_CHAR2('=', '=')
475 #define TOKEN_AND MAKE_CHAR2('A', 'N')
476 #define TOKEN_OR MAKE_CHAR2('O', 'R')
477 #define TOKEN_NOT MAKE_CHAR2('N', 'O')
478 #define TOKEN_IF MAKE_CHAR2('I', 'F')
479 #define TOKEN_ELSE MAKE_CHAR2('E', 'L')
480
481 static const char *token_eq_characters = "!=><";
482 static const char *token_characters = "~`!@#$%^&*+-=/\\?:;<>(){}[]|.,\"'";
483
484 typedef struct KeywordTokenDef {
485 const char *name;
486 short token;
487 } KeywordTokenDef;
488
489 static KeywordTokenDef keyword_list[] = {
490 {"and", TOKEN_AND},
491 {"or", TOKEN_OR},
492 {"not", TOKEN_NOT},
493 {"if", TOKEN_IF},
494 {"else", TOKEN_ELSE},
495 {NULL, TOKEN_ID},
496 };
497
498 typedef struct ExprParseState {
499 int param_names_len;
500 const char **param_names;
501
502 /* Original expression */
503 const char *expr;
504 const char *cur;
505
506 /* Current token */
507 short token;
508 char *tokenbuf;
509 double tokenval;
510
511 /* Opcode buffer */
512 int ops_count, max_ops, last_jmp;
513 ExprOp *ops;
514
515 /* Stack space requirement tracking */
516 int stack_ptr, max_stack;
517 } ExprParseState;
518
519 /* Reserve space for the specified number of operations in the buffer. */
parse_alloc_ops(ExprParseState * state,int count)520 static ExprOp *parse_alloc_ops(ExprParseState *state, int count)
521 {
522 if (state->ops_count + count > state->max_ops) {
523 state->max_ops = power_of_2_max_i(state->ops_count + count);
524 state->ops = MEM_reallocN(state->ops, state->max_ops * sizeof(ExprOp));
525 }
526
527 ExprOp *op = &state->ops[state->ops_count];
528 state->ops_count += count;
529 return op;
530 }
531
532 /* Add one operation and track stack usage. */
parse_add_op(ExprParseState * state,eOpCode code,int stack_delta)533 static ExprOp *parse_add_op(ExprParseState *state, eOpCode code, int stack_delta)
534 {
535 /* track evaluation stack depth */
536 state->stack_ptr += stack_delta;
537 CLAMP_MIN(state->stack_ptr, 0);
538 CLAMP_MIN(state->max_stack, state->stack_ptr);
539
540 /* allocate the new instruction */
541 ExprOp *op = parse_alloc_ops(state, 1);
542 memset(op, 0, sizeof(ExprOp));
543 op->opcode = code;
544 return op;
545 }
546
547 /* Add one jump operation and return an index for parse_set_jump. */
parse_add_jump(ExprParseState * state,eOpCode code)548 static int parse_add_jump(ExprParseState *state, eOpCode code)
549 {
550 parse_add_op(state, code, -1);
551 return state->last_jmp = state->ops_count;
552 }
553
554 /* Set the jump offset in a previously added jump operation. */
parse_set_jump(ExprParseState * state,int jump)555 static void parse_set_jump(ExprParseState *state, int jump)
556 {
557 state->last_jmp = state->ops_count;
558 state->ops[jump - 1].jmp_offset = state->ops_count - jump;
559 }
560
561 /* Returns the required argument count of the given function call code. */
opcode_arg_count(eOpCode code)562 static int opcode_arg_count(eOpCode code)
563 {
564 switch (code) {
565 case OPCODE_FUNC1:
566 return 1;
567 case OPCODE_FUNC2:
568 return 2;
569 case OPCODE_FUNC3:
570 return 3;
571 default:
572 BLI_assert(!"unexpected opcode");
573 return -1;
574 }
575 }
576
577 /* Add a function call operation, applying constant folding when possible. */
parse_add_func(ExprParseState * state,eOpCode code,int args,void * funcptr)578 static bool parse_add_func(ExprParseState *state, eOpCode code, int args, void *funcptr)
579 {
580 ExprOp *prev_ops = &state->ops[state->ops_count];
581 int jmp_gap = state->ops_count - state->last_jmp;
582
583 feclearexcept(FE_ALL_EXCEPT);
584
585 switch (code) {
586 case OPCODE_FUNC1:
587 CHECK_ERROR(args == 1);
588
589 if (jmp_gap >= 1 && prev_ops[-1].opcode == OPCODE_CONST) {
590 UnaryOpFunc func = funcptr;
591
592 /* volatile because some compilers overly aggressive optimize this call out.
593 * see D6012 for details. */
594 volatile double result = func(prev_ops[-1].arg.dval);
595
596 if (fetestexcept(FE_DIVBYZERO | FE_INVALID) == 0) {
597 prev_ops[-1].arg.dval = result;
598 return true;
599 }
600 }
601 break;
602
603 case OPCODE_FUNC2:
604 CHECK_ERROR(args == 2);
605
606 if (jmp_gap >= 2 && prev_ops[-2].opcode == OPCODE_CONST &&
607 prev_ops[-1].opcode == OPCODE_CONST) {
608 BinaryOpFunc func = funcptr;
609
610 /* volatile because some compilers overly aggressive optimize this call out.
611 * see D6012 for details. */
612 volatile double result = func(prev_ops[-2].arg.dval, prev_ops[-1].arg.dval);
613
614 if (fetestexcept(FE_DIVBYZERO | FE_INVALID) == 0) {
615 prev_ops[-2].arg.dval = result;
616 state->ops_count--;
617 state->stack_ptr--;
618 return true;
619 }
620 }
621 break;
622
623 case OPCODE_FUNC3:
624 CHECK_ERROR(args == 3);
625
626 if (jmp_gap >= 3 && prev_ops[-3].opcode == OPCODE_CONST &&
627 prev_ops[-2].opcode == OPCODE_CONST && prev_ops[-1].opcode == OPCODE_CONST) {
628 TernaryOpFunc func = funcptr;
629
630 /* volatile because some compilers overly aggressive optimize this call out.
631 * see D6012 for details. */
632 volatile double result = func(
633 prev_ops[-3].arg.dval, prev_ops[-2].arg.dval, prev_ops[-1].arg.dval);
634
635 if (fetestexcept(FE_DIVBYZERO | FE_INVALID) == 0) {
636 prev_ops[-3].arg.dval = result;
637 state->ops_count -= 2;
638 state->stack_ptr -= 2;
639 return true;
640 }
641 }
642 break;
643
644 default:
645 BLI_assert(false);
646 return false;
647 }
648
649 parse_add_op(state, code, 1 - args)->arg.ptr = funcptr;
650 return true;
651 }
652
653 /* Extract the next token from raw characters. */
parse_next_token(ExprParseState * state)654 static bool parse_next_token(ExprParseState *state)
655 {
656 /* Skip whitespace. */
657 while (isspace(*state->cur)) {
658 state->cur++;
659 }
660
661 /* End of string. */
662 if (*state->cur == 0) {
663 state->token = 0;
664 return true;
665 }
666
667 /* Floating point numbers. */
668 if (isdigit(*state->cur) || (state->cur[0] == '.' && isdigit(state->cur[1]))) {
669 char *end, *out = state->tokenbuf;
670 bool is_float = false;
671
672 while (isdigit(*state->cur)) {
673 *out++ = *state->cur++;
674 }
675
676 if (*state->cur == '.') {
677 is_float = true;
678 *out++ = *state->cur++;
679
680 while (isdigit(*state->cur)) {
681 *out++ = *state->cur++;
682 }
683 }
684
685 if (ELEM(*state->cur, 'e', 'E')) {
686 is_float = true;
687 *out++ = *state->cur++;
688
689 if (ELEM(*state->cur, '+', '-')) {
690 *out++ = *state->cur++;
691 }
692
693 CHECK_ERROR(isdigit(*state->cur));
694
695 while (isdigit(*state->cur)) {
696 *out++ = *state->cur++;
697 }
698 }
699
700 *out = 0;
701
702 /* Forbid C-style octal constants. */
703 if (!is_float && state->tokenbuf[0] == '0') {
704 for (char *p = state->tokenbuf + 1; *p; p++) {
705 if (*p != '0') {
706 return false;
707 }
708 }
709 }
710
711 state->token = TOKEN_NUMBER;
712 state->tokenval = strtod(state->tokenbuf, &end);
713 return (end == out);
714 }
715
716 /* ?= tokens */
717 if (state->cur[1] == '=' && strchr(token_eq_characters, state->cur[0])) {
718 state->token = MAKE_CHAR2(state->cur[0], state->cur[1]);
719 state->cur += 2;
720 return true;
721 }
722
723 /* Special characters (single character tokens) */
724 if (strchr(token_characters, *state->cur)) {
725 state->token = *state->cur++;
726 return true;
727 }
728
729 /* Identifiers */
730 if (isalpha(*state->cur) || ELEM(*state->cur, '_')) {
731 char *out = state->tokenbuf;
732
733 while (isalnum(*state->cur) || ELEM(*state->cur, '_')) {
734 *out++ = *state->cur++;
735 }
736
737 *out = 0;
738
739 for (int i = 0; keyword_list[i].name; i++) {
740 if (STREQ(state->tokenbuf, keyword_list[i].name)) {
741 state->token = keyword_list[i].token;
742 return true;
743 }
744 }
745
746 state->token = TOKEN_ID;
747 return true;
748 }
749
750 return false;
751 }
752
753 /** \} */
754
755 /* -------------------------------------------------------------------- */
756 /** \name Recursive Descent Parser
757 * \{ */
758
759 static bool parse_expr(ExprParseState *state);
760
parse_function_args(ExprParseState * state)761 static int parse_function_args(ExprParseState *state)
762 {
763 if (!parse_next_token(state) || state->token != '(' || !parse_next_token(state)) {
764 return -1;
765 }
766
767 int arg_count = 0;
768
769 for (;;) {
770 if (!parse_expr(state)) {
771 return -1;
772 }
773
774 arg_count++;
775
776 switch (state->token) {
777 case ',':
778 if (!parse_next_token(state)) {
779 return -1;
780 }
781 break;
782
783 case ')':
784 if (!parse_next_token(state)) {
785 return -1;
786 }
787 return arg_count;
788
789 default:
790 return -1;
791 }
792 }
793 }
794
parse_unary(ExprParseState * state)795 static bool parse_unary(ExprParseState *state)
796 {
797 int i;
798
799 switch (state->token) {
800 case '+':
801 return parse_next_token(state) && parse_unary(state);
802
803 case '-':
804 CHECK_ERROR(parse_next_token(state) && parse_unary(state));
805 parse_add_func(state, OPCODE_FUNC1, 1, op_negate);
806 return true;
807
808 case '(':
809 return parse_next_token(state) && parse_expr(state) && state->token == ')' &&
810 parse_next_token(state);
811
812 case TOKEN_NUMBER:
813 parse_add_op(state, OPCODE_CONST, 1)->arg.dval = state->tokenval;
814 return parse_next_token(state);
815
816 case TOKEN_ID:
817 /* Parameters: search in reverse order in case of duplicate names -
818 * the last one should win. */
819 for (i = state->param_names_len - 1; i >= 0; i--) {
820 if (STREQ(state->tokenbuf, state->param_names[i])) {
821 parse_add_op(state, OPCODE_PARAMETER, 1)->arg.ival = i;
822 return parse_next_token(state);
823 }
824 }
825
826 /* Ordinary builtin constants. */
827 for (i = 0; builtin_consts[i].name; i++) {
828 if (STREQ(state->tokenbuf, builtin_consts[i].name)) {
829 parse_add_op(state, OPCODE_CONST, 1)->arg.dval = builtin_consts[i].value;
830 return parse_next_token(state);
831 }
832 }
833
834 /* Ordinary builtin functions. */
835 for (i = 0; builtin_ops[i].name; i++) {
836 if (STREQ(state->tokenbuf, builtin_ops[i].name)) {
837 int args = parse_function_args(state);
838
839 /* Search for other arg count versions if necessary. */
840 if (args != opcode_arg_count(builtin_ops[i].op)) {
841 for (int j = i + 1; builtin_ops[j].name; j++) {
842 if (opcode_arg_count(builtin_ops[j].op) == args &&
843 STREQ(builtin_ops[j].name, builtin_ops[i].name)) {
844 i = j;
845 break;
846 }
847 }
848 }
849
850 return parse_add_func(state, builtin_ops[i].op, args, builtin_ops[i].funcptr);
851 }
852 }
853
854 /* Specially supported functions. */
855 if (STREQ(state->tokenbuf, "min")) {
856 int cnt = parse_function_args(state);
857 CHECK_ERROR(cnt > 0);
858
859 parse_add_op(state, OPCODE_MIN, 1 - cnt)->arg.ival = cnt;
860 return true;
861 }
862
863 if (STREQ(state->tokenbuf, "max")) {
864 int cnt = parse_function_args(state);
865 CHECK_ERROR(cnt > 0);
866
867 parse_add_op(state, OPCODE_MAX, 1 - cnt)->arg.ival = cnt;
868 return true;
869 }
870
871 return false;
872
873 default:
874 return false;
875 }
876 }
877
parse_mul(ExprParseState * state)878 static bool parse_mul(ExprParseState *state)
879 {
880 CHECK_ERROR(parse_unary(state));
881
882 for (;;) {
883 switch (state->token) {
884 case '*':
885 CHECK_ERROR(parse_next_token(state) && parse_unary(state));
886 parse_add_func(state, OPCODE_FUNC2, 2, op_mul);
887 break;
888
889 case '/':
890 CHECK_ERROR(parse_next_token(state) && parse_unary(state));
891 parse_add_func(state, OPCODE_FUNC2, 2, op_div);
892 break;
893
894 default:
895 return true;
896 }
897 }
898 }
899
parse_add(ExprParseState * state)900 static bool parse_add(ExprParseState *state)
901 {
902 CHECK_ERROR(parse_mul(state));
903
904 for (;;) {
905 switch (state->token) {
906 case '+':
907 CHECK_ERROR(parse_next_token(state) && parse_mul(state));
908 parse_add_func(state, OPCODE_FUNC2, 2, op_add);
909 break;
910
911 case '-':
912 CHECK_ERROR(parse_next_token(state) && parse_mul(state));
913 parse_add_func(state, OPCODE_FUNC2, 2, op_sub);
914 break;
915
916 default:
917 return true;
918 }
919 }
920 }
921
parse_get_cmp_func(short token)922 static BinaryOpFunc parse_get_cmp_func(short token)
923 {
924 switch (token) {
925 case TOKEN_EQ:
926 return op_eq;
927 case TOKEN_NE:
928 return op_ne;
929 case '>':
930 return op_gt;
931 case TOKEN_GE:
932 return op_ge;
933 case '<':
934 return op_lt;
935 case TOKEN_LE:
936 return op_le;
937 default:
938 return NULL;
939 }
940 }
941
parse_cmp_chain(ExprParseState * state,BinaryOpFunc cur_func)942 static bool parse_cmp_chain(ExprParseState *state, BinaryOpFunc cur_func)
943 {
944 BinaryOpFunc next_func = parse_get_cmp_func(state->token);
945
946 if (next_func) {
947 parse_add_op(state, OPCODE_CMP_CHAIN, -1)->arg.func2 = cur_func;
948 int jump = state->last_jmp = state->ops_count;
949
950 CHECK_ERROR(parse_next_token(state) && parse_add(state));
951 CHECK_ERROR(parse_cmp_chain(state, next_func));
952
953 parse_set_jump(state, jump);
954 }
955 else {
956 parse_add_func(state, OPCODE_FUNC2, 2, cur_func);
957 }
958
959 return true;
960 }
961
parse_cmp(ExprParseState * state)962 static bool parse_cmp(ExprParseState *state)
963 {
964 CHECK_ERROR(parse_add(state));
965
966 BinaryOpFunc func = parse_get_cmp_func(state->token);
967
968 if (func) {
969 CHECK_ERROR(parse_next_token(state) && parse_add(state));
970
971 return parse_cmp_chain(state, func);
972 }
973
974 return true;
975 }
976
parse_not(ExprParseState * state)977 static bool parse_not(ExprParseState *state)
978 {
979 if (state->token == TOKEN_NOT) {
980 CHECK_ERROR(parse_next_token(state) && parse_not(state));
981 parse_add_func(state, OPCODE_FUNC1, 1, op_not);
982 return true;
983 }
984
985 return parse_cmp(state);
986 }
987
parse_and(ExprParseState * state)988 static bool parse_and(ExprParseState *state)
989 {
990 CHECK_ERROR(parse_not(state));
991
992 if (state->token == TOKEN_AND) {
993 int jump = parse_add_jump(state, OPCODE_JMP_AND);
994
995 CHECK_ERROR(parse_next_token(state) && parse_and(state));
996
997 parse_set_jump(state, jump);
998 }
999
1000 return true;
1001 }
1002
parse_or(ExprParseState * state)1003 static bool parse_or(ExprParseState *state)
1004 {
1005 CHECK_ERROR(parse_and(state));
1006
1007 if (state->token == TOKEN_OR) {
1008 int jump = parse_add_jump(state, OPCODE_JMP_OR);
1009
1010 CHECK_ERROR(parse_next_token(state) && parse_or(state));
1011
1012 parse_set_jump(state, jump);
1013 }
1014
1015 return true;
1016 }
1017
parse_expr(ExprParseState * state)1018 static bool parse_expr(ExprParseState *state)
1019 {
1020 /* Temporarily set the constant expression evaluation barrier */
1021 int prev_last_jmp = state->last_jmp;
1022 int start = state->last_jmp = state->ops_count;
1023
1024 CHECK_ERROR(parse_or(state));
1025
1026 if (state->token == TOKEN_IF) {
1027 /* Ternary IF expression in python requires swapping the
1028 * main body with condition, so stash the body opcodes. */
1029 int size = state->ops_count - start;
1030 int bytes = size * sizeof(ExprOp);
1031
1032 ExprOp *body = MEM_mallocN(bytes, "driver if body");
1033 memcpy(body, state->ops + start, bytes);
1034
1035 state->last_jmp = state->ops_count = start;
1036 state->stack_ptr--;
1037
1038 /* Parse condition. */
1039 if (!parse_next_token(state) || !parse_or(state) || state->token != TOKEN_ELSE ||
1040 !parse_next_token(state)) {
1041 MEM_freeN(body);
1042 return false;
1043 }
1044
1045 int jmp_else = parse_add_jump(state, OPCODE_JMP_ELSE);
1046
1047 /* Add body back. */
1048 memcpy(parse_alloc_ops(state, size), body, bytes);
1049 MEM_freeN(body);
1050
1051 state->stack_ptr++;
1052
1053 int jmp_end = parse_add_jump(state, OPCODE_JMP);
1054
1055 /* Parse the else block. */
1056 parse_set_jump(state, jmp_else);
1057
1058 CHECK_ERROR(parse_expr(state));
1059
1060 parse_set_jump(state, jmp_end);
1061 }
1062 /* If no actual jumps happened, restore previous barrier */
1063 else if (state->last_jmp == start) {
1064 state->last_jmp = prev_last_jmp;
1065 }
1066
1067 return true;
1068 }
1069
1070 /** \} */
1071
1072 /* -------------------------------------------------------------------- */
1073 /** \name Main Parsing Function
1074 * \{ */
1075
1076 /**
1077 * Compile the expression and return the result.
1078 *
1079 * Parse the expression for evaluation later.
1080 * Returns non-NULL even on failure; use is_valid to check.
1081 */
BLI_expr_pylike_parse(const char * expression,const char ** param_names,int param_names_len)1082 ExprPyLike_Parsed *BLI_expr_pylike_parse(const char *expression,
1083 const char **param_names,
1084 int param_names_len)
1085 {
1086 /* Prepare the parser state. */
1087 ExprParseState state;
1088 memset(&state, 0, sizeof(state));
1089
1090 state.cur = state.expr = expression;
1091
1092 state.param_names_len = param_names_len;
1093 state.param_names = param_names;
1094
1095 state.tokenbuf = MEM_mallocN(strlen(expression) + 1, __func__);
1096
1097 state.max_ops = 16;
1098 state.ops = MEM_mallocN(state.max_ops * sizeof(ExprOp), __func__);
1099
1100 /* Parse the expression. */
1101 ExprPyLike_Parsed *expr;
1102
1103 if (parse_next_token(&state) && parse_expr(&state) && state.token == 0) {
1104 BLI_assert(state.stack_ptr == 1);
1105
1106 int bytesize = sizeof(ExprPyLike_Parsed) + state.ops_count * sizeof(ExprOp);
1107
1108 expr = MEM_mallocN(bytesize, "ExprPyLike_Parsed");
1109 expr->ops_count = state.ops_count;
1110 expr->max_stack = state.max_stack;
1111
1112 memcpy(expr->ops, state.ops, state.ops_count * sizeof(ExprOp));
1113 }
1114 else {
1115 /* Always return a non-NULL object so that parse failure can be cached. */
1116 expr = MEM_callocN(sizeof(ExprPyLike_Parsed), "ExprPyLike_Parsed(empty)");
1117 }
1118
1119 MEM_freeN(state.tokenbuf);
1120 MEM_freeN(state.ops);
1121 return expr;
1122 }
1123
1124 /** \} */
1125