1 /* 2 * Copyright (c) 1989 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Robert Paul Corbett. 7 * 8 * Redistribution and use in source and binary forms are permitted 9 * provided that the above copyright notice and this paragraph are 10 * duplicated in all such forms and that any documentation, 11 * advertising materials, and other materials related to such 12 * distribution and use acknowledge that the software was developed 13 * by the University of California, Berkeley. The name of the 14 * University may not be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 19 */ 20 21 #ifndef lint 22 static char sccsid[] = "@(#)reader.c 5.5 (Berkeley) 04/13/90"; 23 #endif /* not lint */ 24 25 #include "defs.h" 26 27 /* The line size must be a positive integer. One hundred was chosen */ 28 /* because few lines in Yacc input grammars exceed 100 characters. */ 29 /* Note that if a line exceeds LINESIZE characters, the line buffer */ 30 /* will be expanded to accomodate it. */ 31 32 #define LINESIZE 100 33 34 char *cache; 35 int cinc, cache_size; 36 37 int ntags, tagmax; 38 char **tag_table; 39 40 char saw_eof, unionized; 41 char *cptr, *line; 42 int linesize; 43 44 bucket *goal; 45 int prec; 46 int gensym; 47 char last_was_action; 48 49 int maxitems; 50 bucket **pitem; 51 52 int maxrules; 53 bucket **plhs; 54 55 int name_pool_size; 56 char *name_pool; 57 58 char line_format[] = "#line %d \"%s\"\n"; 59 60 61 cachec(c) 62 int c; 63 { 64 assert(cinc >= 0); 65 if (cinc >= cache_size) 66 { 67 cache_size += 256; 68 cache = REALLOC(cache, cache_size); 69 if (cache == 0) no_space(); 70 } 71 cache[cinc] = c; 72 ++cinc; 73 } 74 75 76 get_line() 77 { 78 register FILE *f = input_file; 79 register int c; 80 register int i; 81 82 if (saw_eof || (c = getc(f)) == EOF) 83 { 84 if (line) { FREE(line); line = 0; } 85 cptr = 0; 86 saw_eof = 1; 87 return; 88 } 89 90 if (line == 0 || linesize != (LINESIZE + 1)) 91 { 92 if (line) FREE(line); 93 linesize = LINESIZE + 1; 94 line = MALLOC(linesize); 95 if (line == 0) no_space(); 96 } 97 98 i = 0; 99 ++lineno; 100 for (;;) 101 { 102 line[i] = c; 103 if (c == '\n') { cptr = line; return; } 104 if (++i >= linesize) 105 { 106 linesize += LINESIZE; 107 line = REALLOC(line, linesize); 108 if (line == 0) no_space(); 109 } 110 c = getc(f); 111 if (c == EOF) 112 { 113 line[i] = '\n'; 114 saw_eof = 1; 115 cptr = line; 116 return; 117 } 118 } 119 } 120 121 122 char * 123 dup_line() 124 { 125 register char *p, *s, *t; 126 127 if (line == 0) return (0); 128 s = line; 129 while (*s != '\n') ++s; 130 p = MALLOC(s - line + 1); 131 if (p == 0) no_space(); 132 133 s = line; 134 t = p; 135 while ((*t++ = *s++) != '\n') continue; 136 return (p); 137 } 138 139 140 skip_comment() 141 { 142 register char *s; 143 144 int st_lineno = lineno; 145 char *st_line = dup_line(); 146 char *st_cptr = st_line + (cptr - line); 147 148 s = cptr + 2; 149 for (;;) 150 { 151 if (*s == '*' && s[1] == '/') 152 { 153 cptr = s + 2; 154 FREE(st_line); 155 return; 156 } 157 if (*s == '\n') 158 { 159 get_line(); 160 if (line == 0) 161 unterminated_comment(st_lineno, st_line, st_cptr); 162 s = cptr; 163 } 164 else 165 ++s; 166 } 167 } 168 169 170 int 171 nextc() 172 { 173 register char *s; 174 175 if (line == 0) 176 { 177 get_line(); 178 if (line == 0) 179 return (EOF); 180 } 181 182 s = cptr; 183 for (;;) 184 { 185 switch (*s) 186 { 187 case '\n': 188 get_line(); 189 if (line == 0) return (EOF); 190 s = cptr; 191 break; 192 193 case ' ': 194 case '\t': 195 case '\f': 196 case '\r': 197 case '\v': 198 case ',': 199 case ';': 200 ++s; 201 break; 202 203 case '\\': 204 cptr = s; 205 return ('%'); 206 207 case '/': 208 if (s[1] == '*') 209 { 210 cptr = s; 211 skip_comment(); 212 s = cptr; 213 break; 214 } 215 else if (s[1] == '/') 216 { 217 get_line(); 218 if (line == 0) return (EOF); 219 s = cptr; 220 break; 221 } 222 /* fall through */ 223 224 default: 225 cptr = s; 226 return (*s); 227 } 228 } 229 } 230 231 232 int 233 keyword() 234 { 235 register int c; 236 char *t_cptr = cptr; 237 238 c = *++cptr; 239 if (isalpha(c)) 240 { 241 cinc = 0; 242 for (;;) 243 { 244 if (isalpha(c)) 245 { 246 if (isupper(c)) c = tolower(c); 247 cachec(c); 248 } 249 else if (isdigit(c) || c == '_' || c == '.' || c == '$') 250 cachec(c); 251 else 252 break; 253 c = *++cptr; 254 } 255 cachec(NUL); 256 257 if (strcmp(cache, "token") == 0 || strcmp(cache, "term") == 0) 258 return (TOKEN); 259 if (strcmp(cache, "type") == 0) 260 return (TYPE); 261 if (strcmp(cache, "left") == 0) 262 return (LEFT); 263 if (strcmp(cache, "right") == 0) 264 return (RIGHT); 265 if (strcmp(cache, "nonassoc") == 0 || strcmp(cache, "binary") == 0) 266 return (NONASSOC); 267 if (strcmp(cache, "start") == 0) 268 return (START); 269 if (strcmp(cache, "union") == 0) 270 return (UNION); 271 if (strcmp(cache, "ident") == 0) 272 return (IDENT); 273 } 274 else 275 { 276 ++cptr; 277 if (c == '{') 278 return (TEXT); 279 if (c == '%' || c == '\\') 280 return (MARK); 281 if (c == '<') 282 return (LEFT); 283 if (c == '>') 284 return (RIGHT); 285 if (c == '0') 286 return (TOKEN); 287 if (c == '2') 288 return (NONASSOC); 289 } 290 syntax_error(lineno, line, t_cptr); 291 /*NOTREACHED*/ 292 } 293 294 295 copy_ident() 296 { 297 register int c; 298 register FILE *f = output_file; 299 300 c = nextc(); 301 if (c == EOF) unexpected_EOF(); 302 if (c != '"') syntax_error(lineno, line, cptr); 303 ++outline; 304 fprintf(f, "#ident \""); 305 for (;;) 306 { 307 c = *++cptr; 308 if (c == '\n') 309 { 310 fprintf(f, "\"\n"); 311 return; 312 } 313 putc(c, f); 314 if (c == '"') 315 { 316 putc('\n', f); 317 ++cptr; 318 return; 319 } 320 } 321 } 322 323 324 copy_text() 325 { 326 register int c; 327 int quote; 328 register FILE *f = text_file; 329 int need_newline = 0; 330 int t_lineno = lineno; 331 char *t_line = dup_line(); 332 char *t_cptr = t_line + (cptr - line - 2); 333 334 if (*cptr == '\n') 335 { 336 get_line(); 337 if (line == 0) 338 unterminated_text(t_lineno, t_line, t_cptr); 339 } 340 if (!lflag) fprintf(f, line_format, lineno, input_file_name); 341 342 loop: 343 c = *cptr++; 344 switch (c) 345 { 346 case '\n': 347 next_line: 348 putc('\n', f); 349 need_newline = 0; 350 get_line(); 351 if (line) goto loop; 352 unterminated_text(t_lineno, t_line, t_cptr); 353 354 case '\'': 355 case '"': 356 { 357 int s_lineno = lineno; 358 char *s_line = dup_line(); 359 char *s_cptr = s_line + (cptr - line - 1); 360 361 quote = c; 362 putc(c, f); 363 for (;;) 364 { 365 c = *cptr++; 366 putc(c, f); 367 if (c == quote) 368 { 369 need_newline = 1; 370 FREE(s_line); 371 goto loop; 372 } 373 if (c == '\n') 374 unterminated_string(s_lineno, s_line, s_cptr); 375 if (c == '\\') 376 { 377 c = *cptr++; 378 putc(c, f); 379 if (c == '\n') 380 { 381 get_line(); 382 if (line == 0) 383 unterminated_string(s_lineno, s_line, s_cptr); 384 } 385 } 386 } 387 } 388 389 case '/': 390 putc(c, f); 391 need_newline = 1; 392 c = *cptr; 393 if (c == '/') 394 { 395 putc('*', f); 396 while ((c = *++cptr) != '\n') 397 { 398 if (c == '*' && cptr[1] == '/') 399 fprintf(f, "* "); 400 else 401 putc(c, f); 402 } 403 fprintf(f, "*/"); 404 goto next_line; 405 } 406 if (c == '*') 407 { 408 int c_lineno = lineno; 409 char *c_line = dup_line(); 410 char *c_cptr = c_line + (cptr - line - 1); 411 412 putc('*', f); 413 ++cptr; 414 for (;;) 415 { 416 c = *cptr++; 417 putc(c, f); 418 if (c == '*' && *cptr == '/') 419 { 420 putc('/', f); 421 ++cptr; 422 FREE(c_line); 423 goto loop; 424 } 425 if (c == '\n') 426 { 427 get_line(); 428 if (line == 0) 429 unterminated_comment(c_lineno, c_line, c_cptr); 430 } 431 } 432 } 433 need_newline = 1; 434 goto loop; 435 436 case '%': 437 case '\\': 438 if (*cptr == '}') 439 { 440 if (need_newline) putc('\n', f); 441 ++cptr; 442 FREE(t_line); 443 return; 444 } 445 /* fall through */ 446 447 default: 448 putc(c, f); 449 need_newline = 1; 450 goto loop; 451 } 452 } 453 454 455 copy_union() 456 { 457 register int c; 458 int quote; 459 int depth; 460 int u_lineno = lineno; 461 char *u_line = dup_line(); 462 char *u_cptr = u_line + (cptr - line - 6); 463 464 if (unionized) over_unionized(cptr - 6); 465 unionized = 1; 466 467 if (!lflag) 468 fprintf(text_file, line_format, lineno, input_file_name); 469 470 fprintf(text_file, "typedef union"); 471 if (dflag) fprintf(union_file, "typedef union"); 472 473 depth = 0; 474 loop: 475 c = *cptr++; 476 putc(c, text_file); 477 if (dflag) putc(c, union_file); 478 switch (c) 479 { 480 case '\n': 481 next_line: 482 get_line(); 483 if (line == 0) unterminated_union(u_lineno, u_line, u_cptr); 484 goto loop; 485 486 case '{': 487 ++depth; 488 goto loop; 489 490 case '}': 491 if (--depth == 0) 492 { 493 fprintf(text_file, " YYSTYPE;\n"); 494 FREE(u_line); 495 return; 496 } 497 goto loop; 498 499 case '\'': 500 case '"': 501 { 502 int s_lineno = lineno; 503 char *s_line = dup_line(); 504 char *s_cptr = s_line + (cptr - line - 1); 505 506 quote = c; 507 for (;;) 508 { 509 c = *cptr++; 510 putc(c, text_file); 511 if (dflag) putc(c, union_file); 512 if (c == quote) 513 { 514 FREE(s_line); 515 goto loop; 516 } 517 if (c == '\n') 518 unterminated_string(s_lineno, s_line, s_cptr); 519 if (c == '\\') 520 { 521 c = *cptr++; 522 putc(c, text_file); 523 if (dflag) putc(c, union_file); 524 if (c == '\n') 525 { 526 get_line(); 527 if (line == 0) 528 unterminated_string(s_lineno, s_line, s_cptr); 529 } 530 } 531 } 532 } 533 534 case '/': 535 c = *cptr; 536 if (c == '/') 537 { 538 putc('*', text_file); 539 if (dflag) putc('*', union_file); 540 while ((c = *++cptr) != '\n') 541 { 542 if (c == '*' && cptr[1] == '/') 543 { 544 fprintf(text_file, "* "); 545 if (dflag) fprintf(union_file, "* "); 546 } 547 else 548 { 549 putc(c, text_file); 550 if (dflag) putc(c, union_file); 551 } 552 } 553 fprintf(text_file, "*/\n"); 554 if (dflag) fprintf(union_file, "*/\n"); 555 goto next_line; 556 } 557 if (c == '*') 558 { 559 int c_lineno = lineno; 560 char *c_line = dup_line(); 561 char *c_cptr = c_line + (cptr - line - 1); 562 563 putc('*', text_file); 564 if (dflag) putc('*', union_file); 565 ++cptr; 566 for (;;) 567 { 568 c = *cptr++; 569 putc(c, text_file); 570 if (dflag) putc(c, union_file); 571 if (c == '*' && *cptr == '/') 572 { 573 putc('/', text_file); 574 if (dflag) putc('/', union_file); 575 ++cptr; 576 FREE(c_line); 577 goto loop; 578 } 579 if (c == '\n') 580 { 581 get_line(); 582 if (line == 0) 583 unterminated_comment(c_lineno, c_line, c_cptr); 584 } 585 } 586 } 587 goto loop; 588 589 default: 590 goto loop; 591 } 592 } 593 594 595 int 596 hexval(c) 597 int c; 598 { 599 if (c >= '0' && c <= '9') 600 return (c - '0'); 601 if (c >= 'A' && c <= 'F') 602 return (c - 'A' + 10); 603 if (c >= 'a' && c <= 'f') 604 return (c - 'a' + 10); 605 return (-1); 606 } 607 608 609 bucket * 610 get_literal() 611 { 612 register int c, quote; 613 register int i; 614 register int n; 615 register char *s; 616 register bucket *bp; 617 int s_lineno = lineno; 618 char *s_line = dup_line(); 619 char *s_cptr = s_line + (cptr - line); 620 621 quote = *cptr++; 622 cinc = 0; 623 for (;;) 624 { 625 c = *cptr++; 626 if (c == quote) break; 627 if (c == '\n') unterminated_string(s_lineno, s_line, s_cptr); 628 if (c == '\\') 629 { 630 char *c_cptr = cptr - 1; 631 632 c = *cptr++; 633 switch (c) 634 { 635 case '\n': 636 get_line(); 637 if (line == 0) unterminated_string(s_lineno, s_line, s_cptr); 638 continue; 639 640 case '0': case '1': case '2': case '3': 641 case '4': case '5': case '6': case '7': 642 n = c - '0'; 643 c = *cptr; 644 if (IS_OCTAL(c)) 645 { 646 n = (n << 3) + (c - '0'); 647 c = *++cptr; 648 if (IS_OCTAL(c)) 649 { 650 n = (n << 3) + (c - '0'); 651 ++cptr; 652 } 653 } 654 if (n > MAXCHAR) illegal_character(c_cptr); 655 c = n; 656 break; 657 658 case 'x': 659 c = *cptr++; 660 n = hexval(c); 661 if (n < 0 || n >= 16) 662 illegal_character(c_cptr); 663 for (;;) 664 { 665 c = *cptr; 666 i = hexval(c); 667 if (i < 0 || i >= 16) break; 668 ++cptr; 669 n = (n << 4) + i; 670 if (n > MAXCHAR) illegal_character(c_cptr); 671 } 672 c = n; 673 break; 674 675 case 'a': c = 7; break; 676 case 'b': c = '\b'; break; 677 case 'f': c = '\f'; break; 678 case 'n': c = '\n'; break; 679 case 'r': c = '\r'; break; 680 case 't': c = '\t'; break; 681 case 'v': c = '\v'; break; 682 } 683 } 684 cachec(c); 685 } 686 FREE(s_line); 687 688 n = cinc; 689 s = MALLOC(n); 690 if (s == 0) no_space(); 691 692 for (i = 0; i < n; ++i) 693 s[i] = cache[i]; 694 695 cinc = 0; 696 if (n == 1) 697 cachec('\''); 698 else 699 cachec('"'); 700 701 for (i = 0; i < n; ++i) 702 { 703 c = ((unsigned char *)s)[i]; 704 if (c == '\\' || c == cache[0]) 705 { 706 cachec('\\'); 707 cachec(c); 708 } 709 else if (isprint(c)) 710 cachec(c); 711 else 712 { 713 cachec('\\'); 714 switch (c) 715 { 716 case 7: cachec('a'); break; 717 case '\b': cachec('b'); break; 718 case '\f': cachec('f'); break; 719 case '\n': cachec('n'); break; 720 case '\r': cachec('r'); break; 721 case '\t': cachec('t'); break; 722 case '\v': cachec('v'); break; 723 default: 724 cachec(((c >> 6) & 7) + '0'); 725 cachec(((c >> 3) & 7) + '0'); 726 cachec((c & 7) + '0'); 727 break; 728 } 729 } 730 } 731 732 if (n == 1) 733 cachec('\''); 734 else 735 cachec('"'); 736 737 cachec(NUL); 738 bp = lookup(cache); 739 bp->class = TERM; 740 if (n == 1 && bp->value == UNDEFINED) 741 bp->value = *(unsigned char *)s; 742 FREE(s); 743 744 return (bp); 745 } 746 747 748 int 749 is_reserved(name) 750 char *name; 751 { 752 char *s; 753 754 if (strcmp(name, ".") == 0 || 755 strcmp(name, "$accept") == 0 || 756 strcmp(name, "$end") == 0) 757 return (1); 758 759 if (name[0] == '$' && name[1] == '$' && isdigit(name[2])) 760 { 761 s = name + 3; 762 while (isdigit(*s)) ++s; 763 if (*s == NUL) return (1); 764 } 765 766 return (0); 767 } 768 769 770 bucket * 771 get_name() 772 { 773 register int c; 774 775 cinc = 0; 776 for (c = *cptr; IS_IDENT(c); c = *++cptr) 777 cachec(c); 778 cachec(NUL); 779 780 if (is_reserved(cache)) used_reserved(cache); 781 782 return (lookup(cache)); 783 } 784 785 786 int 787 get_number() 788 { 789 register int c; 790 register int n; 791 792 n = 0; 793 for (c = *cptr; isdigit(c); c = *++cptr) 794 n = 10*n + (c - '0'); 795 796 return (n); 797 } 798 799 800 char * 801 get_tag() 802 { 803 register int c; 804 register int i; 805 register char *s; 806 int t_lineno = lineno; 807 char *t_line = dup_line(); 808 char *t_cptr = t_line + (cptr - line); 809 810 ++cptr; 811 c = nextc(); 812 if (c == EOF) unexpected_EOF(); 813 if (!isalpha(c) && c != '_' && c != '$') 814 illegal_tag(t_lineno, t_line, t_cptr); 815 816 cinc = 0; 817 do { cachec(c); c = *++cptr; } while (IS_IDENT(c)); 818 cachec(NUL); 819 820 c = nextc(); 821 if (c == EOF) unexpected_EOF(); 822 if (c != '>') 823 illegal_tag(t_lineno, t_line, t_cptr); 824 ++cptr; 825 826 for (i = 0; i < ntags; ++i) 827 { 828 if (strcmp(cache, tag_table[i]) == 0) 829 return (tag_table[i]); 830 } 831 832 if (ntags >= tagmax) 833 { 834 tagmax += 16; 835 tag_table = (char **) 836 (tag_table ? REALLOC(tag_table, tagmax*sizeof(char *)) 837 : MALLOC(tagmax*sizeof(char *))); 838 if (tag_table == 0) no_space(); 839 } 840 841 s = MALLOC(cinc); 842 if (s == 0) no_space(); 843 strcpy(s, cache); 844 tag_table[ntags] = s; 845 ++ntags; 846 FREE(t_line); 847 return (s); 848 } 849 850 851 declare_tokens(assoc) 852 int assoc; 853 { 854 register int c; 855 register bucket *bp; 856 int value; 857 char *tag = 0; 858 859 if (assoc != TOKEN) ++prec; 860 861 c = nextc(); 862 if (c == EOF) unexpected_EOF(); 863 if (c == '<') 864 { 865 tag = get_tag(); 866 c = nextc(); 867 if (c == EOF) unexpected_EOF(); 868 } 869 870 for (;;) 871 { 872 if (isalpha(c) || c == '_' || c == '.' || c == '$') 873 bp = get_name(); 874 else if (c == '\'' || c == '"') 875 bp = get_literal(); 876 else 877 return; 878 879 if (bp == goal) tokenized_start(bp->name); 880 bp->class = TERM; 881 882 if (tag) 883 { 884 if (bp->tag && tag != bp->tag) 885 retyped_warning(bp->name); 886 bp->tag = tag; 887 } 888 889 if (assoc != TOKEN) 890 { 891 if (bp->prec && prec != bp->prec) 892 reprec_warning(bp->name); 893 bp->assoc = assoc; 894 bp->prec = prec; 895 } 896 897 c = nextc(); 898 if (c == EOF) unexpected_EOF(); 899 value = UNDEFINED; 900 if (isdigit(c)) 901 { 902 value = get_number(); 903 if (bp->value != UNDEFINED && value != bp->value) 904 revalued_warning(bp->name); 905 bp->value = value; 906 c = nextc(); 907 if (c == EOF) unexpected_EOF(); 908 } 909 } 910 } 911 912 913 declare_types() 914 { 915 register int c; 916 register bucket *bp; 917 char *tag; 918 919 c = nextc(); 920 if (c == EOF) unexpected_EOF(); 921 if (c != '<') syntax_error(lineno, line, cptr); 922 tag = get_tag(); 923 924 for (;;) 925 { 926 c = nextc(); 927 if (isalpha(c) || c == '_' || c == '.' || c == '$') 928 bp = get_name(); 929 else if (c == '\'' || c == '"') 930 bp = get_literal(); 931 else 932 return; 933 934 if (bp->tag && tag != bp->tag) 935 retyped_warning(bp->name); 936 bp->tag = tag; 937 } 938 } 939 940 941 declare_start() 942 { 943 register int c; 944 register bucket *bp; 945 946 c = nextc(); 947 if (c == EOF) unexpected_EOF(); 948 if (!isalpha(c) && c != '_' && c != '.' && c != '$') 949 syntax_error(lineno, line, cptr); 950 bp = get_name(); 951 if (bp->class == TERM) 952 terminal_start(bp->name); 953 if (goal && goal != bp) 954 restarted_warning(); 955 goal = bp; 956 } 957 958 959 read_declarations() 960 { 961 register int c, k; 962 963 cache_size = 256; 964 cache = MALLOC(cache_size); 965 if (cache == 0) no_space(); 966 967 for (;;) 968 { 969 c = nextc(); 970 if (c == EOF) unexpected_EOF(); 971 if (c != '%') syntax_error(lineno, line, cptr); 972 switch (k = keyword()) 973 { 974 case MARK: 975 return; 976 977 case IDENT: 978 copy_ident(); 979 break; 980 981 case TEXT: 982 copy_text(); 983 break; 984 985 case UNION: 986 copy_union(); 987 break; 988 989 case TOKEN: 990 case LEFT: 991 case RIGHT: 992 case NONASSOC: 993 declare_tokens(k); 994 break; 995 996 case TYPE: 997 declare_types(); 998 break; 999 1000 case START: 1001 declare_start(); 1002 break; 1003 } 1004 } 1005 } 1006 1007 1008 initialize_grammar() 1009 { 1010 nitems = 4; 1011 maxitems = 300; 1012 pitem = (bucket **) MALLOC(maxitems*sizeof(bucket *)); 1013 if (pitem == 0) no_space(); 1014 pitem[0] = 0; 1015 pitem[1] = 0; 1016 pitem[2] = 0; 1017 pitem[3] = 0; 1018 1019 nrules = 3; 1020 maxrules = 100; 1021 plhs = (bucket **) MALLOC(maxrules*sizeof(bucket *)); 1022 if (plhs == 0) no_space(); 1023 plhs[0] = 0; 1024 plhs[1] = 0; 1025 plhs[2] = 0; 1026 rprec = (short *) MALLOC(maxrules*sizeof(short)); 1027 if (rprec == 0) no_space(); 1028 rprec[0] = 0; 1029 rprec[1] = 0; 1030 rprec[2] = 0; 1031 rassoc = (char *) MALLOC(maxrules*sizeof(char)); 1032 if (rassoc == 0) no_space(); 1033 rassoc[0] = TOKEN; 1034 rassoc[1] = TOKEN; 1035 rassoc[2] = TOKEN; 1036 } 1037 1038 1039 expand_items() 1040 { 1041 maxitems += 300; 1042 pitem = (bucket **) REALLOC(pitem, maxitems*sizeof(bucket *)); 1043 if (pitem == 0) no_space(); 1044 } 1045 1046 1047 expand_rules() 1048 { 1049 maxrules += 100; 1050 plhs = (bucket **) REALLOC(plhs, maxrules*sizeof(bucket *)); 1051 if (plhs == 0) no_space(); 1052 rprec = (short *) REALLOC(rprec, maxrules*sizeof(short)); 1053 if (rprec == 0) no_space(); 1054 rassoc = (char *) REALLOC(rassoc, maxrules*sizeof(char)); 1055 if (rassoc == 0) no_space(); 1056 } 1057 1058 1059 advance_to_start() 1060 { 1061 register int c; 1062 register bucket *bp; 1063 char *s_cptr; 1064 int s_lineno; 1065 1066 for (;;) 1067 { 1068 c = nextc(); 1069 if (c != '%') break; 1070 s_cptr = cptr; 1071 switch (keyword()) 1072 { 1073 case MARK: 1074 no_grammar(); 1075 1076 case TEXT: 1077 copy_text(); 1078 break; 1079 1080 case START: 1081 declare_start(); 1082 break; 1083 1084 default: 1085 syntax_error(lineno, line, s_cptr); 1086 } 1087 } 1088 1089 c = nextc(); 1090 if (!isalpha(c) && c != '_' && c != '.' && c != '_') 1091 syntax_error(lineno, line, cptr); 1092 bp = get_name(); 1093 if (goal == 0) 1094 { 1095 if (bp->class == TERM) 1096 terminal_start(bp->name); 1097 goal = bp; 1098 } 1099 1100 s_lineno = lineno; 1101 c = nextc(); 1102 if (c == EOF) unexpected_EOF(); 1103 if (c != ':') syntax_error(lineno, line, cptr); 1104 start_rule(bp, s_lineno); 1105 ++cptr; 1106 } 1107 1108 1109 start_rule(bp, s_lineno) 1110 register bucket *bp; 1111 int s_lineno; 1112 { 1113 if (bp->class == TERM) 1114 terminal_lhs(s_lineno); 1115 bp->class = NONTERM; 1116 if (nrules >= maxrules) 1117 expand_rules(); 1118 plhs[nrules] = bp; 1119 rprec[nrules] = UNDEFINED; 1120 rassoc[nrules] = TOKEN; 1121 } 1122 1123 1124 end_rule() 1125 { 1126 register int i; 1127 1128 if (!last_was_action && plhs[nrules]->tag) 1129 { 1130 for (i = nitems - 1; pitem[i]; --i) continue; 1131 if (pitem[i+1] == 0 || pitem[i+1]->tag != plhs[nrules]->tag) 1132 default_action_warning(); 1133 } 1134 1135 last_was_action = 0; 1136 if (nitems >= maxitems) expand_items(); 1137 pitem[nitems] = 0; 1138 ++nitems; 1139 ++nrules; 1140 } 1141 1142 1143 insert_empty_rule() 1144 { 1145 register bucket *bp, **bpp; 1146 1147 assert(cache); 1148 sprintf(cache, "$$%d", ++gensym); 1149 bp = make_bucket(cache); 1150 last_symbol->next = bp; 1151 last_symbol = bp; 1152 bp->tag = plhs[nrules]->tag; 1153 bp->class = NONTERM; 1154 1155 if ((nitems += 2) > maxitems) 1156 expand_items(); 1157 bpp = pitem + nitems - 1; 1158 *bpp-- = bp; 1159 while (bpp[0] = bpp[-1]) --bpp; 1160 1161 if (++nrules >= maxrules) 1162 expand_rules(); 1163 plhs[nrules] = plhs[nrules-1]; 1164 plhs[nrules-1] = bp; 1165 rprec[nrules] = rprec[nrules-1]; 1166 rprec[nrules-1] = 0; 1167 rassoc[nrules] = rassoc[nrules-1]; 1168 rassoc[nrules-1] = TOKEN; 1169 } 1170 1171 1172 add_symbol() 1173 { 1174 register int c; 1175 register bucket *bp; 1176 int s_lineno = lineno; 1177 1178 c = *cptr; 1179 if (c == '\'' || c == '"') 1180 bp = get_literal(); 1181 else 1182 bp = get_name(); 1183 1184 c = nextc(); 1185 if (c == ':') 1186 { 1187 end_rule(); 1188 start_rule(bp, s_lineno); 1189 ++cptr; 1190 return; 1191 } 1192 1193 if (last_was_action) 1194 insert_empty_rule(); 1195 last_was_action = 0; 1196 1197 if (++nitems > maxitems) 1198 expand_items(); 1199 pitem[nitems-1] = bp; 1200 } 1201 1202 1203 copy_action() 1204 { 1205 register int c; 1206 register int i, n; 1207 int depth; 1208 int quote; 1209 char *tag; 1210 register FILE *f = action_file; 1211 int a_lineno = lineno; 1212 char *a_line = dup_line(); 1213 char *a_cptr = a_line + (cptr - line); 1214 1215 if (last_was_action) 1216 insert_empty_rule(); 1217 last_was_action = 1; 1218 1219 fprintf(f, "case %d:\n", nrules - 2); 1220 if (!lflag) 1221 fprintf(f, line_format, lineno, input_file_name); 1222 if (*cptr == '=') ++cptr; 1223 1224 n = 0; 1225 for (i = nitems - 1; pitem[i]; --i) ++n; 1226 1227 depth = 0; 1228 loop: 1229 c = *cptr; 1230 if (c == '$') 1231 { 1232 if (cptr[1] == '<') 1233 { 1234 int d_lineno = lineno; 1235 char *d_line = dup_line(); 1236 char *d_cptr = d_line + (cptr - line); 1237 1238 ++cptr; 1239 tag = get_tag(); 1240 c = *cptr; 1241 if (c == '$') 1242 { 1243 fprintf(f, "yyval.%s ", tag); 1244 ++cptr; 1245 FREE(d_line); 1246 goto loop; 1247 } 1248 else if (isdigit(c)) 1249 { 1250 i = get_number(); 1251 if (i > n) dollar_warning(d_lineno, i); 1252 fprintf(f, "yyvsp[%d].%s ", i - n, tag); 1253 FREE(d_line); 1254 goto loop; 1255 } 1256 else if (c == '-' && isdigit(cptr[1])) 1257 { 1258 ++cptr; 1259 i = -get_number() - n; 1260 fprintf(f, "yyvsp[%d].%s ", i, tag); 1261 FREE(d_line); 1262 goto loop; 1263 } 1264 else 1265 dollar_error(d_lineno, d_line, d_cptr); 1266 } 1267 else if (cptr[1] == '$') 1268 { 1269 if (ntags) 1270 { 1271 tag = plhs[nrules]->tag; 1272 if (tag == 0) untyped_lhs(); 1273 fprintf(f, "yyval.%s ", tag); 1274 } 1275 else 1276 fprintf(f, "yyval "); 1277 cptr += 2; 1278 goto loop; 1279 } 1280 else if (isdigit(cptr[1])) 1281 { 1282 ++cptr; 1283 i = get_number(); 1284 if (ntags) 1285 { 1286 if (i <= 0 || i > n) 1287 unknown_rhs(i); 1288 tag = pitem[nitems + i - n - 1]->tag; 1289 if (tag == 0) untyped_rhs(i, pitem[nitems + i - n - 1]->name); 1290 fprintf(f, "yyvsp[%d].%s ", i - n, tag); 1291 } 1292 else 1293 { 1294 if (i > n) 1295 dollar_warning(lineno, i); 1296 fprintf(f, "yyvsp[%d]", i - n); 1297 } 1298 goto loop; 1299 } 1300 else if (cptr[1] == '-') 1301 { 1302 cptr += 2; 1303 i = get_number(); 1304 if (ntags) 1305 unknown_rhs(-i); 1306 fprintf(f, "yyvsp[%d]", -i - n); 1307 goto loop; 1308 } 1309 } 1310 if (isalpha(c) || c == '_' || c == '$') 1311 { 1312 do 1313 { 1314 putc(c, f); 1315 c = *++cptr; 1316 } while (isalnum(c) || c == '_' || c == '$'); 1317 goto loop; 1318 } 1319 putc(c, f); 1320 ++cptr; 1321 switch (c) 1322 { 1323 case '\n': 1324 next_line: 1325 get_line(); 1326 if (line) goto loop; 1327 unterminated_action(a_lineno, a_line, a_cptr); 1328 1329 case ';': 1330 if (depth > 0) goto loop; 1331 fprintf(f, "\nbreak;\n"); 1332 return; 1333 1334 case '{': 1335 ++depth; 1336 goto loop; 1337 1338 case '}': 1339 if (--depth > 0) goto loop; 1340 fprintf(f, "\nbreak;\n"); 1341 return; 1342 1343 case '\'': 1344 case '"': 1345 { 1346 int s_lineno = lineno; 1347 char *s_line = dup_line(); 1348 char *s_cptr = s_line + (cptr - line - 1); 1349 1350 quote = c; 1351 for (;;) 1352 { 1353 c = *cptr++; 1354 putc(c, f); 1355 if (c == quote) 1356 { 1357 FREE(s_line); 1358 goto loop; 1359 } 1360 if (c == '\n') 1361 unterminated_string(s_lineno, s_line, s_cptr); 1362 if (c == '\\') 1363 { 1364 c = *cptr++; 1365 putc(c, f); 1366 if (c == '\n') 1367 { 1368 get_line(); 1369 if (line == 0) 1370 unterminated_string(s_lineno, s_line, s_cptr); 1371 } 1372 } 1373 } 1374 } 1375 1376 case '/': 1377 c = *cptr; 1378 if (c == '/') 1379 { 1380 putc('*', f); 1381 while ((c = *++cptr) != '\n') 1382 { 1383 if (c == '*' && cptr[1] == '/') 1384 fprintf(f, "* "); 1385 else 1386 putc(c, f); 1387 } 1388 fprintf(f, "*/\n"); 1389 goto next_line; 1390 } 1391 if (c == '*') 1392 { 1393 int c_lineno = lineno; 1394 char *c_line = dup_line(); 1395 char *c_cptr = c_line + (cptr - line - 1); 1396 1397 putc('*', f); 1398 ++cptr; 1399 for (;;) 1400 { 1401 c = *cptr++; 1402 putc(c, f); 1403 if (c == '*' && *cptr == '/') 1404 { 1405 putc('/', f); 1406 ++cptr; 1407 FREE(c_line); 1408 goto loop; 1409 } 1410 if (c == '\n') 1411 { 1412 get_line(); 1413 if (line == 0) 1414 unterminated_comment(c_lineno, c_line, c_cptr); 1415 } 1416 } 1417 } 1418 goto loop; 1419 1420 default: 1421 goto loop; 1422 } 1423 } 1424 1425 1426 int 1427 mark_symbol() 1428 { 1429 register int c; 1430 register bucket *bp; 1431 1432 c = cptr[1]; 1433 if (c == '%' || c == '\\') 1434 { 1435 cptr += 2; 1436 return (1); 1437 } 1438 1439 if (c == '=') 1440 cptr += 2; 1441 else if ((c == 'p' || c == 'P') && 1442 ((c = cptr[2]) == 'r' || c == 'R') && 1443 ((c = cptr[3]) == 'e' || c == 'E') && 1444 ((c = cptr[4]) == 'c' || c == 'C') && 1445 ((c = cptr[5], !IS_IDENT(c)))) 1446 cptr += 5; 1447 else 1448 syntax_error(lineno, line, cptr); 1449 1450 c = nextc(); 1451 if (isalpha(c) || c == '_' || c == '.' || c == '$') 1452 bp = get_name(); 1453 else if (c == '\'' || c == '"') 1454 bp = get_literal(); 1455 else 1456 { 1457 syntax_error(lineno, line, cptr); 1458 /*NOTREACHED*/ 1459 } 1460 1461 if (rprec[nrules] != UNDEFINED && bp->prec != rprec[nrules]) 1462 prec_redeclared(); 1463 1464 rprec[nrules] = bp->prec; 1465 rassoc[nrules] = bp->assoc; 1466 return (0); 1467 } 1468 1469 1470 read_grammar() 1471 { 1472 register int c; 1473 1474 initialize_grammar(); 1475 advance_to_start(); 1476 1477 for (;;) 1478 { 1479 c = nextc(); 1480 if (c == EOF) break; 1481 if (isalpha(c) || c == '_' || c == '.' || c == '$' || c == '\'' || 1482 c == '"') 1483 add_symbol(); 1484 else if (c == '{' || c == '=') 1485 copy_action(); 1486 else if (c == '|') 1487 { 1488 end_rule(); 1489 start_rule(plhs[nrules-1], 0); 1490 ++cptr; 1491 } 1492 else if (c == '%') 1493 { 1494 if (mark_symbol()) break; 1495 } 1496 else 1497 syntax_error(lineno, line, cptr); 1498 } 1499 end_rule(); 1500 } 1501 1502 1503 free_tags() 1504 { 1505 register int i; 1506 1507 if (tag_table == 0) return; 1508 1509 for (i = 0; i < ntags; ++i) 1510 { 1511 assert(tag_table[i]); 1512 FREE(tag_table[i]); 1513 } 1514 FREE(tag_table); 1515 } 1516 1517 1518 pack_names() 1519 { 1520 register bucket *bp; 1521 register char *p, *s, *t; 1522 1523 name_pool_size = 13; /* 13 == sizeof("$end") + sizeof("$accept") */ 1524 for (bp = first_symbol; bp; bp = bp->next) 1525 name_pool_size += strlen(bp->name) + 1; 1526 name_pool = MALLOC(name_pool_size); 1527 if (name_pool == 0) no_space(); 1528 1529 strcpy(name_pool, "$accept"); 1530 strcpy(name_pool+8, "$end"); 1531 t = name_pool + 13; 1532 for (bp = first_symbol; bp; bp = bp->next) 1533 { 1534 p = t; 1535 s = bp->name; 1536 while (*t++ = *s++) continue; 1537 FREE(bp->name); 1538 bp->name = p; 1539 } 1540 } 1541 1542 1543 check_symbols() 1544 { 1545 register bucket *bp; 1546 1547 if (goal->class == UNKNOWN) 1548 undefined_goal(goal->name); 1549 1550 for (bp = first_symbol; bp; bp = bp->next) 1551 { 1552 if (bp->class == UNKNOWN) 1553 { 1554 undefined_symbol_warning(bp->name); 1555 bp->class = TERM; 1556 } 1557 } 1558 } 1559 1560 1561 pack_symbols() 1562 { 1563 register bucket *bp; 1564 register bucket **v; 1565 register int i, j, k, n; 1566 1567 nsyms = 2; 1568 ntokens = 1; 1569 for (bp = first_symbol; bp; bp = bp->next) 1570 { 1571 ++nsyms; 1572 if (bp->class == TERM) ++ntokens; 1573 } 1574 start_symbol = ntokens; 1575 nvars = nsyms - ntokens; 1576 1577 symbol_name = (char **) MALLOC(nsyms*sizeof(char *)); 1578 if (symbol_name == 0) no_space(); 1579 symbol_value = (short *) MALLOC(nsyms*sizeof(short)); 1580 if (symbol_value == 0) no_space(); 1581 symbol_prec = (short *) MALLOC(nsyms*sizeof(short)); 1582 if (symbol_prec == 0) no_space(); 1583 symbol_assoc = MALLOC(nsyms); 1584 if (symbol_assoc == 0) no_space(); 1585 1586 v = (bucket **) MALLOC(nsyms*sizeof(bucket *)); 1587 if (v == 0) no_space(); 1588 1589 v[0] = 0; 1590 v[start_symbol] = 0; 1591 1592 i = 1; 1593 j = start_symbol + 1; 1594 for (bp = first_symbol; bp; bp = bp->next) 1595 { 1596 if (bp->class == TERM) 1597 v[i++] = bp; 1598 else 1599 v[j++] = bp; 1600 } 1601 assert(i == ntokens && j == nsyms); 1602 1603 for (i = 1; i < ntokens; ++i) 1604 v[i]->index = i; 1605 1606 goal->index = start_symbol + 1; 1607 k = start_symbol + 2; 1608 while (++i < nsyms) 1609 if (v[i] != goal) 1610 { 1611 v[i]->index = k; 1612 ++k; 1613 } 1614 1615 goal->value = 0; 1616 k = 1; 1617 for (i = start_symbol + 1; i < nsyms; ++i) 1618 { 1619 if (v[i] != goal) 1620 { 1621 v[i]->value = k; 1622 ++k; 1623 } 1624 } 1625 1626 k = 0; 1627 for (i = 1; i < ntokens; ++i) 1628 { 1629 n = v[i]->value; 1630 if (n > 256) 1631 { 1632 for (j = k++; j > 0 && symbol_value[j-1] > n; --j) 1633 symbol_value[j] = symbol_value[j-1]; 1634 symbol_value[j] = n; 1635 } 1636 } 1637 1638 if (v[1]->value == UNDEFINED) 1639 v[1]->value = 256; 1640 1641 j = 0; 1642 n = 257; 1643 for (i = 2; i < ntokens; ++i) 1644 { 1645 if (v[i]->value == UNDEFINED) 1646 { 1647 while (j < k && n == symbol_value[j]) 1648 { 1649 while (++j < k && n == symbol_value[j]) continue; 1650 ++n; 1651 } 1652 v[i]->value = n; 1653 ++n; 1654 } 1655 } 1656 1657 symbol_name[0] = name_pool + 8; 1658 symbol_value[0] = 0; 1659 symbol_prec[0] = 0; 1660 symbol_assoc[0] = TOKEN; 1661 for (i = 1; i < ntokens; ++i) 1662 { 1663 symbol_name[i] = v[i]->name; 1664 symbol_value[i] = v[i]->value; 1665 symbol_prec[i] = v[i]->prec; 1666 symbol_assoc[i] = v[i]->assoc; 1667 } 1668 symbol_name[start_symbol] = name_pool; 1669 symbol_value[start_symbol] = -1; 1670 symbol_prec[start_symbol] = 0; 1671 symbol_assoc[start_symbol] = TOKEN; 1672 for (++i; i < nsyms; ++i) 1673 { 1674 k = v[i]->index; 1675 symbol_name[k] = v[i]->name; 1676 symbol_value[k] = v[i]->value; 1677 symbol_prec[k] = v[i]->prec; 1678 symbol_assoc[k] = v[i]->assoc; 1679 } 1680 1681 FREE(v); 1682 } 1683 1684 1685 pack_grammar() 1686 { 1687 register int i, j; 1688 int assoc, prec; 1689 1690 ritem = (short *) MALLOC(nitems*sizeof(short)); 1691 if (ritem == 0) no_space(); 1692 rlhs = (short *) MALLOC(nrules*sizeof(short)); 1693 if (rlhs == 0) no_space(); 1694 rrhs = (short *) MALLOC((nrules+1)*sizeof(short)); 1695 if (rrhs == 0) no_space(); 1696 rprec = (short *) REALLOC(rprec, nrules*sizeof(short)); 1697 if (rprec == 0) no_space(); 1698 rassoc = REALLOC(rassoc, nrules); 1699 if (rassoc == 0) no_space(); 1700 1701 ritem[0] = -1; 1702 ritem[1] = goal->index; 1703 ritem[2] = 0; 1704 ritem[3] = -2; 1705 rlhs[0] = 0; 1706 rlhs[1] = 0; 1707 rlhs[2] = start_symbol; 1708 rrhs[0] = 0; 1709 rrhs[1] = 0; 1710 rrhs[2] = 1; 1711 1712 j = 4; 1713 for (i = 3; i < nrules; ++i) 1714 { 1715 rlhs[i] = plhs[i]->index; 1716 rrhs[i] = j; 1717 assoc = TOKEN; 1718 prec = 0; 1719 while (pitem[j]) 1720 { 1721 ritem[j] = pitem[j]->index; 1722 if (pitem[j]->class == TERM) 1723 { 1724 prec = pitem[j]->prec; 1725 assoc = pitem[j]->assoc; 1726 } 1727 ++j; 1728 } 1729 ritem[j] = -i; 1730 ++j; 1731 if (rprec[i] == UNDEFINED) 1732 { 1733 rprec[i] = prec; 1734 rassoc[i] = assoc; 1735 } 1736 } 1737 rrhs[i] = j; 1738 1739 FREE(plhs); 1740 FREE(pitem); 1741 } 1742 1743 1744 print_grammar() 1745 { 1746 register int i, j, k; 1747 int spacing; 1748 register FILE *f = verbose_file; 1749 1750 if (!vflag) return; 1751 1752 k = 1; 1753 for (i = 2; i < nrules; ++i) 1754 { 1755 if (rlhs[i] != rlhs[i-1]) 1756 { 1757 if (i != 2) fprintf(f, "\n"); 1758 fprintf(f, "%4d %s :", i - 2, symbol_name[rlhs[i]]); 1759 spacing = strlen(symbol_name[rlhs[i]]) + 1; 1760 } 1761 else 1762 { 1763 fprintf(f, "%4d ", i - 2); 1764 j = spacing; 1765 while (--j >= 0) putc(' ', f); 1766 putc('|', f); 1767 } 1768 1769 while (ritem[k] >= 0) 1770 { 1771 fprintf(f, " %s", symbol_name[ritem[k]]); 1772 ++k; 1773 } 1774 ++k; 1775 putc('\n', f); 1776 } 1777 } 1778 1779 1780 reader() 1781 { 1782 write_section(banner); 1783 create_symbol_table(); 1784 read_declarations(); 1785 read_grammar(); 1786 free_symbol_table(); 1787 free_tags(); 1788 pack_names(); 1789 check_symbols(); 1790 pack_symbols(); 1791 pack_grammar(); 1792 free_symbols(); 1793 print_grammar(); 1794 } 1795