3 static inline void skip_spaces(const char **string) {
4 const char *s = *string;
5 while(isspace(*s)) s++;
9 // ----------------------------------------------------------------------------
10 // operators that work on 2 operands
12 static inline int isoperatorterm_word(const char s) {
13 if(isspace(s) || s == '(' || s == '$' || s == '!' || s == '-' || s == '+' || isdigit(s)) return 1;
17 static inline int isoperatorterm_symbol(const char s) {
18 if(isoperatorterm_word(s) || isalpha(s)) return 1;
22 static inline int parse_and(const char **string) {
23 const char *s = *string;
26 if((s[0] == 'A' || s[0] == 'a') && (s[1] == 'N' || s[1] == 'n') && (s[2] == 'D' || s[2] == 'd') && isoperatorterm_word(s[3])) {
32 if(s[0] == '&' && s[1] == '&' && isoperatorterm_symbol(s[2])) {
40 static inline int parse_or(const char **string) {
41 const char *s = *string;
44 if((s[0] == 'O' || s[0] == 'o') && (s[1] == 'R' || s[1] == 'r') && isoperatorterm_word(s[2])) {
50 if(s[0] == '|' && s[1] == '|' && isoperatorterm_symbol(s[2])) {
58 static inline int parse_greater_than_or_equal(const char **string) {
59 const char *s = *string;
62 if(s[0] == '>' && s[1] == '=' && isoperatorterm_symbol(s[2])) {
70 static inline int parse_less_than_or_equal(const char **string) {
71 const char *s = *string;
74 if (s[0] == '<' && s[1] == '=' && isoperatorterm_symbol(s[2])) {
82 static inline int parse_greater(const char **string) {
83 const char *s = *string;
86 if(s[0] == '>' && isoperatorterm_symbol(s[1])) {
94 static inline int parse_less(const char **string) {
95 const char *s = *string;
98 if(s[0] == '<' && isoperatorterm_symbol(s[1])) {
106 static inline int parse_equal(const char **string) {
107 const char *s = *string;
110 if(s[0] == '=' && s[1] == '=' && isoperatorterm_symbol(s[2])) {
116 if(s[0] == '=' && isoperatorterm_symbol(s[1])) {
124 static inline int parse_not_equal(const char **string) {
125 const char *s = *string;
128 if(s[0] == '!' && s[1] == '=' && isoperatorterm_symbol(s[2])) {
134 if(s[0] == '<' && s[1] == '>' && isoperatorterm_symbol(s[2])) {
141 static inline int parse_multiply(const char **string) {
142 const char *s = *string;
145 if(s[0] == '*' && isoperatorterm_symbol(s[1])) {
153 static inline int parse_divide(const char **string) {
154 const char *s = *string;
157 if(s[0] == '/' && isoperatorterm_symbol(s[1])) {
165 static inline int parse_minus(const char **string) {
166 const char *s = *string;
169 if(s[0] == '-' && isoperatorterm_symbol(s[1])) {
177 static inline int parse_plus(const char **string) {
178 const char *s = *string;
181 if(s[0] == '+' && isoperatorterm_symbol(s[1])) {
189 static inline int parse_open_subexpression(const char **string) {
190 const char *s = *string;
201 static inline int parse_close_subexpression(const char **string) {
202 const char *s = *string;
213 static inline int parse_literal(const char **string, calculated_number *number) {
215 *number = strtold(*string, &end);
216 if(!end || *string == end) return 0;
222 // ----------------------------------------------------------------------------
223 // operators that affect a single operand
225 static inline int parse_not(const char **string) {
226 const char *s = *string;
229 if((s[0] == 'N' || s[0] == 'n') && (s[1] == 'O' || s[1] == 'o') && (s[2] == 'T' || s[2] == 't') && isoperatorterm_word(s[3])) {
234 if(s[0] == EVAL_OPERATOR_NOT) {
242 static struct operator_parser {
244 int (*parse)(const char **);
245 } operator_parsers[] = {
246 // the order in this list is important!
247 // the first matching will be used
248 // so place the longer of overlapping ones
251 { EVAL_OPERATOR_AND, parse_and },
252 { EVAL_OPERATOR_OR, parse_or },
253 { EVAL_OPERATOR_GREATER_THAN_OR_EQUAL, parse_greater_than_or_equal },
254 { EVAL_OPERATOR_LESS_THAN_OR_EQUAL, parse_less_than_or_equal },
255 { EVAL_OPERATOR_NOT_EQUAL, parse_not_equal },
256 { EVAL_OPERATOR_EQUAL, parse_equal },
257 { EVAL_OPERATOR_LESS, parse_less },
258 { EVAL_OPERATOR_GREATER, parse_greater },
259 { EVAL_OPERATOR_PLUS, parse_plus },
260 { EVAL_OPERATOR_MINUS, parse_minus },
261 { EVAL_OPERATOR_MULTIPLY, parse_multiply },
262 { EVAL_OPERATOR_DIVIDE, parse_divide },
273 { EVAL_OPERATOR_NOP, NULL }
276 // ----------------------------------------------------------------------------
277 // evaluation of operations
279 calculated_number eval_and(EVAL_OPERAND *op) {
282 calculated_number eval_or(EVAL_OPERAND *op) {
285 calculated_number eval_greater_than_or_equal(EVAL_OPERAND *op) {
288 calculated_number eval_less_than_or_equal(EVAL_OPERAND *op) {
291 calculated_number eval_not_equal(EVAL_OPERAND *op) {
294 calculated_number eval_equal(EVAL_OPERAND *op) {
297 calculated_number eval_less(EVAL_OPERAND *op) {
300 calculated_number eval_greater(EVAL_OPERAND *op) {
303 calculated_number eval_plus(EVAL_OPERAND *op) {
306 calculated_number eval_minus(EVAL_OPERAND *op) {
309 calculated_number eval_multiply(EVAL_OPERAND *op) {
312 calculated_number eval_divide(EVAL_OPERAND *op) {
315 calculated_number eval_nop(EVAL_OPERAND *op) {
318 calculated_number eval_not(EVAL_OPERAND *op) {
321 calculated_number eval_sign_plus(EVAL_OPERAND *op) {
324 calculated_number eval_sign_minus(EVAL_OPERAND *op) {
328 static struct operator {
329 const char *print_as;
331 calculated_number (*eval)(EVAL_OPERAND *op);
333 // this is a random access array
334 // we always access it with a known EVAL_OPERATOR_X
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 },
355 // this should exist in our evaluation list
356 [EVAL_OPERATOR_EXPRESSION_CLOSE] = { ")", 7, eval_nop }
359 #define eval_precedence(operator) (operators[(unsigned char)(operator)].precedence)
361 // ----------------------------------------------------------------------------
363 static inline char parse_operator(const char **string, int *precedence) {
367 for(i = 0 ; operator_parsers[i].parse != NULL ; i++)
368 if(operator_parsers[i].parse(string)) {
369 if(precedence) *precedence = eval_precedence(operator_parsers[i].id);
370 return operator_parsers[i].id;
373 return EVAL_OPERATOR_NOP;
377 static inline EVAL_OPERAND *operand_alloc(int count) {
380 EVAL_OPERAND *op = calloc(1, sizeof(EVAL_OPERAND) + (sizeof(EVAL_VALUE) * count));
381 if(!op) fatal("Cannot allocate memory for OPERAND with %d slots", count);
384 op->operator = EVAL_OPERATOR_NOP;
385 op->precedence = eval_precedence(EVAL_OPERATOR_NOP);
390 static inline void operand_set_value_operand(EVAL_OPERAND *op, int pos, EVAL_OPERAND *value) {
392 fatal("Invalid request to set position %d of OPERAND that has only %d values", pos + 1, op->count + 1);
394 op->ops[pos].type = EVAL_VALUE_EXPRESSION;
395 op->ops[pos].expression = value;
398 static inline void operand_set_value_literal(EVAL_OPERAND *op, int pos, calculated_number value) {
400 fatal("Invalid request to set position %d of OPERAND that has only %d values", pos + 1, op->count + 1);
402 op->ops[pos].type = EVAL_VALUE_NUMBER;
403 op->ops[pos].number = value;
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);
411 static inline void variable_free(VARIABLE *v) {
415 static inline void value_free(EVAL_VALUE *v) {
417 case EVAL_VALUE_EXPRESSION:
418 operand_free(v->expression);
421 case EVAL_VALUE_VARIABLE:
422 variable_free(v->variable);
430 static inline void operand_free(EVAL_OPERAND *op) {
433 for(i = op->count - 1; i >= 0 ;i--)
434 value_free(&op->ops[i]);
440 static inline EVAL_OPERAND *parse_operand_with_operator(const char **string, char type, int *error) {
441 EVAL_OPERAND *sub = parse_operand1(string, error);
442 if(!sub) return NULL;
444 EVAL_OPERAND *op = operand_alloc(1);
446 operand_set_value_operand(op, 0, sub);
450 static inline EVAL_OPERAND *parse_operand1(const char **string, int *error) {
451 EVAL_OPERAND *op1 = NULL;
452 calculated_number number;
454 *error = EVAL_ERROR_OK;
458 *error = EVAL_ERROR_MISSING_OPERAND;
462 if(parse_not(string)) {
463 op1 = parse_operand_with_operator(string, EVAL_OPERATOR_NOT, error);
464 op1->precedence = eval_precedence(EVAL_OPERATOR_NOT);
466 else if(parse_plus(string)) {
467 op1 = parse_operand_with_operator(string, EVAL_OPERATOR_SIGN_PLUS, error);
468 op1->precedence = eval_precedence(EVAL_OPERATOR_SIGN_PLUS);
470 else if(parse_minus(string)) {
471 op1 = parse_operand_with_operator(string, EVAL_OPERATOR_SIGN_MINUS, error);
472 op1->precedence = eval_precedence(EVAL_OPERATOR_SIGN_MINUS);
474 else if(parse_open_subexpression(string)) {
475 EVAL_OPERAND *sub = parse_operand(string, error);
477 op1 = operand_alloc(1);
478 op1->operator = EVAL_OPERATOR_EXPRESSION_OPEN;
479 op1->precedence = eval_precedence(EVAL_OPERATOR_EXPRESSION_OPEN);
480 operand_set_value_operand(op1, 0, sub);
481 if(!parse_close_subexpression(string)) {
482 *error = EVAL_ERROR_MISSING_CLOSE_SUBEXPRESSION;
488 // else if(parse_variable(string)) {
491 else if(parse_literal(string, &number)) {
492 op1 = operand_alloc(1);
493 op1->operator = EVAL_OPERATOR_VALUE;
494 operand_set_value_literal(op1, 0, number);
497 *error = EVAL_ERROR_UNKNOWN_OPERAND;
499 *error = EVAL_ERROR_MISSING_OPERAND;
504 static inline EVAL_OPERAND *parse_operand_rest(const char **string, int *error, EVAL_OPERAND *op1) {
505 EVAL_OPERAND *op2 = NULL;
509 operator = parse_operator(string, &precedence);
512 if(operator != EVAL_OPERATOR_NOP) {
513 op2 = parse_operand1(string, error);
519 EVAL_OPERAND *op = operand_alloc(2);
520 op->operator = operator;
521 op->precedence = precedence;
523 operand_set_value_operand(op, 0, op1);
524 operand_set_value_operand(op, 1, op2);
526 if(op->precedence > op1->precedence && op1->count == 2 && op1->operator != '(' && op1->ops[1].type == EVAL_VALUE_EXPRESSION) {
527 operand_set_value_operand(op, 0, op1->ops[1].expression);
528 op1->ops[1].expression = op;
532 return parse_operand_rest(string, error, op);
534 else if(**string == EVAL_OPERATOR_EXPRESSION_CLOSE) {
538 if(op1) operand_free(op1);
540 *error = EVAL_ERROR_MISSING_OPERATOR;
546 static inline EVAL_OPERAND *parse_operand(const char **string, int *error) {
547 EVAL_OPERAND *op1 = NULL;
549 op1 = parse_operand1(string, error);
551 *error = EVAL_ERROR_MISSING_OPERAND;
555 return parse_operand_rest(string, error, op1);
558 const char *eval_error(int error) {
563 case EVAL_ERROR_MISSING_CLOSE_SUBEXPRESSION:
564 return "missing closing parenthesis";
566 case EVAL_ERROR_UNKNOWN_OPERAND:
567 return "unknown operand";
569 case EVAL_ERROR_MISSING_OPERAND:
570 return "expected operand";
572 case EVAL_ERROR_MISSING_OPERATOR:
573 return "expected operator";
576 return "unknown error";
580 EVAL_OPERAND *parse_expression(const char *string, const char **failed_at, int *error) {
582 int err = EVAL_ERROR_OK;
583 unsigned long pos = 0;
586 EVAL_OPERAND *op = parse_operand(&s, &err);
588 if (failed_at) *failed_at = s;
589 if (error) *error = err;
592 pos = s - string + 1;
593 error("failed to parse expression '%s': %s at character %lu (i.e.: '%s').", string, eval_error(err), pos, s);
599 void free_expression(EVAL_OPERAND *op) {
600 if(op) operand_free(op);