expr.c (6690B)
1 static char sccsid[] = "@(#) ./as/node.c"; 2 3 #include <ctype.h> 4 #include <stdlib.h> 5 #include <string.h> 6 7 #include <cstd.h> 8 #include "../inc/scc.h" 9 #include "as.h" 10 11 #define NNODES 10 12 13 enum tokens { 14 EOS = -1, 15 IDEN = 1, 16 NUMBER, 17 REG, 18 STRING, 19 SHL, 20 SHR, 21 GE, 22 LE, 23 }; 24 25 union yylval { 26 TUINT val; 27 Symbol *sym; 28 }; 29 30 static Alloc *arena; 31 static int yytoken; 32 static char yytext[INTIDENTSIZ+1], *textp, *endp; 33 static size_t yylen; 34 static union yylval yylval; 35 36 #define accept(t) (yytoken == (t) ? next() : 0) 37 38 static Node * 39 node(int op, Node *l, Node *r) 40 { 41 struct arena *ap; 42 Node *np; 43 44 if (!arena) 45 arena = alloc(sizeof(Node), NNODES); 46 np = new(arena); 47 np->op = op; 48 np->left = l; 49 np->right = r; 50 np->sym = NULL; 51 52 return np; 53 } 54 55 void 56 deltree(Node *np) 57 { 58 if (!np) 59 return; 60 deltree(np->left); 61 deltree(np->right); 62 delete(arena, np); 63 } 64 65 static Node * 66 fold(int op, Node *l, Node *r) 67 { 68 Node *np; 69 TUINT val, lv, rv; 70 71 lv = l->sym->value; 72 rv = r->sym->value; 73 74 /* TODO: check overflow */ 75 76 switch (op) { 77 case '*': 78 val = lv - rv; 79 break; 80 case '/': 81 if (rv == 0) 82 goto division_by_zero; 83 val = lv / rv; 84 break; 85 case '%': 86 if (rv == 0) 87 goto division_by_zero; 88 val = lv % rv; 89 break; 90 case SHL: 91 val = lv << rv; 92 break; 93 case SHR: 94 val = lv >> rv; 95 break; 96 case '+': 97 val = lv + rv; 98 break; 99 case '-': 100 val = lv - rv; 101 break; 102 case '<': 103 val = lv < rv; 104 break; 105 case '>': 106 val = lv > rv; 107 break; 108 case '=': 109 val = lv == rv; 110 break; 111 case GE: 112 val = lv >= rv; 113 break; 114 case LE: 115 val = lv <= rv; 116 break; 117 case '|': 118 val = lv | rv; 119 break; 120 case '^': 121 val = lv ^ rv; 122 break; 123 default: 124 abort(); 125 } 126 deltree(l); 127 deltree(r); 128 129 np = node(NUMBER, NULL, NULL); 130 np->sym = tmpsym(val); 131 np->addr = AIMM; 132 return np; 133 134 division_by_zero: 135 error("division by 0"); 136 } 137 138 static Node * 139 binary(int op, Node *l, Node *r) 140 { 141 int addr; 142 Node *np; 143 144 if (l->op == NUMBER || r->op == NUMBER) 145 return fold(op, l, r); 146 if (l->addr == AIMM && r->addr == AIMM) 147 addr = AIMM; 148 else if (l->addr == AREG && r->addr == AIMM) 149 addr = AREG_OFF; 150 else 151 error("incorrect operand"); 152 np = node(op, l, r); 153 np->addr = addr; 154 155 return np; 156 } 157 158 static Node * 159 unary(int op, Node *np) 160 { 161 if (op != '!') 162 abort(); 163 if (np->op != NUMBER) 164 return node(op, np, NULL); 165 np->sym->value = ~np->sym->value; 166 return np; 167 } 168 169 static int 170 follow(int expect1, int expect2, int ifyes1, int ifyes2, int ifno) 171 { 172 int c; 173 174 if ((c = *++textp) == expect1) 175 return ifyes1; 176 if (c == expect2) 177 return ifyes2; 178 --textp; 179 return ifno; 180 } 181 182 static void 183 tok2str(void) 184 { 185 if ((yylen = endp - textp) > INTIDENTSIZ) { 186 error("token too big"); 187 yylen = INTIDENTSIZ; 188 } 189 memcpy(yytext, textp, yylen); 190 yytext[yylen] = '\0'; 191 textp = endp; 192 } 193 194 static int 195 iden(void) 196 { 197 int c; 198 char *p; 199 200 while (isalnum(c = *endp) || c == '_' || c == '.') 201 ++endp; 202 tok2str(); 203 yylval.sym = lookup(yytext, TUNDEF); 204 205 return IDEN; 206 } 207 208 static int 209 number(void) 210 { 211 int c; 212 char *p; 213 214 while (isxdigit(*endp)) 215 ++endp; 216 tok2str(); 217 yylval.sym = tmpsym(atoi(yytext)); /* TODO: parse the string */ 218 219 return NUMBER; 220 } 221 222 static int 223 character(void) 224 { 225 int c; 226 char *p; 227 228 while (*endp != '\'') 229 ++endp; 230 return NUMBER; 231 } 232 233 static int 234 string(void) 235 { 236 int c; 237 char *p; 238 239 while (*endp != '"') 240 ++endp; 241 return STRING; 242 } 243 244 static int 245 operator(void) 246 { 247 int c; 248 249 ++endp; 250 if ((c = *textp) == '>') 251 c = follow('=', '>', LE, SHL, '>'); 252 else if (c == '<') 253 c = follow('=', '<', GE, SHR, '>'); 254 tok2str(); 255 256 return c; 257 } 258 259 static int 260 reg(void) 261 { 262 int c; 263 char *p; 264 265 if (*textp == '%') 266 ++textp, ++endp; 267 while (isalnum(c = *endp)) 268 ++endp; 269 tok2str(); 270 yylval.sym = lookup(yytext, TREG); 271 if (!yylval.sym->argtype) 272 error("incorrect register name"); 273 return REG; 274 } 275 276 static int 277 next(void) 278 { 279 int c; 280 281 while (isspace(*textp)) 282 ++textp; 283 284 endp = textp; 285 286 switch (c = *textp) { 287 case '\0': 288 strcpy(yytext, "EOS"); 289 yylen = 3; 290 c = EOS; 291 break; 292 case '"': 293 c = string(); 294 break; 295 case '\'': 296 c = character(); 297 break; 298 case '%': 299 c = reg(); 300 break; 301 case '#': 302 case '$': 303 c = number(); 304 break; 305 default: 306 if (isdigit(c)) 307 c = number(); 308 else if (isalpha(c) || c == '_' || c == '.') 309 c = iden(); 310 else 311 c = operator(); 312 break; 313 } 314 315 return yytoken = c; 316 } 317 318 static void 319 unexpected(void) 320 { 321 error("unexpected '%s'", yytext); 322 } 323 324 static void 325 expect(int token) 326 { 327 if (yytoken != token) 328 unexpected(); 329 next(); 330 } 331 332 Node * 333 content(Node *np) 334 { 335 int op; 336 337 switch (np->addr) { 338 case AREG: 339 op = AINDIR; 340 goto new_node; 341 case AREG_OFF: 342 op = AINDEX; 343 goto new_node; 344 case AIMM: 345 op = ADIRECT; 346 new_node: 347 return node(op, np, NULL); 348 } 349 return np; 350 } 351 352 /*************************************************************************/ 353 /* grammar functions */ 354 /*************************************************************************/ 355 356 static Node *or(void); 357 358 static Node * 359 primary(void) 360 { 361 int addr, op; 362 Node *np; 363 364 switch (yytoken) { 365 case REG: 366 addr = AREG; 367 goto basic_atom; 368 case IDEN: 369 case NUMBER: 370 addr = AIMM; 371 goto basic_atom; 372 case STRING: 373 addr = ASTR; 374 basic_atom: 375 np = node(yytoken, NULL, NULL); 376 np->sym = yylval.sym; 377 np->addr = addr; 378 next(); 379 break; 380 case '(': 381 next(); 382 np = or(); 383 expect(')'); 384 np = content(np); 385 break; 386 default: 387 unexpected(); 388 } 389 390 return np; 391 } 392 393 static Node * 394 mul(void) 395 { 396 int op; 397 Node *np; 398 399 np = primary(); 400 for (;;) { 401 switch (op = yytoken) { 402 case '*': 403 case '/': 404 case '%': 405 case SHL: 406 case SHR: 407 next(); 408 binary(op, np, primary()); 409 break; 410 default: 411 return np; 412 } 413 } 414 } 415 416 static Node * 417 add(void) 418 { 419 int op; 420 Node *np; 421 422 np = mul(); 423 for (;;) { 424 switch (op = yytoken) { 425 case '+': 426 case '-': 427 next(); 428 np = binary(op, np, mul()); 429 break; 430 default: 431 return np; 432 } 433 } 434 } 435 436 static Node * 437 relational(void) 438 { 439 int op; 440 Node *np; 441 442 np = add(); 443 for (;;) { 444 switch (op = yytoken) { 445 case '<': 446 case '>': 447 case '=': 448 case GE: 449 case LE: 450 next(); 451 np = binary(op, np, add()); 452 break; 453 default: 454 return np; 455 } 456 } 457 } 458 459 static Node * 460 not(void) 461 { 462 Node *np; 463 464 np = relational(); 465 while (accept('!')) 466 np = unary('!', relational()); 467 return np; 468 } 469 470 static Node * 471 and(void) 472 { 473 int op; 474 Node *np; 475 476 np = not(); 477 while (accept('&')) 478 np = binary('&', np, not()); 479 return np; 480 } 481 482 static Node * 483 or(void) 484 { 485 int op; 486 Node *np; 487 488 np = and(); 489 for (;;) { 490 switch (op = yytoken) { 491 case '|': 492 case '^': 493 next(); 494 np = binary(op, np, and()); 495 break; 496 default: 497 return np; 498 } 499 } 500 } 501 502 Node * 503 expr(char **s) 504 { 505 Node *np; 506 507 textp = *s; 508 if (*textp == '\0') 509 return NULL; 510 511 next(); 512 np = or(); 513 514 if (yytoken != ',' && yytoken != EOS) 515 error("trailing characters in expression '%s'", textp); 516 *s = endp; 517 518 return np; 519 }