wmcalc: Use autotools for build.
[dockapps.git] / wmsupermon / expr.y
blob32c949ec64825df15d030d8f4797c72f3d8db7b7
1 /* Copyright (C) 2006 Sergei Golubchik
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License version 2
5 as published by the Free Software Foundation
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 GNU General Public License for more details.
12 You should have received a copy of the GNU General Public License
13 along with this program; if not, write to the Free Software
14 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
18 #include <strings.h>
19 #include <stdlib.h>
20 #include "expr.h"
22 int yylex (void);
23 void yyerror (char const *);
25 char *yy_err, *yy_str;
26 Expr *yy_expr;
27 int yy_nsum, yy_ndiff;
29 static double e_num(Expr *me, Econtext *ctx) {
30 return me->val.num;
33 static double e_var(Expr *me, Econtext *ctx) {
34 char c, *s, *e; double v;
35 if (ctx->pmatch[me->val.var].rm_so < 0) return 0;
36 s=ctx->str+ctx->pmatch[me->val.var].rm_so;
37 e=ctx->str+ctx->pmatch[me->val.var].rm_eo;
38 c=*e; *e=0; v=strtod(s, 0); *e=c;
39 return v;
42 static double e_if(Expr *me, Econtext *ctx) {
43 return me->val.arg[0]->eval(me->val.arg[0], ctx) ?
44 me->val.arg[1]->eval(me->val.arg[1], ctx) :
45 me->val.arg[2]->eval(me->val.arg[2], ctx) ;
48 static double e_lt(Expr *me, Econtext *ctx) {
49 return me->val.arg[0]->eval(me->val.arg[0], ctx) < me->val.arg[1]->eval(me->val.arg[1], ctx);
52 static double e_gt(Expr *me, Econtext *ctx) {
53 return me->val.arg[0]->eval(me->val.arg[0], ctx) > me->val.arg[1]->eval(me->val.arg[1], ctx);
56 static double e_add(Expr *me, Econtext *ctx) {
57 return me->val.arg[0]->eval(me->val.arg[0], ctx) + me->val.arg[1]->eval(me->val.arg[1], ctx);
60 static double e_sub(Expr *me, Econtext *ctx) {
61 return me->val.arg[0]->eval(me->val.arg[0], ctx) - me->val.arg[1]->eval(me->val.arg[1], ctx);
64 static double e_mul(Expr *me, Econtext *ctx) {
65 return me->val.arg[0]->eval(me->val.arg[0], ctx) * me->val.arg[1]->eval(me->val.arg[1], ctx);
68 static double e_div(Expr *me, Econtext *ctx) {
69 return me->val.arg[0]->eval(me->val.arg[0], ctx) / me->val.arg[1]->eval(me->val.arg[1], ctx);
72 static double e_sum(Expr *me, Econtext *ctx) {
73 int slot=(long)me->val.arg[1];
74 return ctx->sum_acc[slot]+=me->val.arg[0]->eval(me->val.arg[0], ctx);
77 static double e_diff(Expr *me, Econtext *ctx) {
78 double e, v;
79 int slot=(long)me->val.arg[1];
80 ctx->diff_new[slot]=e=me->val.arg[0]->eval(me->val.arg[0], ctx);
81 v=e-ctx->diff_old[slot];
82 return v;
85 static Expr *new_num(double val) {
86 Expr *e=malloc(sizeof(Expr));
87 e->eval=e_num;
88 e->val.num=val;
89 return e;
92 static Expr *new_var(int var) {
93 Expr *e=malloc(sizeof(Expr));
94 e->eval=e_var;
95 e->val.var=var;
96 return e;
99 static Expr *new_op(Expr *e1, Expr *e2, double (*eval)(Expr *, Econtext *))
101 Expr *e=calloc(1, sizeof(Expr));
102 e->eval=eval;
103 e->val.arg[0]=e1;
104 e->val.arg[1]=e2;
105 return e;
110 %error-verbose
112 %union {
113 int var;
114 double val;
115 Expr *expr;
118 /* Bison declarations. */
119 %token<val> NUM
120 %token<var> VAR
121 %token SUM DIFF
122 %type <expr> expr
124 %left '?' ':'
125 %left '<' '>'
126 %left '-' '+'
127 %left '*' '/'
128 %left NEG
130 %% /* The grammar follows. */
132 input: expr { yy_expr=$1; }
134 expr: NUM { $$=new_num($1); }
135 | VAR {
136 if ($1 >= MAX_VAR) {
137 yyerror("too large register number");
138 YYERROR;
140 $$=new_var($1);
142 | SUM '(' expr ')' { $$=new_op($3, (Expr *)(long)yy_nsum++, e_sum);}
143 | DIFF '(' expr ')' { $$=new_op($3, (Expr *)(long)yy_ndiff++, e_diff);}
144 | expr '?' expr ':' expr { $$=new_op($1, $3, e_if); $$->val.arg[2]=$5; }
145 | expr '<' expr { $$=new_op($1, $3, e_lt); }
146 | expr '>' expr { $$=new_op($1, $3, e_gt); }
147 | expr '+' expr { $$=new_op($1, $3, e_add); }
148 | expr '-' expr { $$=new_op($1, $3, e_sub); }
149 | expr '*' expr { $$=new_op($1, $3, e_mul); }
150 | expr '/' expr { $$=new_op($1, $3, e_div); }
151 | '-' expr %prec NEG { $$=new_op(new_num(0) ,$2, e_sub); }
152 | '+' expr %prec NEG { $$=$2; }
153 | '(' expr ')' { $$=$2; }
157 #include <ctype.h>
158 #include <string.h>
160 #define prefix(S,CONST) !strncasecmp((S),CONST,sizeof(CONST)-1)
162 int yylex(void)
164 while (isspace(*yy_str)) yy_str++;
165 if (isdigit(*yy_str)) {
166 yylval.val=strtod(yy_str, &yy_str);
167 return NUM;
169 if (*yy_str == '\\') {
170 if (!isdigit(*++yy_str)) return '\\';
171 yylval.var=strtol(yy_str, &yy_str, 10);
172 return VAR;
174 if (prefix(yy_str, "sum")) {
175 yy_str +=3;
176 return SUM;
178 if (prefix(yy_str, "diff")) {
179 yy_str +=4;
180 return DIFF;
182 return *yy_str++;
185 /* Called by yyparse on error. */
186 void
187 yyerror (char const *s)
189 strcpy(yy_err, s);