expr.y revision 7165
1%{ 2/* Written by Pace Willisson (pace@blitz.com) 3 * and placed in the public domain. 4 * 5 * Largely rewritten by J.T. Conklin (jtc@wimsey.com) 6 * 7 * $Id: expr.y,v 1.8 1994/09/24 02:55:37 davidg Exp $ 8 */ 9 10#include <stdio.h> 11#include <stdlib.h> 12#include <string.h> 13#include <locale.h> 14#include <ctype.h> 15#include <err.h> 16 17enum valtype { 18 integer, string 19} ; 20 21struct val { 22 enum valtype type; 23 union { 24 char *s; 25 int i; 26 } u; 27} ; 28 29struct val *result; 30struct val *op_or (); 31struct val *op_and (); 32struct val *op_eq (); 33struct val *op_gt (); 34struct val *op_lt (); 35struct val *op_ge (); 36struct val *op_le (); 37struct val *op_ne (); 38struct val *op_plus (); 39struct val *op_minus (); 40struct val *op_times (); 41struct val *op_div (); 42struct val *op_rem (); 43struct val *op_colon (); 44 45char **av; 46%} 47 48%union 49{ 50 struct val *val; 51} 52 53%left <val> '|' 54%left <val> '&' 55%left <val> '=' '>' '<' GE LE NE 56%left <val> '+' '-' 57%left <val> '*' '/' '%' 58%left <val> ':' 59%left UNARY 60 61%token <val> TOKEN 62%type <val> start expr 63 64%% 65 66start: expr { result = $$; } 67 68expr: TOKEN 69 | '(' expr ')' { $$ = $2; } 70 | expr '|' expr { $$ = op_or ($1, $3); } 71 | expr '&' expr { $$ = op_and ($1, $3); } 72 | expr '=' expr { $$ = op_eq ($1, $3); } 73 | expr '>' expr { $$ = op_gt ($1, $3); } 74 | expr '<' expr { $$ = op_lt ($1, $3); } 75 | expr GE expr { $$ = op_ge ($1, $3); } 76 | expr LE expr { $$ = op_le ($1, $3); } 77 | expr NE expr { $$ = op_ne ($1, $3); } 78 | expr '+' expr { $$ = op_plus ($1, $3); } 79 | expr '-' expr { $$ = op_minus ($1, $3); } 80 | expr '*' expr { $$ = op_times ($1, $3); } 81 | expr '/' expr { $$ = op_div ($1, $3); } 82 | expr '%' expr { $$ = op_rem ($1, $3); } 83 | expr ':' expr { $$ = op_colon ($1, $3); } 84 ; 85 86 87%% 88 89struct val * 90make_integer (i) 91int i; 92{ 93 struct val *vp; 94 95 vp = (struct val *) malloc (sizeof (*vp)); 96 if (vp == NULL) { 97 err (2, NULL); 98 } 99 100 vp->type = integer; 101 vp->u.i = i; 102 return vp; 103} 104 105struct val * 106make_str (s) 107char *s; 108{ 109 struct val *vp; 110 111 vp = (struct val *) malloc (sizeof (*vp)); 112 if (vp == NULL || ((vp->u.s = strdup (s)) == NULL)) { 113 err (2, NULL); 114 } 115 116 vp->type = string; 117 return vp; 118} 119 120 121void 122free_value (vp) 123struct val *vp; 124{ 125 if (vp->type == string) 126 free (vp->u.s); 127} 128 129 130int 131to_integer (vp) 132struct val *vp; 133{ 134 char *s; 135 int neg; 136 int i; 137 138 if (vp->type == integer) 139 return 1; 140 141 s = vp->u.s; 142 i = 0; 143 144 neg = (*s == '-'); 145 if (neg) 146 s++; 147 148 for (;*s; s++) { 149 if (!isdigit (*s)) 150 return 0; 151 152 i *= 10; 153 i += *s - '0'; 154 } 155 156 free (vp->u.s); 157 if (neg) 158 i *= -1; 159 160 vp->type = integer; 161 vp->u.i = i; 162 return 1; 163} 164 165void 166to_string (vp) 167struct val *vp; 168{ 169 char *tmp; 170 171 if (vp->type == string) 172 return; 173 174 tmp = malloc (25); 175 if (tmp == NULL) { 176 err (2, NULL); 177 } 178 179 sprintf (tmp, "%d", vp->u.i); 180 vp->type = string; 181 vp->u.s = tmp; 182} 183 184 185int 186isstring (vp) 187struct val *vp; 188{ 189 return (vp->type == string); 190} 191 192 193int 194yylex () 195{ 196 char *p; 197 198 if (*av == NULL) 199 return (0); 200 201 p = *av++; 202 203 if (strlen (p) == 1) { 204 if (strchr ("|&=<>+-*/%:()", *p)) 205 return (*p); 206 } else if (strlen (p) == 2 && p[1] == '=') { 207 switch (*p) { 208 case '>': return (GE); 209 case '<': return (LE); 210 case '!': return (NE); 211 } 212 } 213 214 yylval.val = make_str (p); 215 return (TOKEN); 216} 217 218int 219is_zero_or_null (vp) 220struct val *vp; 221{ 222 if (vp->type == integer) { 223 return (vp->u.i == 0); 224 } else { 225 return (*vp->u.s == 0 || (to_integer (vp) && vp->u.i == 0)); 226 } 227 /* NOTREACHED */ 228} 229 230int yyparse (); 231 232void 233main (argc, argv) 234int argc; 235char **argv; 236{ 237 setlocale (LC_ALL, ""); 238 239 av = argv + 1; 240 241 yyparse (); 242 243 if (result->type == integer) 244 printf ("%d\n", result->u.i); 245 else 246 printf ("%s\n", result->u.s); 247 248 exit (is_zero_or_null (result)); 249} 250 251int 252yyerror (s) 253char *s; 254{ 255 errx (2, "syntax error"); 256} 257 258 259struct val * 260op_or (a, b) 261struct val *a, *b; 262{ 263 if (is_zero_or_null (a)) { 264 free_value (a); 265 return (b); 266 } else { 267 free_value (b); 268 return (a); 269 } 270} 271 272struct val * 273op_and (a, b) 274struct val *a, *b; 275{ 276 if (is_zero_or_null (a) || is_zero_or_null (b)) { 277 free_value (a); 278 free_value (b); 279 return (make_integer (0)); 280 } else { 281 free_value (b); 282 return (a); 283 } 284} 285 286struct val * 287op_eq (a, b) 288struct val *a, *b; 289{ 290 struct val *r; 291 292 if (isstring (a) || isstring (b)) { 293 to_string (a); 294 to_string (b); 295 r = make_integer (strcoll (a->u.s, b->u.s) == 0); 296 } else { 297 r = make_integer (a->u.i == b->u.i); 298 } 299 300 free_value (a); 301 free_value (b); 302 return r; 303} 304 305struct val * 306op_gt (a, b) 307struct val *a, *b; 308{ 309 struct val *r; 310 311 if (isstring (a) || isstring (b)) { 312 to_string (a); 313 to_string (b); 314 r = make_integer (strcoll (a->u.s, b->u.s) > 0); 315 } else { 316 r= make_integer (a->u.i > b->u.i); 317 } 318 319 free_value (a); 320 free_value (b); 321 return r; 322} 323 324struct val * 325op_lt (a, b) 326struct val *a, *b; 327{ 328 struct val *r; 329 330 if (isstring (a) || isstring (b)) { 331 to_string (a); 332 to_string (b); 333 r = make_integer (strcoll (a->u.s, b->u.s) < 0); 334 } else { 335 r = make_integer (a->u.i < b->u.i); 336 } 337 338 free_value (a); 339 free_value (b); 340 return r; 341} 342 343struct val * 344op_ge (a, b) 345struct val *a, *b; 346{ 347 struct val *r; 348 349 if (isstring (a) || isstring (b)) { 350 to_string (a); 351 to_string (b); 352 r = make_integer (strcoll (a->u.s, b->u.s) >= 0); 353 } else { 354 r = make_integer (a->u.i >= b->u.i); 355 } 356 357 free_value (a); 358 free_value (b); 359 return r; 360} 361 362struct val * 363op_le (a, b) 364struct val *a, *b; 365{ 366 struct val *r; 367 368 if (isstring (a) || isstring (b)) { 369 to_string (a); 370 to_string (b); 371 r = make_integer (strcoll (a->u.s, b->u.s) <= 0); 372 } else { 373 r = make_integer (a->u.i <= b->u.i); 374 } 375 376 free_value (a); 377 free_value (b); 378 return r; 379} 380 381struct val * 382op_ne (a, b) 383struct val *a, *b; 384{ 385 struct val *r; 386 387 if (isstring (a) || isstring (b)) { 388 to_string (a); 389 to_string (b); 390 r = make_integer (strcoll (a->u.s, b->u.s) != 0); 391 } else { 392 r = make_integer (a->u.i != b->u.i); 393 } 394 395 free_value (a); 396 free_value (b); 397 return r; 398} 399 400struct val * 401op_plus (a, b) 402struct val *a, *b; 403{ 404 struct val *r; 405 406 if (!to_integer (a) || !to_integer (b)) { 407 errx (2, "non-numeric argument"); 408 } 409 410 r = make_integer (a->u.i + b->u.i); 411 free_value (a); 412 free_value (b); 413 return r; 414} 415 416struct val * 417op_minus (a, b) 418struct val *a, *b; 419{ 420 struct val *r; 421 422 if (!to_integer (a) || !to_integer (b)) { 423 errx (2, "non-numeric argument"); 424 } 425 426 r = make_integer (a->u.i - b->u.i); 427 free_value (a); 428 free_value (b); 429 return r; 430} 431 432struct val * 433op_times (a, b) 434struct val *a, *b; 435{ 436 struct val *r; 437 438 if (!to_integer (a) || !to_integer (b)) { 439 errx (2, "non-numeric argument"); 440 } 441 442 r = make_integer (a->u.i * b->u.i); 443 free_value (a); 444 free_value (b); 445 return (r); 446} 447 448struct val * 449op_div (a, b) 450struct val *a, *b; 451{ 452 struct val *r; 453 454 if (!to_integer (a) || !to_integer (b)) { 455 errx (2, "non-numeric argument"); 456 } 457 458 if (b->u.i == 0) { 459 errx (2, "division by zero"); 460 } 461 462 r = make_integer (a->u.i / b->u.i); 463 free_value (a); 464 free_value (b); 465 return r; 466} 467 468struct val * 469op_rem (a, b) 470struct val *a, *b; 471{ 472 struct val *r; 473 474 if (!to_integer (a) || !to_integer (b)) { 475 errx (2, "non-numeric argument"); 476 } 477 478 if (b->u.i == 0) { 479 errx (2, "division by zero"); 480 } 481 482 r = make_integer (a->u.i % b->u.i); 483 free_value (a); 484 free_value (b); 485 return r; 486} 487 488#include <sys/types.h> 489#include <regex.h> 490 491struct val * 492op_colon (a, b) 493struct val *a, *b; 494{ 495 regex_t rp; 496 regmatch_t rm[2]; 497 char errbuf[256]; 498 int eval; 499 struct val *v; 500 501 /* coerce to both arguments to strings */ 502 to_string(a); 503 to_string(b); 504 505 /* compile regular expression */ 506 if ((eval = regcomp (&rp, b->u.s, 0)) != 0) { 507 regerror (eval, &rp, errbuf, sizeof(errbuf)); 508 errx (2, "%s", errbuf); 509 } 510 511 /* compare string against pattern */ 512 /* remember that patterns are anchored to the beginning of the line */ 513 if (regexec(&rp, a->u.s, 2, rm, 0) == 0 && rm[0].rm_so == 0) { 514 if (rm[1].rm_so >= 0) { 515 *(a->u.s + rm[1].rm_eo) = '\0'; 516 v = make_str (a->u.s + rm[1].rm_so); 517 518 } else { 519 v = make_integer (rm[0].rm_eo - rm[0].rm_so); 520 } 521 } else { 522 if (rp.re_nsub == 0) { 523 v = make_integer (0); 524 } else { 525 v = make_str (""); 526 } 527 } 528 529 /* free arguments and pattern buffer */ 530 free_value (a); 531 free_value (b); 532 regfree (&rp); 533 534 return v; 535} 536