%option prefix="expr_" %option reentrant %option bison-bridge %{ #include #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 = expr_get_extra(yyscanner); if (start_token) { expr_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; }