mirror of
https://github.com/torvalds/linux.git
synced 2024-12-24 20:01:55 +00:00
acf71b05d1
Adding computation (expr__parse call) of referenced metric at the point when it needs to be resolved during the parent metric computation. Once the inner metric is computed, the result is stored and used if there's another usage of that metric. Signed-off-by: Jiri Olsa <jolsa@kernel.org> Reviewed-by: Kajol Jain <kjain@linux.ibm.com> Acked-by: Ian Rogers <irogers@google.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Andi Kleen <ak@linux.intel.com> Cc: John Garry <john.garry@huawei.com> Cc: Michael Petlan <mpetlan@redhat.com> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Paul Clarke <pc@us.ibm.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Stephane Eranian <eranian@google.com> Link: http://lore.kernel.org/lkml/20200719181320.785305-12-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
128 lines
2.4 KiB
Plaintext
128 lines
2.4 KiB
Plaintext
/* Simple expression parser */
|
|
%{
|
|
#define YYDEBUG 1
|
|
#include <stdio.h>
|
|
#include "util.h"
|
|
#include "util/debug.h"
|
|
#include <stdlib.h> // strtod()
|
|
#define IN_EXPR_Y 1
|
|
#include "expr.h"
|
|
#include "smt.h"
|
|
#include <string.h>
|
|
|
|
static double d_ratio(double val0, double val1)
|
|
{
|
|
if (val1 == 0) {
|
|
return 0;
|
|
}
|
|
return val0 / val1;
|
|
}
|
|
|
|
%}
|
|
|
|
%define api.pure full
|
|
|
|
%parse-param { double *final_val }
|
|
%parse-param { struct expr_parse_ctx *ctx }
|
|
%parse-param {void *scanner}
|
|
%lex-param {void* scanner}
|
|
|
|
%union {
|
|
double num;
|
|
char *str;
|
|
}
|
|
|
|
%token EXPR_PARSE EXPR_OTHER EXPR_ERROR
|
|
%token <num> NUMBER
|
|
%token <str> ID
|
|
%destructor { free ($$); } <str>
|
|
%token MIN MAX IF ELSE SMT_ON D_RATIO
|
|
%left MIN MAX IF
|
|
%left '|'
|
|
%left '^'
|
|
%left '&'
|
|
%left '<' '>'
|
|
%left '-' '+'
|
|
%left '*' '/' '%'
|
|
%left NEG NOT
|
|
%type <num> expr if_expr
|
|
|
|
%{
|
|
static void expr_error(double *final_val __maybe_unused,
|
|
struct expr_parse_ctx *ctx __maybe_unused,
|
|
void *scanner,
|
|
const char *s)
|
|
{
|
|
pr_debug("%s\n", s);
|
|
}
|
|
|
|
%}
|
|
%%
|
|
|
|
start:
|
|
EXPR_PARSE all_expr
|
|
|
|
|
EXPR_OTHER all_other
|
|
|
|
all_other: all_other other
|
|
|
|
|
|
|
other: ID
|
|
{
|
|
expr__add_id(ctx, $1);
|
|
}
|
|
|
|
|
MIN | MAX | IF | ELSE | SMT_ON | NUMBER | '|' | '^' | '&' | '-' | '+' | '*' | '/' | '%' | '(' | ')' | ','
|
|
|
|
|
'<' | '>' | D_RATIO
|
|
|
|
all_expr: if_expr { *final_val = $1; }
|
|
;
|
|
|
|
if_expr:
|
|
expr IF expr ELSE expr { $$ = $3 ? $1 : $5; }
|
|
| expr
|
|
;
|
|
|
|
expr: NUMBER
|
|
| ID {
|
|
struct expr_id_data *data;
|
|
|
|
if (expr__resolve_id(ctx, $1, &data)) {
|
|
free($1);
|
|
YYABORT;
|
|
}
|
|
|
|
$$ = data->val;
|
|
free($1);
|
|
}
|
|
| expr '|' expr { $$ = (long)$1 | (long)$3; }
|
|
| expr '&' expr { $$ = (long)$1 & (long)$3; }
|
|
| expr '^' expr { $$ = (long)$1 ^ (long)$3; }
|
|
| expr '<' expr { $$ = $1 < $3; }
|
|
| expr '>' expr { $$ = $1 > $3; }
|
|
| expr '+' expr { $$ = $1 + $3; }
|
|
| expr '-' expr { $$ = $1 - $3; }
|
|
| expr '*' expr { $$ = $1 * $3; }
|
|
| expr '/' expr { if ($3 == 0) {
|
|
pr_debug("division by zero\n");
|
|
YYABORT;
|
|
}
|
|
$$ = $1 / $3;
|
|
}
|
|
| expr '%' expr { if ((long)$3 == 0) {
|
|
pr_debug("division by zero\n");
|
|
YYABORT;
|
|
}
|
|
$$ = (long)$1 % (long)$3;
|
|
}
|
|
| '-' expr %prec NEG { $$ = -$2; }
|
|
| '(' if_expr ')' { $$ = $2; }
|
|
| MIN '(' expr ',' expr ')' { $$ = $3 < $5 ? $3 : $5; }
|
|
| MAX '(' expr ',' expr ')' { $$ = $3 > $5 ? $3 : $5; }
|
|
| SMT_ON { $$ = smt_on() > 0; }
|
|
| D_RATIO '(' expr ',' expr ')' { $$ = d_ratio($3,$5); }
|
|
;
|
|
|
|
%%
|