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