expr.y revision 1.2 1 %{
2 /* Written by Pace Willisson (pace (at) blitz.com)
3 * and placed in the public domain
4 *
5 * $Id: expr.y,v 1.2 1993/03/22 08:04:00 cgd Exp $
6 */
7 #include <stdio.h>
8 #include <ctype.h>
9
10 char *malloc ();
11 char *calloc ();
12
13 struct val {
14 char *sval;
15 int ival;
16 int iflag;
17 };
18
19 struct val *result;
20
21 struct val *op_or ();
22 struct val *op_and ();
23 struct val *op_eq ();
24 struct val *op_gt ();
25 struct val *op_lt ();
26 struct val *op_ge ();
27 struct val *op_le ();
28 struct val *op_ne ();
29 struct val *op_plus ();
30 struct val *op_minus ();
31 struct val *op_times ();
32 struct val *op_div ();
33 struct val *op_rem ();
34 struct val *op_colon ();
35
36 char **av;
37 %}
38
39 %union
40 {
41 struct val *val;
42 }
43
44 %left <val> '|'
45 %left <val> '&'
46 %left <val> '=' '>' '<' GE LE NE
47 %left <val> '+' '-'
48 %left <val> '*' '/' '%'
49 %left <val> ':'
50 %left UNARY
51
52 %token <val> TOKEN
53 %type <val> start expr
54
55 %%
56
57 start: expr { result = $$; }
58
59 expr: TOKEN
60 | '(' expr ')' { $$ = $2; }
61 | expr '|' expr { $$ = op_or ($1, $3); }
62 | expr '&' expr { $$ = op_and ($1, $3); }
63 | expr '=' expr { $$ = op_eq ($1, $3); }
64 | expr '>' expr { $$ = op_gt ($1, $3); }
65 | expr '<' expr { $$ = op_lt ($1, $3); }
66 | expr GE expr { $$ = op_ge ($1, $3); }
67 | expr LE expr { $$ = op_le ($1, $3); }
68 | expr NE expr { $$ = op_ne ($1, $3); }
69 | expr '+' expr { $$ = op_plus ($1, $3); }
70 | expr '-' expr { $$ = op_minus ($1, $3); }
71 | expr '*' expr { $$ = op_times ($1, $3); }
72 | expr '/' expr { $$ = op_div ($1, $3); }
73 | expr '%' expr { $$ = op_rem ($1, $3); }
74 | expr ':' expr { $$ = op_colon ($1, $3); }
75 | '-' expr %prec UNARY { $$ = op_minus (NULL, $2); }
76 ;
77
78
79 %%
80
81 struct val *
82 make_val (sval)
83 char *sval;
84 {
85 struct val *vp;
86 char *p;
87
88 if ((vp = (struct val *)calloc (1, sizeof *vp)) == NULL
89 || (vp->sval = malloc (strlen (sval) + 1)) == NULL) {
90 fprintf (stderr, "out of memory\n");
91 exit (2);
92 }
93
94 strcpy (vp->sval, sval);
95
96 p = sval;
97
98 if (*p == '-')
99 p++;
100 while (isdigit (*p))
101 p++;
102 if (*p == 0) {
103 vp->iflag = 1;
104 vp->ival = atoi (sval);
105 }
106
107 return (vp);
108 }
109
110 struct val *
111 make_integer (ival)
112 int ival;
113 {
114 char buf[25];
115
116 sprintf (buf, "%d", ival);
117 return (make_val (buf));
118 }
119
120 int
121 yylex ()
122 {
123 struct val *vp;
124 char *p;
125
126 if (*av == NULL)
127 return (0);
128
129 p = *av++;
130
131 if (strlen (p) == 1) {
132 if (strchr ("|&=<>+-*/%:", *p))
133 return (*p);
134 } else if (strlen (p) == 2 && p[1] == '=') {
135 switch (*p) {
136 case '>': return (GE);
137 case '<': return (LE);
138 case '!': return (NE);
139 }
140 }
141
142 yylval.val = make_val (p);
143 return (TOKEN);
144 }
145
146 int
147 is_zero_or_null (vp)
148 struct val *vp;
149 {
150 if (vp->iflag && vp->ival == 0)
151 return (1);
152
153 if (*vp->sval == 0)
154 return (1);
155
156 return (0);
157 }
158
159 void
160 main (argc, argv)
161 int argc;
162 char **argv;
163 {
164 av = argv + 1;
165
166 yyparse ();
167
168 if (result->iflag)
169 printf ("%d\n", result->ival);
170 else
171 printf ("%s\n", result->sval);
172
173 if (is_zero_or_null (result))
174 exit (1);
175 else
176 exit (0);
177 }
178
179 int
180 yyerror (s)
181 char *s;
182 {
183 fprintf (stderr, "syntax error\n");
184 exit (2);
185 }
186
187 void
188 check_integers (a, b)
189 struct val *a, *b;
190 {
191 if (!a->iflag || !b->iflag) {
192 fprintf (stderr, "expr: non-numeric argument\n");
193 exit (2);
194 }
195 }
196
197 struct val *
198 op_or (a, b)
199 struct val *a, *b;
200 {
201 if (is_zero_or_null (a))
202 return (b);
203 else
204 return (a);
205 }
206
207 struct val *
208 op_and (a, b)
209 struct val *a, *b;
210 {
211 if (is_zero_or_null (a) || is_zero_or_null (b))
212 return (make_integer (0));
213 else
214 return (a);
215 }
216
217 struct val *
218 op_eq (a, b)
219 struct val *a, *b;
220 {
221 if (a->iflag && b->iflag)
222 return (make_integer (a->ival == b->ival));
223 else
224 return (make_integer (strcmp (a->sval, b->sval) == 0));
225 }
226
227 struct val *
228 op_gt (a, b)
229 struct val *a, *b;
230 {
231 if (a->iflag && b->iflag)
232 return (make_integer (a->ival > b->ival));
233 else
234 return (make_integer (strcmp (a->sval, b->sval) > 0));
235 }
236
237 struct val *
238 op_lt (a, b)
239 struct val *a, *b;
240 {
241 if (a->iflag && b->iflag)
242 return (make_integer (a->ival < b->ival));
243 else
244 return (make_integer (strcmp (a->sval, b->sval) < 0));
245 }
246
247 struct val *
248 op_ge (a, b)
249 struct val *a, *b;
250 {
251 if (a->iflag && b->iflag)
252 return (make_integer (a->ival >= b->ival));
253 else
254 return (make_integer (strcmp (a->sval, b->sval) >= 0));
255 }
256
257 struct val *
258 op_le (a, b)
259 struct val *a, *b;
260 {
261 if (a->iflag && b->iflag)
262 return (make_integer (a->ival <= b->ival));
263 else
264 return (make_integer (strcmp (a->sval, b->sval) <= 0));
265 }
266
267 struct val *
268 op_ne (a, b)
269 struct val *a, *b;
270 {
271 if (a->iflag && b->iflag)
272 return (make_integer (a->ival != b->ival));
273 else
274 return (make_integer (strcmp (a->sval, b->sval) != 0));
275 }
276
277 struct val *
278 op_plus (a, b)
279 struct val *a, *b;
280 {
281 check_integers (a, b);
282
283 return (make_integer (a->ival + b->ival));
284 }
285
286 struct val *
287 op_minus (a, b)
288 struct val *a, *b;
289 {
290 check_integers (a, b);
291
292 return (make_integer (a->ival - b->ival));
293 }
294
295 struct val *
296 op_times (a, b)
297 struct val *a, *b;
298 {
299 check_integers (a, b);
300
301 return (make_integer (a->ival * b->ival));
302 }
303
304 struct val *
305 op_div (a, b)
306 struct val *a, *b;
307 {
308 check_integers (a, b);
309
310 return (make_integer (a->ival / b->ival));
311 }
312
313 struct val *
314 op_rem (a, b)
315 struct val *a, *b;
316 {
317 check_integers (a, b);
318
319 return (make_integer (a->ival % b->ival));
320 }
321
322 #include <regexp.h>
323
324 struct val *
325 op_colon (a, b)
326 struct val *a, *b;
327 {
328 regexp *rp;
329 char *newexp;
330 char *p;
331 char *q;
332
333 newexp = malloc (3 * strlen (b->sval));
334 p = b->sval;
335 q = newexp;
336
337 *q++ = '^';
338 while (*p) {
339 if (*p == '\\') {
340 p++;
341 if (*p == '(' || *p == ')') {
342 *q++ = *p++;
343 } else {
344 *q++ = '\\';
345 *q++ = *p++;
346 }
347 } else if (*p == '(' || *p == ')') {
348 *q++ = '\\';
349 *q++ = *p++;
350 } else {
351 *q++ = *p++;
352 }
353 }
354 *q = 0;
355
356 if ((rp = regcomp (newexp)) == NULL)
357 yyerror ("invalid regular expression");
358
359 if (regexec (rp, a->sval)) {
360 if (rp->startp[1]) {
361 rp->endp[1][0] = 0;
362 return (make_val (rp->startp[1]));
363 } else {
364 return (make_integer (rp->endp[0] - rp->startp[0]));
365 }
366 } else {
367 return (make_integer (0));
368 }
369 }
370