18c2ecf20Sopenharmony_ci%option prefix="expr_"
28c2ecf20Sopenharmony_ci%option reentrant
38c2ecf20Sopenharmony_ci%option bison-bridge
48c2ecf20Sopenharmony_ci
58c2ecf20Sopenharmony_ci%{
68c2ecf20Sopenharmony_ci#include <linux/compiler.h>
78c2ecf20Sopenharmony_ci#include "expr.h"
88c2ecf20Sopenharmony_ci#include "expr-bison.h"
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_cichar *expr_get_text(yyscan_t yyscanner);
118c2ecf20Sopenharmony_ciYYSTYPE *expr_get_lval(yyscan_t yyscanner);
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_cistatic double __value(YYSTYPE *yylval, char *str, int token)
148c2ecf20Sopenharmony_ci{
158c2ecf20Sopenharmony_ci	double num;
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci	errno = 0;
188c2ecf20Sopenharmony_ci	num = strtod(str, NULL);
198c2ecf20Sopenharmony_ci	if (errno)
208c2ecf20Sopenharmony_ci		return EXPR_ERROR;
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci	yylval->num = num;
238c2ecf20Sopenharmony_ci	return token;
248c2ecf20Sopenharmony_ci}
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_cistatic int value(yyscan_t scanner)
278c2ecf20Sopenharmony_ci{
288c2ecf20Sopenharmony_ci	YYSTYPE *yylval = expr_get_lval(scanner);
298c2ecf20Sopenharmony_ci	char *text = expr_get_text(scanner);
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci	return __value(yylval, text, NUMBER);
328c2ecf20Sopenharmony_ci}
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_ci/*
358c2ecf20Sopenharmony_ci * Allow @ instead of / to be able to specify pmu/event/ without
368c2ecf20Sopenharmony_ci * conflicts with normal division.
378c2ecf20Sopenharmony_ci */
388c2ecf20Sopenharmony_cistatic char *normalize(char *str, int runtime)
398c2ecf20Sopenharmony_ci{
408c2ecf20Sopenharmony_ci	char *ret = str;
418c2ecf20Sopenharmony_ci	char *dst = str;
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci	while (*str) {
448c2ecf20Sopenharmony_ci		if (*str == '@')
458c2ecf20Sopenharmony_ci			*dst++ = '/';
468c2ecf20Sopenharmony_ci		else if (*str == '\\')
478c2ecf20Sopenharmony_ci			*dst++ = *++str;
488c2ecf20Sopenharmony_ci		 else if (*str == '?') {
498c2ecf20Sopenharmony_ci			char *paramval;
508c2ecf20Sopenharmony_ci			int i = 0;
518c2ecf20Sopenharmony_ci			int size = asprintf(&paramval, "%d", runtime);
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci			if (size < 0)
548c2ecf20Sopenharmony_ci				*dst++ = '0';
558c2ecf20Sopenharmony_ci			else {
568c2ecf20Sopenharmony_ci				while (i < size)
578c2ecf20Sopenharmony_ci					*dst++ = paramval[i++];
588c2ecf20Sopenharmony_ci				free(paramval);
598c2ecf20Sopenharmony_ci			}
608c2ecf20Sopenharmony_ci		}
618c2ecf20Sopenharmony_ci		else
628c2ecf20Sopenharmony_ci			*dst++ = *str;
638c2ecf20Sopenharmony_ci		str++;
648c2ecf20Sopenharmony_ci	}
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_ci	*dst = 0x0;
678c2ecf20Sopenharmony_ci	return ret;
688c2ecf20Sopenharmony_ci}
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_cistatic int str(yyscan_t scanner, int token, int runtime)
718c2ecf20Sopenharmony_ci{
728c2ecf20Sopenharmony_ci	YYSTYPE *yylval = expr_get_lval(scanner);
738c2ecf20Sopenharmony_ci	char *text = expr_get_text(scanner);
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci	yylval->str = normalize(strdup(text), runtime);
768c2ecf20Sopenharmony_ci	if (!yylval->str)
778c2ecf20Sopenharmony_ci		return EXPR_ERROR;
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_ci	yylval->str = normalize(yylval->str, runtime);
808c2ecf20Sopenharmony_ci	return token;
818c2ecf20Sopenharmony_ci}
828c2ecf20Sopenharmony_ci%}
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_cinumber		([0-9]+\.?[0-9]*|[0-9]*\.?[0-9]+)
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_cisch		[-,=]
878c2ecf20Sopenharmony_cispec		\\{sch}
888c2ecf20Sopenharmony_cisym		[0-9a-zA-Z_\.:@?]+
898c2ecf20Sopenharmony_cisymbol		({spec}|{sym})+
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ci%%
928c2ecf20Sopenharmony_ci	struct expr_scanner_ctx *sctx = expr_get_extra(yyscanner);
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci	{
958c2ecf20Sopenharmony_ci		int start_token = sctx->start_token;
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_ci		if (sctx->start_token) {
988c2ecf20Sopenharmony_ci			sctx->start_token = 0;
998c2ecf20Sopenharmony_ci			return start_token;
1008c2ecf20Sopenharmony_ci		}
1018c2ecf20Sopenharmony_ci	}
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_cid_ratio		{ return D_RATIO; }
1048c2ecf20Sopenharmony_cimax		{ return MAX; }
1058c2ecf20Sopenharmony_cimin		{ return MIN; }
1068c2ecf20Sopenharmony_ciif		{ return IF; }
1078c2ecf20Sopenharmony_cielse		{ return ELSE; }
1088c2ecf20Sopenharmony_ci#smt_on		{ return SMT_ON; }
1098c2ecf20Sopenharmony_ci{number}	{ return value(yyscanner); }
1108c2ecf20Sopenharmony_ci{symbol}	{ return str(yyscanner, ID, sctx->runtime); }
1118c2ecf20Sopenharmony_ci"|"		{ return '|'; }
1128c2ecf20Sopenharmony_ci"^"		{ return '^'; }
1138c2ecf20Sopenharmony_ci"&"		{ return '&'; }
1148c2ecf20Sopenharmony_ci"<"		{ return '<'; }
1158c2ecf20Sopenharmony_ci">"		{ return '>'; }
1168c2ecf20Sopenharmony_ci"-"		{ return '-'; }
1178c2ecf20Sopenharmony_ci"+"		{ return '+'; }
1188c2ecf20Sopenharmony_ci"*"		{ return '*'; }
1198c2ecf20Sopenharmony_ci"/"		{ return '/'; }
1208c2ecf20Sopenharmony_ci"%"		{ return '%'; }
1218c2ecf20Sopenharmony_ci"("		{ return '('; }
1228c2ecf20Sopenharmony_ci")"		{ return ')'; }
1238c2ecf20Sopenharmony_ci","		{ return ','; }
1248c2ecf20Sopenharmony_ci.		{ }
1258c2ecf20Sopenharmony_ci%%
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_ciint expr_wrap(void *scanner __maybe_unused)
1288c2ecf20Sopenharmony_ci{
1298c2ecf20Sopenharmony_ci	return 1;
1308c2ecf20Sopenharmony_ci}
131