at v5.7-rc2 2.2 kB view raw
1/* Simple expression parser */ 2%{ 3#define YYDEBUG 1 4#include <stdio.h> 5#include "util.h" 6#include "util/debug.h" 7#include <stdlib.h> // strtod() 8#define IN_EXPR_Y 1 9#include "expr.h" 10#include "smt.h" 11#include <string.h> 12 13%} 14 15%define api.pure full 16 17%parse-param { double *final_val } 18%parse-param { struct parse_ctx *ctx } 19%parse-param {void *scanner} 20%lex-param {void* scanner} 21 22%union { 23 double num; 24 char *str; 25} 26 27%token EXPR_PARSE EXPR_OTHER EXPR_ERROR 28%token <num> NUMBER 29%token <str> ID 30%token MIN MAX IF ELSE SMT_ON 31%left MIN MAX IF 32%left '|' 33%left '^' 34%left '&' 35%left '-' '+' 36%left '*' '/' '%' 37%left NEG NOT 38%type <num> expr if_expr 39 40%{ 41static void expr_error(double *final_val __maybe_unused, 42 struct parse_ctx *ctx __maybe_unused, 43 void *scanner, 44 const char *s) 45{ 46 pr_debug("%s\n", s); 47} 48 49static int lookup_id(struct parse_ctx *ctx, char *id, double *val) 50{ 51 int i; 52 53 for (i = 0; i < ctx->num_ids; i++) { 54 if (!strcasecmp(ctx->ids[i].name, id)) { 55 *val = ctx->ids[i].val; 56 return 0; 57 } 58 } 59 return -1; 60} 61 62%} 63%% 64 65start: 66EXPR_PARSE all_expr 67| 68EXPR_OTHER all_other 69 70all_other: all_other other 71| 72 73other: ID 74{ 75 if (ctx->num_ids + 1 >= EXPR_MAX_OTHER) { 76 pr_err("failed: way too many variables"); 77 YYABORT; 78 } 79 80 ctx->ids[ctx->num_ids++].name = $1; 81} 82| 83MIN | MAX | IF | ELSE | SMT_ON | NUMBER | '|' | '^' | '&' | '-' | '+' | '*' | '/' | '%' | '(' | ')' 84 85 86all_expr: if_expr { *final_val = $1; } 87 ; 88 89if_expr: 90 expr IF expr ELSE expr { $$ = $3 ? $1 : $5; } 91 | expr 92 ; 93 94expr: NUMBER 95 | ID { if (lookup_id(ctx, $1, &$$) < 0) { 96 pr_debug("%s not found\n", $1); 97 YYABORT; 98 } 99 } 100 | expr '|' expr { $$ = (long)$1 | (long)$3; } 101 | expr '&' expr { $$ = (long)$1 & (long)$3; } 102 | expr '^' expr { $$ = (long)$1 ^ (long)$3; } 103 | expr '+' expr { $$ = $1 + $3; } 104 | expr '-' expr { $$ = $1 - $3; } 105 | expr '*' expr { $$ = $1 * $3; } 106 | expr '/' expr { if ($3 == 0) YYABORT; $$ = $1 / $3; } 107 | expr '%' expr { if ((long)$3 == 0) YYABORT; $$ = (long)$1 % (long)$3; } 108 | '-' expr %prec NEG { $$ = -$2; } 109 | '(' if_expr ')' { $$ = $2; } 110 | MIN '(' expr ',' expr ')' { $$ = $3 < $5 ? $3 : $5; } 111 | MAX '(' expr ',' expr ')' { $$ = $3 > $5 ? $3 : $5; } 112 | SMT_ON { $$ = smt_on() > 0; } 113 ; 114 115%%