1 /* Simple expression parser */
4 #include "util/debug.h"
13 %parse-param { double *final_val }
14 %parse-param { struct parse_ctx *ctx }
15 %parse-param { const char **pp }
16 %lex-param { const char **pp }
34 static int expr__lex(YYSTYPE *res, const char **pp);
36 static void expr__error(double *final_val __maybe_unused,
37 struct parse_ctx *ctx __maybe_unused,
38 const char **pp __maybe_unused,
44 static int lookup_id(struct parse_ctx *ctx, char *id, double *val)
48 for (i = 0; i < ctx->num_ids; i++) {
49 if (!strcasecmp(ctx->ids[i].name, id)) {
50 *val = ctx->ids[i].val;
60 all_expr: expr { *final_val = $1; }
64 | ID { if (lookup_id(ctx, $1, &$$) < 0) {
65 pr_debug("%s not found", $1);
69 | expr '+' expr { $$ = $1 + $3; }
70 | expr '-' expr { $$ = $1 - $3; }
71 | expr '*' expr { $$ = $1 * $3; }
72 | expr '/' expr { if ($3 == 0) YYABORT; $$ = $1 / $3; }
73 | expr '%' expr { if ((long)$3 == 0) YYABORT; $$ = (long)$1 % (long)$3; }
74 | '-' expr %prec NEG { $$ = -$2; }
75 | '(' expr ')' { $$ = $2; }
80 static int expr__symbol(YYSTYPE *res, const char *p, const char **pp)
85 while (isalnum(*p) || *p == '_' || *p == '.') {
86 if (p - s >= MAXIDLEN)
95 static int expr__lex(YYSTYPE *res, const char **pp)
107 return expr__symbol(res, p - 1, pp);
108 case '0' ... '9': case '.':
109 res->num = strtod(s, (char **)&p);
120 /* Caller must make sure id is allocated */
121 void expr__add_id(struct parse_ctx *ctx, const char *name, double val)
124 assert(ctx->num_ids < MAX_PARSE_ID);
125 idx = ctx->num_ids++;
126 ctx->ids[idx].name = name;
127 ctx->ids[idx].val = val;
130 void expr__ctx_init(struct parse_ctx *ctx)
135 int expr__find_other(const char *p, const char *one, const char ***other,
138 const char *orig = p;
142 *other = malloc((EXPR_MAX_OTHER + 1) * sizeof(char *));
149 int tok = expr__lex(&val, &p);
154 if (tok == ID && strcasecmp(one, val.id)) {
155 if (num_other >= EXPR_MAX_OTHER - 1) {
156 pr_debug("Too many extra events in %s\n", orig);
159 (*other)[num_other] = strdup(val.id);
160 if (!(*other)[num_other])
165 (*other)[num_other] = NULL;
166 *num_otherp = num_other;