mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-24 00:45:19 +07:00
26226a9772
Adding expr flex code instead of the manual parser code. So it's easily extensible in upcoming changes. The new flex code is in flex.l object and gets compiled like all the other flexers we use. It's defined as flex reentrant parser. It's used by both expr__parse and expr__find_other interfaces by separating the starting point. There's no intended change of functionality ;-) the test expr is passing. Signed-off-by: Jiri Olsa <jolsa@kernel.org> Reviewed-by: Andi Kleen <ak@linux.intel.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: John Garry <john.garry@huawei.com> Cc: Kajol Jain <kjain@linux.ibm.com> Cc: Michael Petlan <mpetlan@redhat.com> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Ravi Bangoria <ravi.bangoria@linux.ibm.com> Link: http://lore.kernel.org/lkml/20200228093616.67125-3-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
116 lines
2.2 KiB
Plaintext
116 lines
2.2 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>
|
|
|
|
%}
|
|
|
|
%define api.pure full
|
|
|
|
%parse-param { double *final_val }
|
|
%parse-param { struct 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
|
|
%token MIN MAX IF ELSE SMT_ON
|
|
%left MIN MAX IF
|
|
%left '|'
|
|
%left '^'
|
|
%left '&'
|
|
%left '-' '+'
|
|
%left '*' '/' '%'
|
|
%left NEG NOT
|
|
%type <num> expr if_expr
|
|
|
|
%{
|
|
static void expr_error(double *final_val __maybe_unused,
|
|
struct parse_ctx *ctx __maybe_unused,
|
|
void *scanner,
|
|
const char *s)
|
|
{
|
|
pr_debug("%s\n", s);
|
|
}
|
|
|
|
static int lookup_id(struct parse_ctx *ctx, char *id, double *val)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < ctx->num_ids; i++) {
|
|
if (!strcasecmp(ctx->ids[i].name, id)) {
|
|
*val = ctx->ids[i].val;
|
|
return 0;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
%}
|
|
%%
|
|
|
|
start:
|
|
EXPR_PARSE all_expr
|
|
|
|
|
EXPR_OTHER all_other
|
|
|
|
all_other: all_other other
|
|
|
|
|
|
|
other: ID
|
|
{
|
|
if (ctx->num_ids + 1 >= EXPR_MAX_OTHER) {
|
|
pr_err("failed: way too many variables");
|
|
YYABORT;
|
|
}
|
|
|
|
ctx->ids[ctx->num_ids++].name = $1;
|
|
}
|
|
|
|
|
MIN | MAX | IF | ELSE | SMT_ON | NUMBER | '|' | '^' | '&' | '-' | '+' | '*' | '/' | '%' | '(' | ')'
|
|
|
|
|
|
all_expr: if_expr { *final_val = $1; }
|
|
;
|
|
|
|
if_expr:
|
|
expr IF expr ELSE expr { $$ = $3 ? $1 : $5; }
|
|
| expr
|
|
;
|
|
|
|
expr: NUMBER
|
|
| ID { if (lookup_id(ctx, $1, &$$) < 0) {
|
|
pr_debug("%s not found\n", $1);
|
|
YYABORT;
|
|
}
|
|
}
|
|
| 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 { if ($3 == 0) YYABORT; $$ = $1 / $3; }
|
|
| expr '%' expr { if ((long)$3 == 0) 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; }
|
|
;
|
|
|
|
%%
|