162306a36Sopenharmony_ci%option prefix="expr_"
262306a36Sopenharmony_ci%option reentrant
362306a36Sopenharmony_ci%option bison-bridge
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci%{
662306a36Sopenharmony_ci#include <linux/compiler.h>
762306a36Sopenharmony_ci#include "expr.h"
862306a36Sopenharmony_ci#include "expr-bison.h"
962306a36Sopenharmony_ci#include <math.h>
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_cichar *expr_get_text(yyscan_t yyscanner);
1262306a36Sopenharmony_ciYYSTYPE *expr_get_lval(yyscan_t yyscanner);
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_cistatic double __value(YYSTYPE *yylval, char *str, int token)
1562306a36Sopenharmony_ci{
1662306a36Sopenharmony_ci	double num;
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci	errno = 0;
1962306a36Sopenharmony_ci	num = strtod(str, NULL);
2062306a36Sopenharmony_ci	if (errno)
2162306a36Sopenharmony_ci		return EXPR_ERROR;
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci	yylval->num = num;
2462306a36Sopenharmony_ci	return token;
2562306a36Sopenharmony_ci}
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_cistatic int value(yyscan_t scanner)
2862306a36Sopenharmony_ci{
2962306a36Sopenharmony_ci	YYSTYPE *yylval = expr_get_lval(scanner);
3062306a36Sopenharmony_ci	char *text = expr_get_text(scanner);
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci	return __value(yylval, text, NUMBER);
3362306a36Sopenharmony_ci}
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci/*
3662306a36Sopenharmony_ci * Allow @ instead of / to be able to specify pmu/event/ without
3762306a36Sopenharmony_ci * conflicts with normal division.
3862306a36Sopenharmony_ci */
3962306a36Sopenharmony_cistatic char *normalize(char *str, int runtime)
4062306a36Sopenharmony_ci{
4162306a36Sopenharmony_ci	char *ret = str;
4262306a36Sopenharmony_ci	char *dst = str;
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci	while (*str) {
4562306a36Sopenharmony_ci		if (*str == '\\') {
4662306a36Sopenharmony_ci			*dst++ = *++str;
4762306a36Sopenharmony_ci			if (!*str)
4862306a36Sopenharmony_ci				break;
4962306a36Sopenharmony_ci		}
5062306a36Sopenharmony_ci		else if (*str == '?') {
5162306a36Sopenharmony_ci			char *paramval;
5262306a36Sopenharmony_ci			int i = 0;
5362306a36Sopenharmony_ci			int size = asprintf(&paramval, "%d", runtime);
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci			if (size < 0)
5662306a36Sopenharmony_ci				*dst++ = '0';
5762306a36Sopenharmony_ci			else {
5862306a36Sopenharmony_ci				while (i < size)
5962306a36Sopenharmony_ci					*dst++ = paramval[i++];
6062306a36Sopenharmony_ci				free(paramval);
6162306a36Sopenharmony_ci			}
6262306a36Sopenharmony_ci		}
6362306a36Sopenharmony_ci		else
6462306a36Sopenharmony_ci			*dst++ = *str;
6562306a36Sopenharmony_ci		str++;
6662306a36Sopenharmony_ci	}
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci	*dst = 0x0;
6962306a36Sopenharmony_ci	return ret;
7062306a36Sopenharmony_ci}
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_cistatic int str(yyscan_t scanner, int token, int runtime)
7362306a36Sopenharmony_ci{
7462306a36Sopenharmony_ci	YYSTYPE *yylval = expr_get_lval(scanner);
7562306a36Sopenharmony_ci	char *text = expr_get_text(scanner);
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci	yylval->str = normalize(strdup(text), runtime);
7862306a36Sopenharmony_ci	if (!yylval->str)
7962306a36Sopenharmony_ci		return EXPR_ERROR;
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ci	yylval->str = normalize(yylval->str, runtime);
8262306a36Sopenharmony_ci	return token;
8362306a36Sopenharmony_ci}
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_cistatic int literal(yyscan_t scanner, const struct expr_scanner_ctx *sctx)
8662306a36Sopenharmony_ci{
8762306a36Sopenharmony_ci	YYSTYPE *yylval = expr_get_lval(scanner);
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci	yylval->num = expr__get_literal(expr_get_text(scanner), sctx);
9062306a36Sopenharmony_ci	if (isnan(yylval->num)) {
9162306a36Sopenharmony_ci		if (!sctx->is_test)
9262306a36Sopenharmony_ci			return EXPR_ERROR;
9362306a36Sopenharmony_ci		yylval->num = 1;
9462306a36Sopenharmony_ci	}
9562306a36Sopenharmony_ci	return LITERAL;
9662306a36Sopenharmony_ci}
9762306a36Sopenharmony_ci%}
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_cinumber		([0-9]+\.?[0-9]*|[0-9]*\.?[0-9]+)(e-?[0-9]+)?
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_cisch		[-,=]
10262306a36Sopenharmony_cispec		\\{sch}
10362306a36Sopenharmony_cisym		[0-9a-zA-Z_\.:@?]+
10462306a36Sopenharmony_cisymbol		({spec}|{sym})+
10562306a36Sopenharmony_ciliteral		#[0-9a-zA-Z_\.\-]+
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ci%%
10862306a36Sopenharmony_ci	struct expr_scanner_ctx *sctx = expr_get_extra(yyscanner);
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_cid_ratio		{ return D_RATIO; }
11162306a36Sopenharmony_cimax		{ return MAX; }
11262306a36Sopenharmony_cimin		{ return MIN; }
11362306a36Sopenharmony_ciif		{ return IF; }
11462306a36Sopenharmony_cielse		{ return ELSE; }
11562306a36Sopenharmony_cisource_count	{ return SOURCE_COUNT; }
11662306a36Sopenharmony_cihas_event	{ return HAS_EVENT; }
11762306a36Sopenharmony_cistrcmp_cpuid_str	{ return STRCMP_CPUID_STR; }
11862306a36Sopenharmony_ci{literal}	{ return literal(yyscanner, sctx); }
11962306a36Sopenharmony_ci{number}	{ return value(yyscanner); }
12062306a36Sopenharmony_ci{symbol}	{ return str(yyscanner, ID, sctx->runtime); }
12162306a36Sopenharmony_ci"|"		{ return '|'; }
12262306a36Sopenharmony_ci"^"		{ return '^'; }
12362306a36Sopenharmony_ci"&"		{ return '&'; }
12462306a36Sopenharmony_ci"<"		{ return '<'; }
12562306a36Sopenharmony_ci">"		{ return '>'; }
12662306a36Sopenharmony_ci"-"		{ return '-'; }
12762306a36Sopenharmony_ci"+"		{ return '+'; }
12862306a36Sopenharmony_ci"*"		{ return '*'; }
12962306a36Sopenharmony_ci"/"		{ return '/'; }
13062306a36Sopenharmony_ci"%"		{ return '%'; }
13162306a36Sopenharmony_ci"("		{ return '('; }
13262306a36Sopenharmony_ci")"		{ return ')'; }
13362306a36Sopenharmony_ci","		{ return ','; }
13462306a36Sopenharmony_ci.		{ }
13562306a36Sopenharmony_ci%%
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_ciint expr_wrap(void *scanner __maybe_unused)
13862306a36Sopenharmony_ci{
13962306a36Sopenharmony_ci	return 1;
14062306a36Sopenharmony_ci}
141