linux-stable/tools/perf/util/expr.l
Jiri Olsa 26226a9772 perf expr: Move expr lexer to flex
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>
2020-03-09 21:43:24 -03:00

114 lines
1.9 KiB
Text

%option prefix="expr_"
%option reentrant
%option bison-bridge
%{
#include <linux/compiler.h>
#include "expr.h"
#include "expr-bison.h"
char *expr_get_text(yyscan_t yyscanner);
YYSTYPE *expr_get_lval(yyscan_t yyscanner);
static int __value(YYSTYPE *yylval, char *str, int base, int token)
{
u64 num;
errno = 0;
num = strtoull(str, NULL, base);
if (errno)
return EXPR_ERROR;
yylval->num = num;
return token;
}
static int value(yyscan_t scanner, int base)
{
YYSTYPE *yylval = expr_get_lval(scanner);
char *text = expr_get_text(scanner);
return __value(yylval, text, base, NUMBER);
}
/*
* Allow @ instead of / to be able to specify pmu/event/ without
* conflicts with normal division.
*/
static char *normalize(char *str)
{
char *ret = str;
char *dst = str;
while (*str) {
if (*str == '@')
*dst++ = '/';
else if (*str == '\\')
*dst++ = *++str;
else
*dst++ = *str;
str++;
}
*dst = 0x0;
return ret;
}
static int str(yyscan_t scanner, int token)
{
YYSTYPE *yylval = expr_get_lval(scanner);
char *text = expr_get_text(scanner);
yylval->str = normalize(strdup(text));
if (!yylval->str)
return EXPR_ERROR;
yylval->str = normalize(yylval->str);
return token;
}
%}
number [0-9]+
sch [-,=]
spec \\{sch}
sym [0-9a-zA-Z_\.:@]+
symbol {spec}*{sym}*{spec}*{sym}*
%%
{
int start_token;
start_token = parse_events_get_extra(yyscanner);
if (start_token) {
parse_events_set_extra(NULL, yyscanner);
return start_token;
}
}
max { return MAX; }
min { return MIN; }
if { return IF; }
else { return ELSE; }
#smt_on { return SMT_ON; }
{number} { return value(yyscanner, 10); }
{symbol} { return str(yyscanner, ID); }
"|" { return '|'; }
"^" { return '^'; }
"&" { return '&'; }
"-" { return '-'; }
"+" { return '+'; }
"*" { return '*'; }
"/" { return '/'; }
"%" { return '%'; }
"(" { return '('; }
")" { return ')'; }
"," { return ','; }
. { }
%%
int expr_wrap(void *scanner __maybe_unused)
{
return 1;
}