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