operational evaluator for expressions
Costa Tsaousis committed
Aug 11, 2016 at 00:14 UTC
3f52dca264fee6721813bd662811e020b62e6748
3 files changed
+279
-83
profile/test-eval.c
+129
-23
@@ -56,82 +56,181 @@ void print_operand(EVAL_OPERAND *op, int level) {
56
while(i--) print_value(&op->ops[i], level + 1);
57
}
58
59
-calculated_number evaluate(EVAL_OPERAND *op);
59
+calculated_number evaluate(EVAL_OPERAND *op, int depth);
60
61
-calculated_number evaluate_value(EVAL_VALUE *v) {
61
+calculated_number evaluate_value(EVAL_VALUE *v, int depth) {
62
switch(v->type) {
63
case EVAL_VALUE_NUMBER:
64
return v->number;
65
66
case EVAL_VALUE_EXPRESSION:
67
- return evaluate(v->expression);
67
+ return evaluate(v->expression, depth);
68
69
default:
70
fatal("I don't know how to handle EVAL_VALUE type %d", v->type);
71
}
72
}
73
74
-calculated_number evaluate(EVAL_OPERAND *op) {
74
+void print_depth(int depth) {
75
+ static int count = 0;
76
+
77
+ printf("%d. ", ++count);
78
+ while(depth--) printf(" ");
79
+}
80
+
81
+calculated_number evaluate(EVAL_OPERAND *op, int depth) {
82
calculated_number n1, n2, r;
83
84
switch(op->operator) {
85
case EVAL_OPERATOR_SIGN_PLUS:
79
- r = evaluate_value(&op->ops[0]);
86
+ r = evaluate_value(&op->ops[0], depth);
87
break;
88
89
case EVAL_OPERATOR_SIGN_MINUS:
83
- r = -evaluate_value(&op->ops[0]);
90
+ r = -evaluate_value(&op->ops[0], depth);
91
break;
92
93
case EVAL_OPERATOR_PLUS:
94
if(op->count != 2)
95
fatal("Operator '%c' requires 2 values, but we have %d", op->operator, op->count);
89
- n1 = evaluate_value(&op->ops[0]);
90
- n2 = evaluate_value(&op->ops[1]);
96
+ n1 = evaluate_value(&op->ops[0], depth);
97
+ n2 = evaluate_value(&op->ops[1], depth);
98
r = n1 + n2;
92
- printf("%Lf = %Lf %c %Lf\n", r, n1, op->operator, n2);
99
+ print_depth(depth);
100
+ printf("%Lf = %Lf + %Lf\n", r, n1, n2);
101
break;
102
103
case EVAL_OPERATOR_MINUS:
104
if(op->count != 2)
105
fatal("Operator '%c' requires 2 values, but we have %d", op->operator, op->count);
98
- n1 = evaluate_value(&op->ops[0]);
99
- n2 = evaluate_value(&op->ops[1]);
106
+ n1 = evaluate_value(&op->ops[0], depth);
107
+ n2 = evaluate_value(&op->ops[1], depth);
108
r = n1 - n2;
101
- printf("%Lf = %Lf %c %Lf\n", r, n1, op->operator, n2);
109
+ print_depth(depth);
110
+ printf("%Lf = %Lf - %Lf\n", r, n1, n2);
111
break;
112
113
case EVAL_OPERATOR_MULTIPLY:
114
if(op->count != 2)
115
fatal("Operator '%c' requires 2 values, but we have %d", op->operator, op->count);
107
- n1 = evaluate_value(&op->ops[0]);
108
- n2 = evaluate_value(&op->ops[1]);
116
+ n1 = evaluate_value(&op->ops[0], depth);
117
+ n2 = evaluate_value(&op->ops[1], depth);
118
r = n1 * n2;
110
- printf("%Lf = %Lf %c %Lf\n", r, n1, op->operator, n2);
119
+ print_depth(depth);
120
+ printf("%Lf = %Lf * %Lf\n", r, n1, n2);
121
break;
122
123
case EVAL_OPERATOR_DIVIDE:
124
if(op->count != 2)
125
fatal("Operator '%c' requires 2 values, but we have %d", op->operator, op->count);
116
- n1 = evaluate_value(&op->ops[0]);
117
- n2 = evaluate_value(&op->ops[1]);
126
+ n1 = evaluate_value(&op->ops[0], depth);
127
+ n2 = evaluate_value(&op->ops[1], depth);
128
r = n1 / n2;
119
- printf("%Lf = %Lf %c %Lf\n", r, n1, op->operator, n2);
129
+ print_depth(depth);
130
+ printf("%Lf = %Lf / %Lf\n", r, n1, n2);
131
+ break;
132
+
133
+ case EVAL_OPERATOR_NOT:
134
+ n1 = evaluate_value(&op->ops[0], depth);
135
+ r = !n1;
136
+ print_depth(depth);
137
+ printf("%Lf = NOT %Lf\n", r, n1);
138
+ break;
139
+
140
+ case EVAL_OPERATOR_AND:
141
+ if(op->count != 2)
142
+ fatal("Operator '%c' requires 2 values, but we have %d", op->operator, op->count);
143
+ n1 = evaluate_value(&op->ops[0], depth);
144
+ n2 = evaluate_value(&op->ops[1], depth);
145
+ r = n1 && n2;
146
+ print_depth(depth);
147
+ printf("%Lf = %Lf AND %Lf\n", r, n1, n2);
148
+ break;
149
+
150
+ case EVAL_OPERATOR_OR:
151
+ if(op->count != 2)
152
+ fatal("Operator '%c' requires 2 values, but we have %d", op->operator, op->count);
153
+ n1 = evaluate_value(&op->ops[0], depth);
154
+ n2 = evaluate_value(&op->ops[1], depth);
155
+ r = n1 || n2;
156
+ print_depth(depth);
157
+ printf("%Lf = %Lf OR %Lf\n", r, n1, n2);
158
+ break;
159
+
160
+ case EVAL_OPERATOR_GREATER_THAN_OR_EQUAL:
161
+ if(op->count != 2)
162
+ fatal("Operator '%c' requires 2 values, but we have %d", op->operator, op->count);
163
+ n1 = evaluate_value(&op->ops[0], depth);
164
+ n2 = evaluate_value(&op->ops[1], depth);
165
+ r = n1 >= n2;
166
+ print_depth(depth);
167
+ printf("%Lf = %Lf >= %Lf\n", r, n1, n2);
168
+ break;
169
+
170
+ case EVAL_OPERATOR_LESS_THAN_OR_EQUAL:
171
+ if(op->count != 2)
172
+ fatal("Operator '%c' requires 2 values, but we have %d", op->operator, op->count);
173
+ n1 = evaluate_value(&op->ops[0], depth);
174
+ n2 = evaluate_value(&op->ops[1], depth);
175
+ r = n1 <= n2;
176
+ print_depth(depth);
177
+ printf("%Lf = %Lf <= %Lf\n", r, n1, n2);
178
+ break;
179
+
180
+ case EVAL_OPERATOR_GREATER:
181
+ if(op->count != 2)
182
+ fatal("Operator '%c' requires 2 values, but we have %d", op->operator, op->count);
183
+ n1 = evaluate_value(&op->ops[0], depth);
184
+ n2 = evaluate_value(&op->ops[1], depth);
185
+ r = n1 > n2;
186
+ print_depth(depth);
187
+ printf("%Lf = %Lf > %Lf\n", r, n1, n2);
188
+ break;
189
+
190
+ case EVAL_OPERATOR_LESS:
191
+ if(op->count != 2)
192
+ fatal("Operator '%c' requires 2 values, but we have %d", op->operator, op->count);
193
+ n1 = evaluate_value(&op->ops[0], depth);
194
+ n2 = evaluate_value(&op->ops[1], depth);
195
+ r = n1 < n2;
196
+ print_depth(depth);
197
+ printf("%Lf = %Lf < %Lf\n", r, n1, n2);
198
+ break;
199
+
200
+ case EVAL_OPERATOR_NOT_EQUAL:
201
+ if(op->count != 2)
202
+ fatal("Operator '%c' requires 2 values, but we have %d", op->operator, op->count);
203
+ n1 = evaluate_value(&op->ops[0], depth);
204
+ n2 = evaluate_value(&op->ops[1], depth);
205
+ r = n1 != n2;
206
+ print_depth(depth);
207
+ printf("%Lf = %Lf <> %Lf\n", r, n1, n2);
208
+ break;
209
+
210
+ case EVAL_OPERATOR_EQUAL:
211
+ if(op->count != 2)
212
+ fatal("Operator '%c' requires 2 values, but we have %d", op->operator, op->count);
213
+ n1 = evaluate_value(&op->ops[0], depth);
214
+ n2 = evaluate_value(&op->ops[1], depth);
215
+ r = n1 == n2;
216
+ print_depth(depth);
217
+ printf("%Lf = %Lf == %Lf\n", r, n1, n2);
218
break;
219
220
case EVAL_OPERATOR_EXPRESSION_OPEN:
221
printf("BEGIN SUB-EXPRESSION\n");
124
- r = evaluate_value(&op->ops[0]);
222
+ r = evaluate_value(&op->ops[0], depth + 1);
223
printf("END SUB-EXPRESSION\n");
224
break;
225
226
case EVAL_OPERATOR_NOP:
227
case EVAL_OPERATOR_VALUE:
130
- r = evaluate_value(&op->ops[0]);
228
+ r = evaluate_value(&op->ops[0], depth);
229
break;
230
231
default:
134
- fatal("I don't know how to handle operator '%c'", op->operator);
232
+ error("I don't know how to handle operator '%c'", op->operator);
233
+ r = 0;
234
break;
235
}
236
@@ -140,9 +239,16 @@ calculated_number evaluate(EVAL_OPERAND *op) {
239
240
void print_expression(EVAL_OPERAND *op, const char *failed_at, int error) {
241
if(op) {
143
- printf("<expression root>\n");
242
+ printf("expression tree:\n");
243
print_operand(op, 0);
145
- evaluate(op);
244
+
245
+ printf("\nevaluation steps:\n");
246
+ evaluate(op, 0);
247
+
248
+ int error;
249
+ calculated_number ret = evaluate_expression(op, &error);
250
+ printf("\ninternal evaluator:\nSTATUS: %d, RESULT = %Lf\n", error, ret);
251
+
252
free_expression(op);
253
}
254
else {
src/eval.c
+140
-59
@@ -1,5 +1,12 @@
1
#include "common.h"
2
3
+// forward definitions
4
+static inline void operand_free(EVAL_OPERAND *op);
5
+static inline EVAL_OPERAND *parse_operand(const char **string, int *error);
6
+static inline EVAL_OPERAND *parse_operand1(const char **string, int *error);
7
+static inline calculated_number eval_operand(EVAL_OPERAND *op, int *error);
8
+
9
+
10
static inline void skip_spaces(const char **string) {
11
const char *s = *string;
12
while(isspace(*s)) s++;
@@ -212,8 +219,12 @@ static inline int parse_close_subexpression(const char **string) {
219
220
static inline int parse_literal(const char **string, calculated_number *number) {
221
char *end = NULL;
215
- *number = strtold(*string, &end);
216
- if(!end || *string == end) return 0;
222
+ calculated_number n = strtold(*string, &end);
223
+ if(unlikely(!end || *string == end || isnan(n) || isinf(n))) {
224
+ *number = 0;
225
+ return 0;
226
+ }
227
+ *number = n;
228
229
*string = end;
230
return 1;
@@ -276,88 +287,138 @@ static struct operator_parser {
287
// ----------------------------------------------------------------------------
288
// evaluation of operations
289
279
-calculated_number eval_and(EVAL_OPERAND *op) {
280
- return 0;
290
+static inline calculated_number eval_check_number(calculated_number n, int *error) {
291
+ if(unlikely(isnan(n))) {
292
+ *error = EVAL_ERROR_VALUE_IS_NAN;
293
+ return 0;
294
+ }
295
+
296
+ if(unlikely(isinf(n))) {
297
+ *error = EVAL_ERROR_VALUE_IS_INFINITE;
298
+ return 0;
299
+ }
300
+
301
+ return n;
302
}
282
-calculated_number eval_or(EVAL_OPERAND *op) {
283
- return 0;
303
+
304
+static inline calculated_number eval_value(EVAL_VALUE *v, int *error) {
305
+ calculated_number n;
306
+
307
+ switch(v->type) {
308
+ case EVAL_VALUE_EXPRESSION:
309
+ n = eval_operand(v->expression, error);
310
+ break;
311
+
312
+ case EVAL_VALUE_NUMBER:
313
+ n = v->number;
314
+ break;
315
+
316
+// case EVAL_VALUE_VARIABLE:
317
+// break;
318
+
319
+ default:
320
+ *error = EVAL_ERROR_INVALID_VALUE;
321
+ n = 0;
322
+ break;
323
+ }
324
+
325
+ return eval_check_number(n, error);
326
}
285
-calculated_number eval_greater_than_or_equal(EVAL_OPERAND *op) {
286
- return 0;
327
+
328
+calculated_number eval_and(EVAL_OPERAND *op, int *error) {
329
+ return eval_value(&op->ops[0], error) && eval_value(&op->ops[1], error);
330
}
288
-calculated_number eval_less_than_or_equal(EVAL_OPERAND *op) {
289
- return 0;
331
+calculated_number eval_or(EVAL_OPERAND *op, int *error) {
332
+ return eval_value(&op->ops[0], error) || eval_value(&op->ops[1], error);
333
}
291
-calculated_number eval_not_equal(EVAL_OPERAND *op) {
292
- return 0;
334
+calculated_number eval_greater_than_or_equal(EVAL_OPERAND *op, int *error) {
335
+ return eval_value(&op->ops[0], error) >= eval_value(&op->ops[1], error);
336
}
294
-calculated_number eval_equal(EVAL_OPERAND *op) {
295
- return 0;
337
+calculated_number eval_less_than_or_equal(EVAL_OPERAND *op, int *error) {
338
+ return eval_value(&op->ops[0], error) <= eval_value(&op->ops[1], error);
339
}
297
-calculated_number eval_less(EVAL_OPERAND *op) {
298
- return 0;
340
+calculated_number eval_not_equal(EVAL_OPERAND *op, int *error) {
341
+ return eval_value(&op->ops[0], error) != eval_value(&op->ops[1], error);
342
}
300
-calculated_number eval_greater(EVAL_OPERAND *op) {
301
- return 0;
343
+calculated_number eval_equal(EVAL_OPERAND *op, int *error) {
344
+ return eval_value(&op->ops[0], error) == eval_value(&op->ops[1], error);
345
}
303
-calculated_number eval_plus(EVAL_OPERAND *op) {
304
- return 0;
346
+calculated_number eval_less(EVAL_OPERAND *op, int *error) {
347
+ return eval_value(&op->ops[0], error) < eval_value(&op->ops[1], error);
348
}
306
-calculated_number eval_minus(EVAL_OPERAND *op) {
307
- return 0;
349
+calculated_number eval_greater(EVAL_OPERAND *op, int *error) {
350
+ return eval_value(&op->ops[0], error) > eval_value(&op->ops[1], error);
351
}
309
-calculated_number eval_multiply(EVAL_OPERAND *op) {
310
- return 0;
352
+calculated_number eval_plus(EVAL_OPERAND *op, int *error) {
353
+ return eval_value(&op->ops[0], error) + eval_value(&op->ops[1], error);
354
}
312
-calculated_number eval_divide(EVAL_OPERAND *op) {
313
- return 0;
355
+calculated_number eval_minus(EVAL_OPERAND *op, int *error) {
356
+ return eval_value(&op->ops[0], error) - eval_value(&op->ops[1], error);
357
}
315
-calculated_number eval_nop(EVAL_OPERAND *op) {
316
- return 0;
358
+calculated_number eval_multiply(EVAL_OPERAND *op, int *error) {
359
+ return eval_value(&op->ops[0], error) * eval_value(&op->ops[1], error);
360
}
318
-calculated_number eval_not(EVAL_OPERAND *op) {
319
- return 0;
361
+calculated_number eval_divide(EVAL_OPERAND *op, int *error) {
362
+ return eval_value(&op->ops[0], error) / eval_value(&op->ops[1], error);
363
}
321
-calculated_number eval_sign_plus(EVAL_OPERAND *op) {
322
- return 0;
364
+calculated_number eval_nop(EVAL_OPERAND *op, int *error) {
365
+ return eval_value(&op->ops[0], error);
366
}
324
-calculated_number eval_sign_minus(EVAL_OPERAND *op) {
325
- return 0;
367
+calculated_number eval_not(EVAL_OPERAND *op, int *error) {
368
+ return !eval_value(&op->ops[0], error);
369
+}
370
+calculated_number eval_sign_plus(EVAL_OPERAND *op, int *error) {
371
+ return eval_value(&op->ops[0], error);
372
+}
373
+calculated_number eval_sign_minus(EVAL_OPERAND *op, int *error) {
374
+ return -eval_value(&op->ops[0], error);
375
}
376
377
static struct operator {
378
const char *print_as;
379
char precedence;
331
- calculated_number (*eval)(EVAL_OPERAND *op);
380
+ char parameters;
381
+ calculated_number (*eval)(EVAL_OPERAND *op, int *error);
382
} operators[256] = {
383
// this is a random access array
384
// we always access it with a known EVAL_OPERATOR_X
385
336
- [EVAL_OPERATOR_AND] = { "&&", 2, eval_and },
337
- [EVAL_OPERATOR_OR] = { "||", 2, eval_or },
338
- [EVAL_OPERATOR_GREATER_THAN_OR_EQUAL] = { ">=", 3, eval_greater_than_or_equal },
339
- [EVAL_OPERATOR_LESS_THAN_OR_EQUAL] = { "<=", 3, eval_less_than_or_equal },
340
- [EVAL_OPERATOR_NOT_EQUAL] = { "!=", 3, eval_not_equal },
341
- [EVAL_OPERATOR_EQUAL] = { "==", 3, eval_equal },
342
- [EVAL_OPERATOR_LESS] = { "<", 3, eval_less },
343
- [EVAL_OPERATOR_GREATER] = { ">", 3, eval_greater },
344
- [EVAL_OPERATOR_PLUS] = { "+", 4, eval_plus },
345
- [EVAL_OPERATOR_MINUS] = { "-", 4, eval_minus },
346
- [EVAL_OPERATOR_MULTIPLY] = { "*", 5, eval_multiply },
347
- [EVAL_OPERATOR_DIVIDE] = { "/", 5, eval_divide },
348
- [EVAL_OPERATOR_NOT] = { "!", 6, eval_not },
349
- [EVAL_OPERATOR_SIGN_PLUS] = { "+", 6, eval_sign_plus },
350
- [EVAL_OPERATOR_SIGN_MINUS] = { "-", 6, eval_sign_minus },
351
- [EVAL_OPERATOR_NOP] = { NULL, 7, eval_nop },
352
- [EVAL_OPERATOR_VALUE] = { NULL, 7, eval_nop },
353
- [EVAL_OPERATOR_EXPRESSION_OPEN] = { "(", 7, eval_nop },
386
+ [EVAL_OPERATOR_AND] = { "&&", 2, 2, eval_and },
387
+ [EVAL_OPERATOR_OR] = { "||", 2, 2, eval_or },
388
+ [EVAL_OPERATOR_GREATER_THAN_OR_EQUAL] = { ">=", 3, 2, eval_greater_than_or_equal },
389
+ [EVAL_OPERATOR_LESS_THAN_OR_EQUAL] = { "<=", 3, 2, eval_less_than_or_equal },
390
+ [EVAL_OPERATOR_NOT_EQUAL] = { "!=", 3, 2, eval_not_equal },
391
+ [EVAL_OPERATOR_EQUAL] = { "==", 3, 2, eval_equal },
392
+ [EVAL_OPERATOR_LESS] = { "<", 3, 2, eval_less },
393
+ [EVAL_OPERATOR_GREATER] = { ">", 3, 2, eval_greater },
394
+ [EVAL_OPERATOR_PLUS] = { "+", 4, 2, eval_plus },
395
+ [EVAL_OPERATOR_MINUS] = { "-", 4, 2, eval_minus },
396
+ [EVAL_OPERATOR_MULTIPLY] = { "*", 5, 2, eval_multiply },
397
+ [EVAL_OPERATOR_DIVIDE] = { "/", 5, 2, eval_divide },
398
+ [EVAL_OPERATOR_NOT] = { "!", 6, 1, eval_not },
399
+ [EVAL_OPERATOR_SIGN_PLUS] = { "+", 6, 1, eval_sign_plus },
400
+ [EVAL_OPERATOR_SIGN_MINUS] = { "-", 6, 1, eval_sign_minus },
401
+ [EVAL_OPERATOR_NOP] = { NULL, 7, 1, eval_nop },
402
+ [EVAL_OPERATOR_VALUE] = { NULL, 7, 1, eval_nop },
403
+ [EVAL_OPERATOR_EXPRESSION_OPEN] = { "(", 7, 1, eval_nop },
404
405
// this should exist in our evaluation list
356
- [EVAL_OPERATOR_EXPRESSION_CLOSE] = { ")", 7, eval_nop }
406
+ [EVAL_OPERATOR_EXPRESSION_CLOSE] = { ")", 7, 1, eval_nop }
407
};
408
409
#define eval_precedence(operator) (operators[(unsigned char)(operator)].precedence)
410
411
+static inline calculated_number eval_operand(EVAL_OPERAND *op, int *error) {
412
+ if(unlikely(op->count != operators[op->operator].parameters)) {
413
+ *error = EVAL_ERROR_INVALID_NUMBER_OF_OPERANDS;
414
+ return 0;
415
+ }
416
+
417
+ calculated_number n = operators[op->operator].eval(op, error);
418
+
419
+ return eval_check_number(n, error);
420
+}
421
+
422
// ----------------------------------------------------------------------------
423
424
static inline char parse_operator(const char **string, int *precedence) {
@@ -403,11 +464,6 @@ static inline void operand_set_value_literal(EVAL_OPERAND *op, int pos, calculat
464
op->ops[pos].number = value;
465
}
466
406
-// forward definitions
407
-static inline void operand_free(EVAL_OPERAND *op);
408
-static inline EVAL_OPERAND *parse_operand(const char **string, int *error);
409
-static inline EVAL_OPERAND *parse_operand1(const char **string, int *error);
410
-
467
static inline void variable_free(VARIABLE *v) {
468
free(v);
469
}
@@ -572,6 +628,18 @@ const char *eval_error(int error) {
628
case EVAL_ERROR_MISSING_OPERATOR:
629
return "expected operator";
630
631
+ case EVAL_ERROR_INVALID_VALUE:
632
+ return "invalid value structure - internal error";
633
+
634
+ case EVAL_ERROR_INVALID_NUMBER_OF_OPERANDS:
635
+ return "wrong number of operands for operation - internal error";
636
+
637
+ case EVAL_ERROR_VALUE_IS_NAN:
638
+ return "value or variable is missing or is not a number";
639
+
640
+ case EVAL_ERROR_VALUE_IS_INFINITE:
641
+ return "computed value is infinite";
642
+
643
default:
644
return "unknown error";
645
}
@@ -596,6 +664,19 @@ EVAL_OPERAND *parse_expression(const char *string, const char **failed_at, int *
664
return op;
665
}
666
667
+calculated_number evaluate_expression(EVAL_OPERAND *expression, int *error) {
668
+ int err = EVAL_ERROR_OK;
669
+ calculated_number ret = eval_operand(expression, &err);
670
+
671
+ if(err != EVAL_ERROR_OK) {
672
+ error("Failed to execute expression with error %d (%s)", err, eval_error(err));
673
+ if(error) *error = err;
674
+ return 0;
675
+ }
676
+
677
+ return ret;
678
+}
679
+
680
void free_expression(EVAL_OPERAND *op) {
681
if(op) operand_free(op);
682
}
src/eval.h
+10
-1
@@ -34,11 +34,19 @@ typedef struct variable {
34
#define EVAL_OPERATOR_SIGN_MINUS 'M'
35
36
#define EVAL_ERROR_OK 0
37
+
38
+// parsing errors
39
#define EVAL_ERROR_MISSING_CLOSE_SUBEXPRESSION 1
40
#define EVAL_ERROR_UNKNOWN_OPERAND 2
41
#define EVAL_ERROR_MISSING_OPERAND 3
42
#define EVAL_ERROR_MISSING_OPERATOR 4
43
44
+// evaluation errors
45
+#define EVAL_ERROR_INVALID_VALUE 5
46
+#define EVAL_ERROR_INVALID_NUMBER_OF_OPERANDS 6
47
+#define EVAL_ERROR_VALUE_IS_NAN 7
48
+#define EVAL_ERROR_VALUE_IS_INFINITE 8
49
+
50
typedef struct eval_value {
51
int type;
52
@@ -51,7 +59,7 @@ typedef struct eval_value {
59
60
typedef struct eval_operand {
61
int id;
54
- char operator;
62
+ unsigned char operator;
63
int precedence;
64
65
int count;
@@ -59,6 +67,7 @@ typedef struct eval_operand {
67
} EVAL_OPERAND;
68
69
extern EVAL_OPERAND *parse_expression(const char *string, const char **failed_at, int *error);
70
+extern calculated_number evaluate_expression(EVAL_OPERAND *expression, int *error);
71
extern void free_expression(EVAL_OPERAND *op);
72
73
#endif //NETDATA_EVAL_H